免责声明:我知道应该避免到字符串的隐式转换,正确的方法是Person
的op<<
重载。
考虑以下代码:
#include <string>
#include <ostream>
#include <iostream>
struct NameType {
operator std::string() { return "wobble"; }
};
struct Person {
NameType name;
};
int main() {
std::cout << std::string("bobble");
std::cout << "wibble";
Person p;
std::cout << p.name;
}
It yields the following on GCC 4.3.4
prog.cpp: In function ‘int main()’:
prog.cpp:18: error: no match for ‘operator<<’ in ‘std::cout << p.Person::name’
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:112: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:121: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:131: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:169: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:173: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:177: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:97: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:184: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:111: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:195: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:204: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:208: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:213: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:217: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:225: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:229: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:125: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>]
为什么空闲的op<<(ostream&, string const&)
没有进入重载集中?这是不是由于所需的重载是模板实例化和...ADL?
发布于 2011-09-22 02:54:57
14.8.1/4 in C++98
如果函数参数类型不包含参与模板参数推导的模板参数,则将对函数参数执行
隐式转换(第4条),以将其转换为相应函数参数的类型。
在这里,您希望实例化
template <class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&,
const basic_string<charT, traits, Allocator>&);
在不显式提供任何模板参数的情况下进行推导。因此,所有的参数都包含一个参与模板参数推导的模板参数,因此它们都不能从隐式转换中获得它的值。
发布于 2011-07-13 17:59:01
这是因为它是一个模板。
要实现这一点,您需要首先实例化模板,然后使用转换操作符。这是错误的顺序,所以它不起作用。
如果你之前在程序中使用了特定的运算符,这都无关紧要。每次使用都是单独考虑的
被视为候选的重载是那些所有模板参数都可以从std::ostream推导出来的重载,或者是那些属于该类的重载。
如果我们添加一个非模板运算符呢?
#include <string>
#include <ostream>
#include <iostream>
struct NameType {
operator std::string() { return "wobble"; }
};
struct Person {
NameType name;
};
void operator<<(std::ostream& os, const std::string& s) // ** added **
{ std::operator<<(os, s); }
int main()
{
std::cout << std::string("bobble");
std::cout << "wibble";
Person p;
std::cout << p.name;
}
现在它可以工作了,并且输出
bobblewibblewobble
发布于 2011-07-13 17:59:49
这是因为ADL中没有考虑用户定义的转换函数。ADL表示重载集包含来自定义参数的命名空间的重载函数。在这里,operator<<
的参数类型是NameType
,但在定义NameType
的名称空间中尚未定义operator << (std::ostream&, const NameType&)
。因此出现了错误,因为搜索适当的重载就在这里停止了。这就是ADL。ADL没有进一步研究NameType
的定义,以确定它是否定义了任何用户定义的转换函数。
如果您执行以下操作,您将获得the same error:
NameType name;
std::cout << name ; //error: user-defined conversion not considered.
你需要cast它:
std::cout << (std::string)name << std::endl; //ok - use std::string()
此外,您可能有多个用户定义的转换函数:
std::cout << (int)name << std::endl; //ok - use int() instead
ideone格式的输出
wobble
100
https://stackoverflow.com/questions/6677072
复制相似问题