[英]Why does outputting a class with a conversion operator not work for std::string?
這個工作,打印1 :
#include <iostream>
struct Int {
int i;
operator int() const noexcept {return i;}
};
int main() {
Int i;
i.i = 1;
std::cout << i;
}
但是, 這無法在GCC 4.8.1上編譯 :
#include <iostream>
#include <string>
struct String {
std::string s;
operator std::string() const {return s;}
};
int main() {
String s;
s.s = "hi";
std::cout << s;
}
以下是錯誤的相關部分:
錯誤:'operator <<'不匹配(操作數類型為'std :: ostream {aka std :: basic_ostream}'和'String')
std :: cout << s;SNIP
template std :: basic_ostream <_CharT,_Traits>&std :: operator <<(std :: basic_ostream <_CharT,_Traits>&,const std :: basic_string <_CharT,_Traits,_Alloc>&)
operator <<(basic_ostream <_CharT,_Traits>&__os,/usr/include/c++/4.8/bits/basic_string.h:2753:5:注意:模板參數扣除/替換失敗:
main.cpp:25:18:注意:'String'不是從'const std :: basic_string <_CharT,_Traits,_Alloc>'派生的
std :: cout << s;
我只使用std::cout
和std::string
,它們具有相同的模板參數。 我真的不確定為什么它不能像Int
那樣獲取隱式轉換。 為什么它適用於int
,而不是std::string
?
該運算符是一個免費的template
函數。 在對template
函數參數進行匹配時,不會檢查用戶定義的轉換,而是使用類型模式匹配(替換)。
理論上,使用std::is_convertable<>
的SFINAE重載將能夠執行您想要的操作,但是當定義了將std::string
輸出到basic_ostream<char>
operator<<
,不使用該技術。
將類輸出到basic_ostream<...>
的手動重載將解決您的問題。
我會這樣做:
struct String {
std::string s;
operator std::string() const {return s;}
friend std::ostream& operator<<( std::ostream& os, String const& self) {
return os<<self.s;
}
};
它具有不創建浪費副本的額外好處。
<<運算符似乎有一個重載池,其類型不是std :: string。 正如我通過使用clang ++編譯器看到的那樣。
編譯器執行從String到std :: string的隱式轉換,但它與任何已定義的<<運算符都不匹配。
如果為std :: string定義<<運算符,它將起作用
#include <iostream>
#include <string>
std::ostream& operator<<(std::ostream& s, const std::string& str)
{
s << str.c_str();
return s;
}
struct String {
std::string s;
operator std::string() const {return s;}
};
int main() {
String s;
s.s = "hi";
std::cout << s;
}
您可以在此處找到有關同一問題的更多詳細信息: http : //forums.codeguru.com/showthread.php?4322227-RESOLVED-Implicit-conversion-to-std-string
如一篇文章中所見;
問題是operator <<這里是一個模板,並且不能為TestClass類型進行模板實例化,因為在隱式實例化的模板的參數推導中可能沒有考慮用戶定義的轉換(至少我在第14.7節中找不到)。 1(隱式實例化)。這會導致調用“std :: cout << obj <<'\\ n';”的空重載設置,從而導致錯誤。實例化是否已經發生並不重要。候選者被選擇為完全匹配的重載集(除了數組到指針衰減和const限定 - http://groups.google.co.in/group/com...29910b6?hl=en& )。
當您提供顯式重載運算符<< with std :: string時,它是非模板並在重載集中相加,因此在執行重載解析/可調用匹配時調用隱式轉換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.