std::ostringstream 运算符重载搜索顺序



我有以下类:

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";
}

最新更新