下面的代码是一个递归可变参数函数过载的一个典型例子。在这两种铛和GCC,它编译干净,并main
返回36(如预期):是一个C++ 11 variadic函数模板重载与依赖类型模糊?
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使用铛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 = <>
实例化)
MSVC15编译两个样本。铿锵在这里很奇怪,但我没有一个标准的参考文献引用来说谁是正确的,谁是错的。 – Niall
基于这个缺陷([CWG1395](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1395)),我认为这是一个叮叮声虫。我无法找到为什么嵌入式会产生变化的任何事情。 – Niall
部分排序在这里很棘手,因为所有内容都在非推导的上下文中。 –