【发布时间】:2012-04-07 13:24:23
【问题描述】:
函数one() 接受一个参数包。函数 two() 接受两个。每个包都被限制在 A 和 B 类型中。为什么无法实例化two()?
template <typename T>
struct A {};
template <typename T>
struct B {};
template <typename... Ts>
void one(A<Ts> ...as) {
}
template <typename... Ts, typename... Us>
void two(A<Ts> ...as, B<Us> ...bs) {
}
int main() {
auto a = A<int>();
auto b = B<int>();
// Just fine
one();
one(a);
one(a, a);
// All errors
two();
two(a);
two(a, b);
}
尝试使用 gcc 和 clang。
sam@wish:~/x/cpp$ gcc -std=c++0x variadic_templates.cpp
variadic_templates.cpp: In function ‘int main()’:
variadic_templates.cpp:23:7: error: no matching function for call to ‘two()’
variadic_templates.cpp:23:7: note: candidate is:
variadic_templates.cpp:11:6: note: template<class ... Ts, class ... Us> void two(A<Ts>..., B<Us>...)
variadic_templates.cpp:24:8: error: no matching function for call to ‘two(A<int>&)’
variadic_templates.cpp:24:8: note: candidate is:
variadic_templates.cpp:11:6: note: template<class ... Ts, class ... Us> void two(A<Ts>..., B<Us>...)
variadic_templates.cpp:25:11: error: no matching function for call to ‘two(A<int>&, B<int>&)’
variadic_templates.cpp:25:11: note: candidate is:
variadic_templates.cpp:11:6: note: template<class ... Ts, class ... Us> void two(A<Ts>..., B<Us>...)
sam@wish:~/x/cpp$ clang -std=c++0x variadic_templates.cpp
variadic_templates.cpp:23:3: error: no matching function for call to 'two'
two();
^~~
variadic_templates.cpp:11:6: note: candidate function template not viable: requires at least 1 argument, but 0 were provided
void two(A<Ts> ...as, B<Us> ...bs) {}
^
variadic_templates.cpp:24:3: error: no matching function for call to 'two'
two(a);
^~~
variadic_templates.cpp:11:6: note: candidate function not viable: requires 0 arguments, but 1 was provided
void two(A<Ts> ...as, B<Us> ...bs) {}
^
variadic_templates.cpp:25:3: error: no matching function for call to 'two'
two(a, b);
^~~
variadic_templates.cpp:11:6: note: candidate function not viable: requires 0 arguments, but 2 were provided
void two(A<Ts> ...as, B<Us> ...bs) {}
^
3 errors generated.
【问题讨论】:
-
A<Ts> ...as-- 这作为参数是否合法? -
编译器如何知道一个包何时结束而另一个包何时开始?
-
@ildjarn:因为一个包必须有类型包装在 A 中,而另一个包必须有类型包装在 B 中。
-
委员会考虑(或至少这样做,不确定当前状态)更改有关此的规则,因此当前编译器实现在处理它们方面有所不同。例如,clang 拒绝对带有参数 > 1 的
template<class ...A,class...B>void f(A...a,B...b)的调用(因为“A...a”是非推导上下文,因为它不是最后一个函数参数包,也不能是“catch-all”-推导出为一个空包,因为它不是f的尾随模板参数包,但 GCC 接受它,给A空包列表和B所有传入参数类型。 -
在 C++14/17 中是否对此有进一步的说明?
标签: c++ c++11 variadic-templates