Ana*_*and 1 c++ stream visual-studio-2010 visual-c++
以下代码给出了编译错误.谁能告诉我为什么?
class mytype {
public:
int value;
mytype(int a) {
value = a;
}
friend ostream& operator<<(ostream& stream, const mytype& a) {
stream << a.value;//works
return stream;
}
friend ostringstream& operator<<(ostringstream& stream, const mytype& a) {
stream << (a.value);//compilation error
return stream;
}
};
Run Code Online (Sandbox Code Playgroud)
错误:
错误C2027:使用未定义类型'std :: basic_ostringstream <_Elem,_Traits,_Alloc>'
在确定:
错误C2666:'operator <<':18次重载具有类似的转换
最终修复:
将构造函数声明为显式.然后在MSVC上工作.
我想知道为什么.
错误C2027:使用未定义类型'std :: basic_ostringstream <_Elem,_Traits,_Alloc>'
你需要#include <sstream>得到[i/o]stringstream班.
表单重载的问题
ostringstream& operator<<(ostringstream& stream, const mytype& a)
Run Code Online (Sandbox Code Playgroud)
是它ostringstream 完全匹配.为什么要有更准确的重载是一件坏事?从标准,§13.3.3/ 1-2:
如果对于所有参数i,ICSi(F1)不是比ICSi(F2)更差的转换序列,则可行函数F1被定义为比另一个可行函数F2更好的函数...
如果只有一个可行的函数比所有其他可行函数更好的函数,则它是由重载决策选择的函数; 否则电话会形成不良
因此,如果operator<<( ostream &, int )并且operator<<( ostringstream &, mytype const & )都是候选者stream << value,前者int完全没有转换,但后者ostringstream完全匹配.因此,对于所有论点都不能"不差",也不能选择候选人.
但是由于存在漏洞,代码是有效的.您的重载根本不是候选者,除非您在函数调用中实际使用了类型.在friend类块中声明/定义一个类时,它不会将它引入任何命名空间范围; 它只是将它与类范围相关联,如果该类类型描述了传递的参数之一,则允许找到它.
标准有关于朋友声明的说法,尽管它在另一部分(14.6.5):
朋友声明不会在任何范围内引入新名称......
因此,MSVC试图很好,并主动将您的朋友介绍到其封闭的命名空间.打击MSVC.
然而,当我试图添加一个等同于MSVC"免费"的声明时,Comeau和GCC很好地解决了由此产生的超载冲突 - 对它们进行攻击.或者是吗?事实证明,重载调用发生在文件中的早于我推荐的声明.如果我之前 移动声明class mytype {(需要向前声明mytype),那么两者都适当地抱怨模糊性.
根据标准的§3.3-3.4,在命名空间范围内声明之前使用重载似乎很好.所以GCC和Comeau实际上都在右边.声明点就在声明对象的名称之后.(最后我检查过,自引用函数声明仍然可以使GCC崩溃.)ADL在封闭类之前的某个点调用封闭命名空间中的非限定查找.(3.4.1/8最后一颗子弹,3.4.1/9,3.4.2/2a.)如果朋友没有在课前宣布,那么合法的不是候选人.(7.3.1.2/3)C++不是一门优美的语言吗?
friend ostringstream& operator<<(ostringstream& stream, const mytype& a) {
stream << (a.value);//compilation error
return stream;
}
};
ostringstream& operator<<(ostringstream& stream, const mytype& a); // <- here
Run Code Online (Sandbox Code Playgroud)
在这个宣言之后,将不可能写成int一个ostringstream.
class mytype; // <- here
// and here:
inline ostringstream& operator<<(ostringstream& stream, const mytype& a);
class mytype {
public:
Run Code Online (Sandbox Code Playgroud)
根据这一声明,这将是不可能写一int成ostringstream......包括里面的朋友的声明class mytype {}.
流类应该是无法区分的.如果你真的想确定一个给定的流是否在内存中输入一个字符串(你不应该),那么最好查看它streambuf返回的内部对象rdbuf(),它实际上执行了I/O gruntwork.如果给定a,即使是通用ostream对象也可以具有ostringstream功能stringbuf.
if ( typeid( stream.rdbuf() ) == typeid( stringbuf * ) ) {
// this is effectively a stringstream
} else {
// not a stringstream
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1508 次 |
| 最近记录: |