以下代码是递归可变参数函数重载的教科书示例。在clang和GCC中,它都会干净地编译,并main
返回36(按预期):
template <typename T>
int add(T val)
{
return val;
}
template <typename FirstTypeT, typename... RestT>
int add(FirstTypeT first_value, RestT... rest)
{
return first_value + add<RestT...>(rest...);
}
int main(void)
{
return add(12, 12, 12);
}
但是,这里稍作修改。它在模板定义中使用依赖类型,而不是直接使用template参数:
struct Foo
{
using SomeType = int;
};
template <typename T>
int add(typename T::SomeType val)
{
return val;
}
template <typename FirstT, typename... RestT>
int add(typename FirstT::SomeType first_value, typename RestT::SomeType... rest)
{
return first_value + add<RestT...>(rest...);
}
int main(void)
{
return add<Foo, Foo, Foo>(12, 12, 12);
}
它可以使用GCC 5.2进行编译和运行,但不能使用clang 3.8进行运行:
clang++ variadic.cpp -o var -std=c++11 -Wall
variadic.cpp:15:26: error: call to 'add' is ambiguous
return first_value + add<RestT...>(rest...);
^~~~~~~~~~~~~
variadic.cpp:15:26: note: in instantiation of function template specialization 'add<Foo, Foo>' requested here
return first_value + add<RestT...>(rest...);
^
variadic.cpp:20:12: note: in instantiation of function template specialization 'add<Foo, Foo, Foo>' requested here
return add<Foo, Foo, Foo>(12, 12, 12);
^
variadic.cpp:7:5: note: candidate function [with T = Foo]
int add(typename T::SomeType val)
^
variadic.cpp:13:5: note: candidate function [with FirstT = Foo, RestT = <>]
int add(typename FirstT::SomeType first_value, typename RestT::SomeType... rest)
^
1 error generated.
我的问题是双重的。
typename RestT::SomeType...
?RestT = <>
)当前的措词很清楚:部分排序期间完全忽略了参数包,因为没有参数([temp.deduct.partial] /(3.1))。[temp.func.order] / 5也给出了一个非常重要的例子,即使有可推论的模板参数也是如此-表明您的第一个例子也是模棱两可的:
[注意:由于调用上下文中的部分排序仅考虑具有显式调用参数的参数,因此将忽略某些参数(即,函数参数包,带默认参数的参数和省略号参数)。[...] [示例:
template<class T, class... U> void f(T, U ...); // #1 template<class T > void f(T ); // #2 void h(int i) { f(&i); // error: ambiguous // [...] }
但是,这不是最佳的。关于可变参数模板部分排序,存在核心问题1395:
CWG同意应接受该示例,将这种情况视为迟来的决胜局,与参数pack相比,首选省略的参数。
(第1825期提供了更完善的策略。)两种编译器都在第一种情况下实现了此规则。只有GCC才做第二个(即可以认为是领先了半步)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句