2014-04-11 30 views
6

編譯器使用模板版本來計算t = max(a, b)max(t, c)。標準支持的任何引用是值得歡迎的。爲什麼模板版本是由編譯器在下面選擇的?

#include <iostream> 

template <typename T> 
inline T const& max (T const& a, T const& b) 
{ 
    std::cout << "template" << '\n'; 
    return a < b ? b : a; 
} 

template <typename T> 
inline T const& max (T const& a, T const& b, T const& c) 
{ 
    return max (max(a,b), c); 
} 

inline int const& max (int const& a, int const& b) 
{ 
    std::cout << "non-template" << '\n'; 
    return a <b ? b : a; 
} 

int main() 
{ 
    std::cout << max(3, 5, 7) << '\n'; 
} 

The code prints

template 
template 
7 
+1

嘗試在你的3參數'max'前向前聲明'int const&max(int const&a,int const&b)'? – Yakk

+0

@Yakk我知道這將解決問題。但我想知道這是爲什麼? – Alexander

+0

「模板」定義點之後的重載只能通過標準的ADL找到。 'int'不是用戶定義的類型,所以你的ADL不工作(我不知道非用戶定義類型ADL是如何工作的,如果它真的工作的話)。一些編譯器**咳嗽**視覺工作室**咳嗽**不正確地做到這一點(不確定2013年左右)。 – Yakk

回答

8

max()您的非模板版本的定義是不可見在調用點,它的定義之後。將該函數移動到3參數max()之上或在呼叫站點上方添加原型。

int const& max (int const& a, int const& b); 

現在在兩種情況下都選擇了非模板版本。

Live example


至於爲什麼是這樣的話,我相信§3.4.1/ 1 basic.lookup.unqual]持有的答案。

在3.4.1中列出的所有情況下,按照每個類別中列出的順序搜索範圍;只要找到名稱聲明,名稱查找就會結束。如果沒有發現聲明,該程序是格式不正確的。

注意參數相關的名稱查找不會在你的情況,因爲論點也適用於maxint,而不是用戶定義類型。只有非限定名稱查找適用,因此,如上所述,當找到第一個匹配(功能模板版本max())時,查找停止。

引用部分中的最後一句還解釋了爲什麼如果註釋掉函數模板版本max(),則代碼將無法編譯。

+0

@TonyD然而,這是正確的,因爲原始類型沒有名稱空間,所以沒有用於ADL搜索的命名空間。 – Oktalist

+0

有沒有解釋爲什麼ADL不應該適用於'int's?我猜測它不適用於其他內置類型。 –

相關問題