voi*_*ter 5 c++ stl overload-resolution
我有以下课程:
namespace {
class MimeLogger : public std::ostringstream
{
public:
MimeLogger()
{}
~MimeLogger()
{
LOGEVENT( logModuleWSE, logEventDebug, logMsgWSETrace1, str() );
}
};
}
Run Code Online (Sandbox Code Playgroud)
当我这样做:
MimeLogger() << "Hello " << "World";
Run Code Online (Sandbox Code Playgroud)
第一个"Hello "字符串被视为a void*.如果我调试代码,"Hello "则传入std::basic_ostream::operator<< (void const*)并打印为指针值,而不是字符串.第二个字符串,"World"正确地传递给全局重载的<<运算符,它接受一个char const*.
我希望<<运算符的两个用法都能解析为相同的重载,但这不会发生.有人可以解释,也许可以提出修复方案吗?
提前致谢.
我忽略了提到我坚持使用C++ 03,但我很高兴有些人同时介绍了C++ 03和C++ 11.
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);
Run Code Online (Sandbox Code Playgroud)
在重载解析期间不考虑因为临时MimeLogger()可能不绑定到非const引用.成员函数重载没有此问题,因为隐式参数的规则允许绑定到临时参数.
如果你可以使用支持C++ 11 rvalue-references的编译器,这应该按照你的意图工作,因为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; }
Run Code Online (Sandbox Code Playgroud)
允许临时流使用,<<就像它们不是临时的一样.
(我确实尝试了一个带有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<<;
Run Code Online (Sandbox Code Playgroud)
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>&));
};
}
Run Code Online (Sandbox Code Playgroud)