为什么使用转换运算符输出类不适用于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>&)
运算符<<(basic_ostream <_CharT,_Traits>&__os,
/usr/include/c++/4.8/bits/basic_string.h:2753:5:注意:模板参数扣除/替换失败:
main.cpp:25:18:note:'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?432227-RESOLVED-Implicit-conversion-to-std-string
如在一篇文章中看到的;
问题在于运算符<<这里是一个模板,因为用户定义的转换可能没有在用于隐式实例的模板的参数推导中考虑,所以对于TestClass类型可以没有模板实例化(至少我在14.7节找不到)。 1(隐式实例化),这导致了为std :: cout << obj <<' n';“调用一个空的重载集合,并因此产生错误,无论是否已经发生实例化都无关紧要。候选人被选入严格匹配的重载集(除了数组到指针衰减和常规资格 - http://groups.google.co.in/group/com...29910b6?hl=en&)。
当你使用std :: string类型提供一个显式的重载操作符<<时,它是非模板并且在重载集合中累加,因此在进行重载解析/可调用匹配时调用隐式转换。
链接地址: http://www.djcxy.com/p/73079.html上一篇: Why does outputting a class with a conversion operator not work for std::string?