C++03:对于表达式MimeLogger() << "Hello "
,模板函数
template <typename charT, class traits>
std::basic_ostream<charT, traits>& std::operator<< (
std::basic_ostream<charT, traits>& os,
const char* cstr);
在重载决议期间不考虑,因为临时MimeLogger()
可能未绑定到非常量引用。成员函数重载没有这个问题,因为隐式参数的规则确实允许绑定到临时参数。
如果您可以使用支持 C++11 右值引用的编译器,这应该可以按您的预期工作,因为 C++11 库提供了额外的重载
template <typename charT, class traits, typename T>
std::basic_ostream<charT, traits>& std::operator<< (
std::basic_ostream<charT, traits>&& os,
const T& x ); // { os << x; return os; }
这允许使用临时流,<<
就好像它们不是临时的一样。
(我确实尝试了一个带有 g++ 的测试程序,并且在没有和使用 -std=c++0x 的情况下得到了不同的结果。)
如果您不能使用 C++11 友好的编译器,将其添加到的公共部分class MimeLogger
是一种解决方法,可以满足您对 C++03 的要求:
template<typename T>
MimeLogger& operator<<(const T& x)
{
static_cast<std::ostringstream&>(*this) << x;
return *this;
}
using std::ostringstream::operator<<;
using 声明确保标准库中的成员重载也可以从MimeLogger
. 特别是,如果没有它,操纵器std::endl
就不能与模板运算符一起工作,因为std::endl
它本身就是一个函数模板,而从 C++ 中期望的模板类型推导太多了。但只要我们确定不隐藏ostream
使函数操纵器工作的成员(27.7.3.6.3),一切都很好:
namespace std {
template <typename charT, class traits>
class basic_ostream : /*...*/ {
public:
basic_ostream<charT, traits>& operator<<(
basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
};
}