gpt4 book ai didi

c++ - 从可变参数模板实例化调用函数时调用意外重载

转载 作者:可可西里 更新时间:2023-11-01 16:16:16 25 4
gpt4 key购买 nike

假设以下代码:

#include <iostream>

template<typename... T>
void foo(const T &...);

template<unsigned N>
void foo(const char (&)[N])
{
std::cout << "char(&)[N]" << std::endl;
}

void foo(const char *)
{
std::cout << "const char *" << std::endl;
}

template<typename T>
void foo(const T &)
{
std::cout << "Single" << std::endl;
}

template<typename First, typename... T>
void foo(const First & first, const T &... rest)
{
std::cout << "Generic + " << sizeof...(T) << std::endl;
foo(first);
foo(rest...);
}

int main()
{
const char * c = "asdf";
char a[] = {'a', 'b', 'c', 'd'};
foo('f', c, a, 1);
foo(a);
}

The output is:

Generic + 3
Single // fine; 'f' is `char` -> generic
Generic + 2
const char * // fine; c is `const char *`
Generic + 1
const char * // (!) not fine
Single
char(&)[N] // fine; a is char[4]

最后一次通话 - foo(a) , 其中achar[4] - 调用我期待的版本 - template<unsigned N> void foo(const char (&)[N]) .但是为什么不实例化 foo 的可变参数模板?调用foo(const char (&)[N] , 但调用 foo(const char *)反而?如果没有 char 数组过载,那应该是预料之中的 - 但为什么会发生在这里?不应该const First &正确捕获数组类型?

此外,使通用可变参数版本正确处理传递给它的数组的最简单方法是什么?


正如 Matthieu M. 在评论中注意到的那样,问题可能不是由可变参数模板引起的,而是由 indirection 引起的:

#include <iostream>

template <unsigned N>
void foo(const char (&)[N])
{
std::cout << "char(&)[N]" << std::endl;
}

void foo(const char *)
{
std::cout << "const char *" << std::endl;
}

template <typename T>
void goo(T const& t) {
foo(t);
}

int main()
{
char a[] = {'a', 'b', 'c', 'd'};
foo(a);
goo(a);
}
    char(&)[N]    const char *

他还说这可能是编译器错误 - 尽管代码在 Clang 3.2 dev、G++ 4.6 和 4.7 中产生完全相同的结果。

R。 Martinho Fernandes 指出,更改 a在最后一个片段中输入 const char a[]使代码产生 const char *两次。

最佳答案

我想我可以回答第二部分:如何解决?我不确定我是否得到了正确的答案,因为在我看来,传递字符串文字的情况仍然会产生错误的结果。修复的基本思想是使用完美转发,而不是希望为 T const& 推导出正确的类型。为什么对数组使用 T const& 会导致数组衰减,不过我还没有完全弄清楚。

当然,使用 perfect forward 意味着执行它的函数是完美匹配的,并且一些特化实际上进行了一些转换,至少,添加了 const。因此,有必要使用不同的名称。总的来说,这看起来像这样:

#include <iostream>
#include <utility>

void foo()
{
}

template<unsigned N>
void special(const char (&)[N])
{
std::cout << "char(&)[" << N << "]" << '\n';
}

void special(const char *)
{
std::cout << "const char *" << '\n';
}

template<typename T>
void special(const T &)
{
std::cout << "Single" << '\n';
}

template<typename First, typename... T>
void foo(First&& first, T&&... rest)
{
std::cout << "Generic + " << sizeof...(T) << '\n';
special(std::forward<First>(first));
foo(std::forward<T>(rest)...);
}

int main()
{
char const* c("foo");
char a[] = {'a', 'b', 'c', 'd'};
foo('f', "afas", a, c, 1);
foo(a);
}

关于c++ - 从可变参数模板实例化调用函数时调用意外重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13109130/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com