【发布时间】:2016-03-29 13:54:47
【问题描述】:
在为std::string 重载std::wostream::operator<<() 时出错。
这是说明我的问题的最小测试用例:
#include <string>
#include <sstream>
inline std::wostream &operator<<(std::wostream &os, const std::string &)
{
return os;
}
class FakeOstream{};
namespace mynamespace {
class FakeClasse1 {
friend inline FakeOstream &operator<<(FakeOstream &out, const FakeClasse1 &) {
return out;
}
};
class FakeClasse2 {
friend inline FakeOstream &operator<<(FakeOstream &out, const FakeClasse2 &) {
return out;
}
};
void test()
{
auto mystring = std::string{u8"mystring"};
std::wostringstream s;
s << mystring; // The errors occur here
}
} // namespace mynamespace
代码可以在这里编译执行:http://cpp.sh/9emtv
正如您在此处看到的,operator<< 与 std::wostream 存在重载
和std::string。除了声明之外,这两个假类是空的
operator<< 和 FakeOstream 和他们自己。 test() 函数
实例化一个std::wostringstream 并提供一个std::string。假的
假类和测试函数位于命名空间中。
此代码在 cpp.sh 的 s << mystring; 行产生以下错误:
In function 'void mynamespace::test()':
25:10: error: cannot bind 'std::basic_ostream<wchar_t>' lvalue to 'std::basic_ostream<wchar_t>&&'
In file included from /usr/include/c++/4.9/istream:39:0,
from /usr/include/c++/4.9/sstream:38,
from 2:
/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = wchar_t; _Traits = std::char_traits<wchar_t>; _Tp = std::basic_string<char>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
当直接使用 g++(来自 MSYS2 的 5.3.0 版)时,no match error 也是
显示:
./tmpbug.cpp: In function 'void mynamespace::test()':
./tmpbug.cpp:25:7: error: no match for 'operator<<' (operand types are 'std::wostringstream {aka std::__cxx11::basic_ostringstream<wchar_t>}' and 'std::__cxx11::basic_string<char>')
s << mystring;
^
In file included from C:/Appli/msys64/mingw64/include/c++/5.3.0/istream:39:0,
from C:/Appli/msys64/mingw64/include/c++/5.3.0/sstream:38,
from ./tmpbug.cpp:2:
C:/Appli/msys64/mingw64/include/c++/5.3.0/ostream:628:5: note: candidate: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = wchar_t; _Traits = std::char_traits<wchar_t>; _Tp = std::__cxx11::basic_string<char>] <near match>
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
C:/Appli/msys64/mingw64/include/c++/5.3.0/ostream:628:5: note: conversion of argument 1 would be ill-formed:
./tmpbug.cpp:25:10: error: cannot bind 'std::basic_ostream<wchar_t>' lvalue to 'std::basic_ostream<wchar_t>&&'
s << mystring;
^
In file included from C:/Appli/msys64/mingw64/include/c++/5.3.0/istream:39:0,
from C:/Appli/msys64/mingw64/include/c++/5.3.0/sstream:38,
from ./tmpbug.cpp:2:
据我所知,示例的所有部分都是错误发生所必需的
出现。如果我注释掉命名空间、假类或只是其中之一
operator<< 在假类中,代码编译得很好。此外,如果我
只需将其中一个假类或测试函数移到命名空间之外,
代码也可以正常编译。
此外,我尝试使用编译器在 clang 3.7 上编译此示例 来自http://cppreference.com,代码似乎编译没有问题。
我的代码有问题还是 GCC 错误?如果这是一个 GCC 错误,是 有解决办法吗?
【问题讨论】:
-
如果上面的代码可以编译,那么什么代码会产生错误?
-
代码无法编译,至少在 GCC 上是这样。错误发生在
s << mystring;行上。我已编辑问题以添加此精度。 -
对我来说看起来像是一个名称查找问题,但我猜不出正确的行为是什么。将
using ::operator<<;添加到test是我能找到的最小解决方法。 (将重载添加到std以启用依赖于参数的查找也会使问题消失,但我不确定它的有效性。) -
谢谢,
using ::operator<<似乎工作正常 :)。不过,我想知道为什么会出现这些错误,至少想知道我是否必须提交 GCC 错误。 -
好像已经在主干上修好了。