【发布时间】:2016-07-03 06:36:37
【问题描述】:
以下代码是递归可变参数函数重载的教科书示例。在 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);
}
但是,这里稍作修改。它在模板定义中使用依赖类型,而不是直接使用模板参数:
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 按预期编译和运行,但 fails 使用 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...中那样将作用域解析运算符应用于包的每个成员是否真的有效使用参数包类型名模式? - clang 相对于标准是否正确,或者这是一个错误?第二个例子真的比第一个更模棱两可吗? (对于第一个示例,您似乎可以说单参数重载与用
RestT = <>实例化的第二个参数不明确)
【问题讨论】:
标签: c++ c++11 gcc clang language-lawyer