假设以下代码:
#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);
}
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)
,在哪里a
-char[4]
调用我期待的版本 - template<unsigned N> void foo(const char (&)[N])
。但是为什么不实例化foo
call的可变参数模板foo(const char (&)[N]
,而是调用foo(const char *)
呢?如果没有 char 数组重载,那应该是可以预料的——但为什么会发生在这里?不应该const First &
正确捕获数组类型吗?
此外,使通用可变参数版本与传递给它的数组一起正常工作的最简单方法是什么?
正如Matthieu M.在评论中注意到的那样,问题可能不是由可变参数模板引起的,而是由间接引起的:
#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);
}
字符(&)[N] 常量字符 *
他还说这可能是编译器错误——尽管代码在 Clang 3.2 dev、G++ 4.6 和 4.7 中产生完全相同的结果。
R. Martinho Fernandes指出,a
在最后一个片段中更改 's 类型以const char a[]
使代码产生const char *
两次。