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

时间:2012-05-15 23:24:22

标签: c++ stl overload-resolution

我有以下课程:

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"被正确传递到全局重载&lt;&lt;采用char const*

的运算符

我希望&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;运算符解决相同的重载,但这不会发生。有人可以解释,也许可以提出解决方案吗?

提前致谢。

更新

我忽略了提到我坚持使用C ++ 03,但我很高兴有些人同时介绍了C ++ 03和C ++ 11。

2 个答案:

答案 0 :(得分:7)

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()可能未绑定到非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; }

允许在<<左侧使用临时流,就好像它们不是临时的一样。

(我确实尝试过使用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>&));
    };
}

答案 1 :(得分:0)

如何使用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";
}