2017-04-06 27 views
5

下面的代碼編譯失敗ADL使用std類型無法找到經營者

namespace A { 
using C = std::vector<std::string>; 
std::ostream& operator << (std::ostream& lhs, const C& rhs) { 
    lhs << 5; 
    return lhs; 
} 
} 
int main() 
{ 
    A::C f; 
    std::cout << f; 
    return 0; 
} 

與錯誤

Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'A::C' (or there is no acceptable conversion) 

顯然它不能找到< <運營商大概是由於考慮到c是一個類來自std命名空間。有什麼方法可以確保編譯器找到這個操作符或者解決這個問題嗎?

+0

以運營商出的命名空間應該工作的。 – interjay

+0

'A :: operator <<(std :: cout,f);'但是我懷疑你在找什麼。 – DeiDei

+4

'A :: C'不是一個類型定義,它只是一個別名。該類型存在於'std'命名空間中。 –

回答

2

A::C只是一個類型別名,別名是透明的。他們不「記住」他們來自哪裏。當我們進行依賴於參數的查找並確定相關的命名空間是什麼時,我們只考慮類型的關聯命名空間 - 而不是讓我們在那裏的別名。您不能只將關聯的名稱空間添加到現有類型。 f(其類型爲std::vector<std::string>)的特定關聯名稱空間爲std,該關聯名稱空間沒有與其關聯的operator<<。由於沒有使用普通查找找到的operator<<,也沒有使用ADL發現的,所以調用失敗。

現在,我說你不能只添加關聯的名稱空間到現有的類型。但是,你當然可以只創建新類型:

namespace A { 
    struct C : std::vector<std::string> { }; 
} 

或:

namespace A { 
    // template parameters are also considered for associated namespaces 
    struct S : std::string { }; 
    using C = std::vector<S>; 
}