c++ - 以下重载 << 编译需要什么 enable_if 或其他提示?

标签 c++

让 << 重载工作需要什么? 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/

相关文章:

c++ - 如何查找一个点是否在一组区间内?

c++ - 模板什么时候结束?

c++ - 多重继承虚拟调用歧义

c++ - 链接静态库时 undefined reference

c++ - 首先从 A 点通过最近邻点到达所有剩余点

c# - C# Action += function 的 C++ 方式?

c++ - 在 Turbo C++ 中将文本文件从一个位置移动到另一个位置

c++ - C++试图将类传递给另一个类的构造函数

c++ - makefile 一次又一次地为不同的对象选择相同的源文件

c++ - 如何在命令行中使用 addr2line