假设我们在库中定义了全局运算符(全部在全局命名空间中)
template< class tAnyType >
SpecialStream & operator << ( SpecialStream & os, tAnyType && value )
{
return os.serialize( std::forward<tAnyType>( value ) );
}
我想为我的一门课重载/专业化(是哪一个?),例如:
SpecialStream & operator << ( SpecialStream & os, const MyClass & value )
{
return os << value.i << value.s.c_str();
}
我想要一个运算符重载,它可以与 const/non-const 左值和右值一起使用,就像库中的那个一样。
事实证明,我必须至少制作三个:
- "MyClass &" 捕获非常量左值
- "const MyClass &" 捕获 const 左值
- "MyClass &&" 捕获右值
必须为每个专业类编写三个重载似乎并不正确。我不应该能够使用“const MyClass &”(正如我们在“流”类重载<<中随处可见)或使用“MyClass &&”(应该能够捕获所有内容)捕获所有内容吗?
这是使用带有“const MyClass &”的单个运算符的尝试(不编译),对于任何类型的参数都应该没问题:
#include <iostream>
using namespace std;
//---------------------------------------
// Radically simplified code from a library, in global namespace
class SpecialStream
{
public:
template< class tAnyType >
SpecialStream & serialize( tAnyType && value )
{
cout << value; // whatever, just an example <-- line 13
return *this;
}
};
// global operator that I’d like to overload/specialize for a specific class
template< class tAnyType >
SpecialStream & operator << ( SpecialStream & os, tAnyType && value )
{
return os.serialize( forward<tAnyType>( value ) ); // <-- line 22
}
//---------------------------------------
//---------------------------------------
// code from my project
class MyClass
{
public:
int i;
string s;
};
// Global operator overload/specialization (does not work! See question below)
// Tried const MyClass &, Myclass &&, MyClass
SpecialStream & operator << ( SpecialStream & os, const MyClass & value )
{
return os << value.i << value.s.c_str();
}
int main( int argc, char ** argv )
{
SpecialStream oss;
MyClass object;
oss << object; // compiler error! <-- line 46
}
上面没有编译,因为在 oss << 对象上,编译器总是尝试使用库中的模板运算符,而不是我的。我正在使用 Visual Studio 2015(更新 3),我认为这对于 C++11 的这一部分是可以的。编译器错误是:
1>test.cpp(13): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'MyClass' (or there is no acceptable conversion)
接下来是编译器尝试过的所有二元运算符 << 的很长列表,例如:
note: could be 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_streambuf<char,std::char_traits<char>> *)'
note: or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(const void *)'
然后最后(我们看到问题是它试图实例化第 22 行而不是使用我的运算符):
1> test.cpp(13): note: while trying to match the argument list '(std::ostream, MyClass)'
1> test.cpp(22): note: see reference to function template instantiation 'SpecialStream &SpecialStream::serialize<MyClass&>(tAnyType)' being compiled
1> with
1> [
1> tAnyType=MyClass &
1> ]
1> test.cpp(46): note: see reference to function template instantiation 'SpecialStream &operator <<<MyClass&>(SpecialStream &,tAnyType)' being compiled
1> with
1> [
1> tAnyType=MyClass &
1> ]
库代码的设计是好是坏可能是一个问题,但这不是我现在要问的。正如我所说,复制我的运算符以获取(非常量) MyClass & 工作正常,但我很确定我不应该复制代码(SpecialStream 毕竟使用单个运算符完成所有操作)。
有没有办法在一个函数中做到这一点?