我有下面的C++代码,可以成功编译gcc < v5.5
#include <sstream>
namespace util
{
inline void operator << (std::stringstream& stream, const char* data)
{
data = data ? data : "(null)";
std::operator<<(stream, data);
}
}
class Record
{
public:
template<typename T>
Record& operator<<(const T& data)
{
using namespace util;
m_message << data;
// std::cout << data << std::endl;
return *this;
}
private:
std::stringstream m_message;
};
int main()
{
Record r;
std::stringstream m;
r << m; //Error after gcc5.5
r << m.str(); //Ok in both
return 0;
}
看起来将字符串流传递给字符串流不再有效。我不知道为什么
这里有一个比较的链接:https://godbolt.org/z/novWE3so8
1条答案
按热度按时间a64a0gku1#
这并不取决于gcc版本,而是取决于您正在编译的C标准版本。
你的例子在C03下编译时,使用最新的gcc版本没有问题:godbolt
之所以能编译,是因为在C++11之前没有
bool
数据类型。检查流是否有效(例如
if(stream) { /*...*/ }
)因此被强制只返回一些未指定的类似于布尔的类型:cppreference
请注意,在C11之前,转换也是隐式的,因为explicit conversion functions是在C11中添加的。
libstdc++恰好定义了转换操作符如下:GitHub
注意,这允许使用 implicit(!)从任何流到
void*
的转换。这是不幸的,因为
std::basic_ostream
提供了输出指针的重载:cppreference
因此,在您的示例中实际发生的情况是,流被隐式转换为
void*
指针,然后调用operator<<(const void*)
以输出该指针。这可能不是你想要的结果
godbolt
追加流的正确方法
C++
std::istream
s可以通过传递底层流缓冲区而不是整个流来写入std::ostreams
,例如:godbolt
所以你的例子可以这样修改: