簡體   English   中英

遞歸調用可變參數模板函數重載時的不明確調用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM