我有以下类:
namespace {
class MimeLogger : public std::ostringstream
{
public:
MimeLogger()
{}
~MimeLogger()
{
LOGEVENT( logModuleWSE, logEventDebug, logMsgWSETrace1, str() );
}
};
}
当我这样做时:
MimeLogger() << "Hello " << "World";
第一个"Hello "
字符串被视为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);
在重载解析期间不考虑,因为临时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>&));
};
}
使用包含std::ostringstream
怎么样?
class MimeLogger
{
private:
std::ostringstream oss_m;
public:
MimeLogger()
{
}
~MimeLogger()
{
std::cout << __FILE__ << "(" << __LINE__ << "):" << oss_m.str() << "n";
}
template<typename Type>
MimeLogger& operator<<(const Type& t)
{
oss_m << t;
return *this;
}
};
void LogDemo()
{
MimeLogger logger;
logger << "Hello " << "World!!n";
MimeLogger() << "Hello " << "StackOverflow!!n";
}