2015-05-15 60 views
24

考慮this question,大約是下面的代碼編譯沒有:運營商是否應該被宣佈爲非成員非模板的朋友

std::vector<int> a, b; 
std::cout << (std::ref(a) < std::ref(b)); 

它不會編譯,因爲vector矢量comparison operators爲非成員函數模板和隱式轉換不允許考慮。但是,如果經營者,而不是寫成非成員非模板,friend功能:

template <class T, class Allocator = std::allocator<T>> 
class vector { 
    // ... 

    friend bool operator<(const vector& lhs, const vector& rhs) { 
     // impl details 
    } 
}; 

那麼這個版本的operator<會被發現ADL和被選爲最佳可行的過載,和原來的例子將編譯。鑑於此,是否有理由寧願我們目前擁有的非成員函數模板,還是應該將其視爲標準中的缺陷?

+0

'operator <<'和流在幾個地方也有類似的問題:這會帶來一些問題。我可以寫一個'template operator <<(std :: basic_ostream &,std :: basic_string &)'* without *,這取決於不止一個前向聲明(任一個)。 「Koenig運營商」至少需要其中一個(哪個?),是否需要兩者? (這是正切的,因爲它是關於兩個類型的操作符,而不是像上面那樣) – Yakk

+3

我不明白爲什麼你會寫'std :: ref(a) Columbo

+0

@Columbo它適用於'int's。此外,我不知道爲什麼你會做很多東西 - 並不意味着語言不允許。另外,這可以讓你的類使用'operator std :: string()'來比較'string's比較的東西。 – Barry

回答

1

鑑於這種情況,有沒有理由喜歡非成員函數模板 我們目前有,還是應該這被認爲是一個缺陷 標準?

原因是ADL是否可以找出正確的功能。當這樣的搜索需要從給定對象的類型中提取替換的模板參數,然後將它們多次替換爲函數模板的模板化參數時,ADL不能這樣做,因爲在一般情況下沒有理由偏好一種模板參數綁定到其他的方法。在該模板的命名空間範圍之後定義的非成員函數模板(歸因於friend)排除了這種不確定性。