让 << 重载工作需要什么? t.cxx 是:
#include <sstream>
#include <string>
struct St : std::ostringstream {
template<typename Tp> St& operator<<( const Tp& value ) { return *this; }
operator std::string() const { return str(); }
friend std::ostream& operator<<( std::ostream& s, const St& ss ) { return
s << ss.str(); }
};
struct Memory_type {
std::string to_string() const { return St() << "s=" << s; }
const char* s;
};
g++ t.cxx
t.cxx: In member function 'std::__cxx11::string Memory_type::to_string() const':
t.cxx:10:46: error: ambiguous overload for 'operator<<' (operand types are 'St' and 'const char [3]')
std::string to_string() const { return St() << "s=" << s; }
~~~~~^~~~~~~
t.cxx:5:28: note: candidate: St& St::operator<<(const Tp&) [with Tp = char [3]]
template<typename Tp> St& operator<<( const Tp& value ) { return *this; }
^~~~~~~~
最佳答案
问题是从 C++11 开始就有了一个 operator<<
与右值 ostream 一起使用的重载,参见 [ostream.rvalue] .这会导致歧义,因为 St() << "s="
可以调用St::operator<<
重载,或 [ostream.rvalue] 之一。这可以通过制作 St::operator<<
来解决。重载仅对左值有效,通过添加 &
它的引用限定符:
template<typename Tp> St& operator<<( const Tp& value ) &
然而,这只是揭示了一个更深层次的问题,即表达式 return St() << "s=" << s;
假设 <<
运算符将返回原始类型,而不是 std::ostream&
基类(以便它可以从 St
隐式转换为 std::string
,这似乎是一个有问题的设计)。返回派生类型不是 ostream 操作通常的工作方式。在 ostream
上的操作对象通常返回对基类的引用,而不是传递给它的派生类型。
这个问题可以通过使用左值对象来解决,而不是尝试将其全部写成右值上的单个表达式:
St st;
st << "s=" << s;
return st;
这行得通,因为 return st;
看到原始类型,而不仅仅是 ostream
基类。
关于c++ - 以下重载 << 编译需要什么 enable_if 或其他提示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51637953/