下面的代碼是一個遞歸可變參數函數過載的一個典型例子。在這兩種鐺和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
部分排序在這裏很棘手,因爲所有內容都在非推導的上下文中。 –