[英]Ambiguous call when recursively calling variadic template function overload
考慮這段代碼:
template<typename FirstArg>
void foo()
{
}
template<typename FirstArg, typename... RestOfArgs>
void foo()
{
foo<RestOfArgs...>();
}
int main()
{
foo<int, int, int>();
return 0;
}
由於不明確的調用foo<RestOfArgs...>();
它無法編譯當RestOfArgs
只有一個元素( {int}
)。
但這編譯沒有錯誤:
template<typename FirstArg>
void foo(FirstArg x)
{
}
template<typename FirstArg, typename... RestOfArgs>
void foo(FirstArg x, RestOfArgs... y)
{
foo(y...);
}
int main()
{
foo<int, int, int>(5, 6, 7);
return 0;
}
為什么第一種情況有歧義?
為什么在第二種情況下沒有歧義?
有很多規則可以判斷哪個模板函數更專業(根據給定的參數)。
要點
template<typename> void foo();
template<typename, typename...> void foo();
foo<int>()
模棱兩可,但不是
template<typename T> void foo(T);
template<typename T, typename... Ts> void foo(T, Ts...);
對於foo(42)
如下:
在平局的情況下,如果一個函數模板有一個尾隨參數包而另一個沒有,則具有省略參數的那個被認為比具有空參數包的那個更專業。
@ZangMingJie 的回答回答了您在代碼中觀察到的行為差異。
我發現通過以下更改更容易理解名稱解析:
template<typename FirstArg>
void foo()
{
printf("1\n");
}
template<typename FirstArg, typename SecondArg, typename... RestOfArgs>
void foo()
{
printf("2\n");
foo<SecondArg, RestOfArgs...>();
}
int main()
{
foo<int, int, int>();
return 0;
}
當使用兩個或多個模板參數時,將調用第二個函數。 當有一個模板參數時,第一個函數被調用。
為什么第一種情況有歧義?
RestOfArgs
可以為空。
所以foo<int>
可以被實例化為:
template<int>
void foo()
{
}
和
template<int,>
void foo()
{
foo<>();
}
兩者都會編譯,所以它是模棱兩可的。
實際上foo<>()
不會編譯,但是在下一次實例化時它會失敗,所以沒關系。
為什么在第二種情況下沒有歧義?
foo<int>(7)
可以實例化為:
template<int>
void foo(int 7)
{
}
和
template<int>
void foo(int 7)
{
foo();
}
但是第二個是錯誤的,因為沒有 foo 沒有參數,所以唯一的候選人是第一個,所以不會有歧義
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.