簡體   English   中英

函數模板 - 當使用相同類型調用時,編譯器選擇具有不同參數類型的函數

[英]Function templates - compiler choosing function with different parameter types when calling with the same type

我正在玩功能模板,我偶然發現了一個奇怪的互動。

template<class T1, class T2>
void foo(T1, T1);

template<class T1, class T2>
void foo(T1, T2);

//main
foo(1,1)

這調用foo(T1,T2),我不明白為什么。 那會怎么樣? 這些函數是否相互重載,為什么編譯器會選擇具有不同參數類型的函數?

Henri Menke的帖子的第一部分解釋了這種特殊的互動


在經歷了一些混亂后,我發現了一些更奇怪的東西

#include <iostream>

template<class T1, class T2>
void foo(T1 a, T1 b)
{
    std::cout << "same\n";
}

template<class T1, class T2>
void foo(T1 a, T2 b)
{
    std::cout << "different\n";
}

int main()
{
    foo(1, 1);
    foo<int, int>(1, 1);
}

在這段代碼中我得到了一個結果

different
different

但在評論出第一個電話之后

int main()
{
    //foo(1, 1);
    foo<int, int>(1, 1);
}

結果是

same

我正在使用VS2015,如果我在Ideone中寫同樣的東西( 比如這里 ),第一個的結果是

different
same

有人能夠解釋發生了什么(或不發生了什么)?


順便說一句,我得出的結論是調用foo<int, int>(1, 1); 應該是模棱兩可的。 兩個功能模板都具有相同的簽名,並且來自同一模板。 那是另一回事,他們為什么不碰撞呢?

通過簡單地刪除第二個模板,即擁有類似的源文件,很容易看出為什么會失敗

template<class T1, class T2>
void foo(T1, T1);

int main()
{
  foo(1,1);
}

這在Clang中失敗了

test.cpp:6:3: error: no matching function for call to 'foo'
  foo(1,1);
  ^~~
test.cpp:2:6: note: candidate template ignored: couldn't infer template argument
      'T2'
void foo(T1, T1);
     ^
1 error generated.

編譯器無法推導出第二個模板參數T2


如果從第一個模板中刪除多余的T2並使用此類源文件

template<class T1>
void foo(T1, T1);

template<class T1, class T2>
void foo(T1, T2);

int main()
{
  foo(1,1);
}

編譯器將始終選擇第一個選項(如果T1T2當然是相同的),因為它更專業。

另一種選擇是給T2一個默認值。 然后第一個變體也可以從foo(1,1)實例化。

template<class T1, class T2 = void>
void foo(T1, T1);

另一個有趣的事情是:

#include <iostream>

template<class T1, class T2>
void foo(T1, T1)
{ std::cout << "First choice!\n"; }

template<class T1, class T2>
void foo(T1, T2)
{ std::cout << "Second choice!\n"; }

int main()
{
  foo<int,int>(1,1);
}

這將在運行時輸出:

First choice!

我不完全確定,但我相信這是因為在演繹的情況下(即使這里沒有執行),對於第一個變體,編譯器必須只推導出一種類型而不是兩種類型,這使得它更多專業選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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