Ich habe einen Fehler beim Überladen std::wostream::operator<<()
für std::string
. Hier ist die minimale Testfall mein Problem darstellt:"no match" und "lvalue nicht binden" Fehler beim Überladen `operator <<` mit `std :: wostream` und` std :: string`
#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
Der Code kompiliert werden kann und hier ausgeführt: http://cpp.sh/9emtv
Wie man hier sehen kann, gibt es eine Überlastung für operator<<
mit std::wostream
und std::string
. Die beiden falschen Klassen sind bis auf die Deklaration und operator<<
mit FakeOstream
und sich selbst leer. Die test()
Funktion instanziieren Sie eine std::wostringstream
und füttern Sie eine std::string
. Die gefälschten Klassen und die Testfunktion befinden sich in einem Namespace.
Dieser Code ergibt die folgenden Fehler auf cpp.sh an der Linie 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)
^
Bei direkten g ++ (Version 5.3.0 von MSYS2) verwendet wird, ein no match error
auch angezeigt:
./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:
Soweit ich weiß, sind alle Teile des Beispiels notwendig, damit die Fehler erscheinen. Wenn ich den Namespace, die falschen Klassen oder nur einen der operator<<
in den falschen Klassen auskommentieren, kompiliert der Code ganz gut. Außerdem, wenn ich nur eine der gefälschten Klassen oder die Test-Funktion außerhalb des Namespace, verschieben, wird der Code auch gut kompilieren.
Zusätzlich habe ich versucht, dieses Beispiel auf clang 3.7 mit dem Compiler von http://cppreference.com zu kompilieren, und der Code scheint ohne Probleme zu kompilieren.
Gibt es ein Problem mit meinem Code oder ist das ein GCC-Fehler? Wenn dies ein GCC-Fehler ist, ist da ein Workaround?
Wenn der obere Abschnitt des Codes? – NathanOliver
Der Code wird nicht kompiliert, zumindest nicht in GCC. Die Fehler treten in der Zeile 'mystring;' auf. Ich habe die Frage bearbeitet, um diese Genauigkeit hinzuzufügen. – Basile
Sieht aus wie ein Namens-Lookup-Problem für mich, aber ich kann nicht erraten, was das richtige Verhalten ist. Das Hinzufügen von 'using :: operator <<;' zu 'test 'ist die minimale Problemumgehung, die ich gefunden habe. (Das Hinzufügen der Überladung zu 'std', um die argumentabhängige Suche zu aktivieren, macht das Problem auch weg, aber ich bin nicht sicher, wie gültig das ist.) – molbdnilo