5

我有以下课程:

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 的情况。

4

2 回答 2

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()可能未绑定到非常量引用。成员函数重载没有这个问题,因为隐式参数的规则确实允许绑定到临时参数。

如果您可以使用支持 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>&));
    };
}
于 2012-05-16T01:07:29.233 回答
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";
}
于 2012-05-16T00:20:41.043 回答