我正在尝试定义一个<<一组类的运算符;该集是开放的,但所有成员都有一个共同的标记基类,并且都具有成员函数std::string String() const
。基本上,我得到的是:
class Tag {};
class Obj : public Tag
{
public:
std::string String() const { return "specialized"; }
};
template <typename T>
typename std::enable_if<std::is_base_of<Tag, T>::type, std::ostream>::value& operator<<( std::ostream& dest, T const& source)
{
dest << source.String();
return dest;
}
int
main()
{
std::cout << typeid(std::enable_if<std::is_base_of<Tag, Obj>::value, std::ostream>::type).name() << std::endl;
std::string s( "generic" );
Obj e;
std::cout << e << std::endl;
std::cout << s << std::endl;
return 0;
}
这不起作用:使用g ++(版本4.8.3,使用-std=c++11
调用),我收到错误消息:
enableIf.cc: In function 'int main()':
enableIf.cc:55:18: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
std::cout << e << std::endl;
^
In file included from /usr/lib/gcc/x86_64-pc-cygwin/4.8.3/include/c++/iostream:39:0,
from enableIf.cc:8:
/usr/lib/gcc/x86_64-pc-cygwin/4.8.3/include/c++/ostream:602:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Obj]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
我无法理解,因为看不到任何右值参考;编译器似乎已经触及标准库中std::ostream&&
的泛型重载。
使用MSC(VS 2013),错误消息更详细,但它始于:
enableIf.cc(55) : error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Obj' (or there is no acceptable conversion)
然后继续在标准库中列出许多可能的函数。
(在我的实际代码中,第55行对应于行std::cout << e << std::endl;
。)
在这两种情况下,编译器似乎拒绝我的重载函数。但是,如果我注释掉<<
行,代码会编译,main
中第一行输出的值似乎是正确的(至少对于MSC- g ++的输出是So
,这应该是什么意思)。
鉴于两个编译器都同意,我认为我的代码中存在错误,但我无法弄清楚是什么。你怎么做到这一点? (FWIW:对于具有成员函数std::string Type::String() const
的所有类型生成重载的解决方案,我会同样高兴,甚至更开心。)
答案 0 :(得分:3)
我很确定你的意思是:
template <typename T> // here here
typename std::enable_if<std::is_base_of<Tag, T>::type, std::ostream>::value&
operator<<( std::ostream& dest, T const& source)
是这样的:
template <typename T>
typename std::enable_if<std::is_base_of<Tag, T>::value, std::ostream>::type&
operator<<( std::ostream& dest, T const& source)
更改后,您可以成功编译。