编译以下重载<<需要什么enable_if或其他提示?
What enable_if or other hint is need for the following overloaded << to compile?
允许<lt;超负荷工作?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.rvalue]。这会导致歧义,因为St() << "s="
可以调用St::operator<<
重载或[ostream.ervalue]重载。这可以通过使St::operator<<
重载仅对lvalues有效来解决,方法是向其添加&
ref限定符:
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
基类。
这是GCC中的一个错误。相比之下,代码在clang和Visual Studio上运行得非常完美。
编辑:显然,根据标准(见评论(,GCC是正确的。
您的冲突是由于GCC在这种情况下处理右值引用的方式造成的。GCC有以下定义:
template<typename _Ostream, typename _Tp>
inline
typename enable_if<__and_<__not_<is_lvalue_reference<_Ostream>>,
__is_convertible_to_basic_ostream<_Ostream>,
__is_insertable<
__rvalue_ostream_type<_Ostream>,
const _Tp&>>::value,
__rvalue_ostream_type<_Ostream>>::type
operator<<(_Ostream&& __os, const _Tp& __x)
{ .... }
该定义将导致可转换为std::ostream
的任何右值引用的歧义。作为一种变通方法,您可以停止使用std::ostream
的右值引用,而是编写:
struct Memory_type {
std::string to_string() const
{
// Defining a variable avoids passing an rvalue references of St
St st;
return st << "s=" << s;
}
const char* s;
};
这应该适用于所有现代编译器。
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 我的简单if-else语句是如何无法访问的代码
- 如何将enable-if与模板参数和参数包一起使用
- 呼叫运营商<<临时
- 无论条件是否为true,if总是在c++中执行
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 如何删除peer if else分支中的冗长句子
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 我似乎对if/else的基本语句有问题:/
- <<操作员在下面的行中工作
- if数组上的随机数
- 将按位if条件转换为普通if条件
- If语句在c++中被忽略
- 比较if语句中的数组值和int值