“压倒”ostream&运算符<<

时间:2014-01-05 00:06:49

标签: c++ stream iostream

我想实现一个stringstream对象,它表示某个类型的字符串流。

例如,

class ohtmlstringstream : public std::ostringstream {
};
ohtmlstringstream& operator <<(ohtmlstringstream& ohss, double d) {
    ohss << "<div title='double'>" << d << "</div>";
    return ohss;
}

可悲的是,这不起作用,我创建的任何ohtmlstringstream对象,我<<加倍只运行std::ostream& operator <<(std::ostream&, double)

这样做的方法是什么?看起来我不应该继承ostringstream。

我真的只想要一种干净简单的方法来“分叉”特定类型的序列化方式。很长一段时间我只想以单一方式序列化一个类型,但是现在我想为至少3种情况构建我的类型的字符串表示:在HTML(或XML)表示中,在JSON中,以及在我已经做过的方式,这是在调试时转储到终端的基本方法。

2 个答案:

答案 0 :(得分:1)

撇开源自std::ostringstream的一般智慧,也许是全球性的

template<typename T> 
ohtmlstringstream & operator <<(ohtmlstringstream& ohss, T const & t)

通过以下方式为您做到:

#include <sstream>
#include <iostream>
#include <typeinfo>

using namespace std;

class ohtmlstringstream : public ostringstream {};

template<typename T>
ohtmlstringstream & operator <<(ohtmlstringstream& ohss, T const & t)
{
    static_cast<ostringstream &>(ohss) 
        << "<div title='"
        << typeid(T).name() // For the sake of illustration
        << "'>"
        << t << 
        "</div>\n";
    return ohss;
}

// Testing ...
int main()
{
    ohtmlstringstream ohtml;
    ohtml << string("Testing") 
        << '1' << 2 << 3.0f << "4" << endl << "Bye" << endl;
    cout << ohtml.str() << endl;
    return 0;
}

输出:

<div title='Ss'>Testing</div>
<div title='c'>1</div>
<div title='i'>2</div>
<div title='f'>3</div>
<div title='A2_c'>4</div>

Bye

typeid(T).name()无疑不是T的令人满意的描述符。您 可能会将其替换为专业化的习惯,例如:

template<typename T>
std::string type_desc(T const &)
{
    return typeid(T).name();
}

适用于您需要的所有T(让自己辞去这种苦差事)。

请注意,插入操纵器(例如std::endl)会终止“html-ization”, 因为插入会返回对基础std::ostream的引用。

如果您不希望发生这种情况,您可能需要操纵器 只是要注意,但在html输出中没有采取行动。所以你可能会 添加专业化:

inline ohtmlstringstream & 
operator <<(ohtmlstringstream& ohss, ostream & (*pf)(ostream &))
{
    static_cast<ostringstream &>(ohss) 
        << "<div title='"
        << typeid(pf).name()
        << "'>"
        "</div>\n";
    return ohss;
}

通过此添加,输出变为:

<div title='Ss'>Testing</div>
<div title='c'>1</div>
<div title='i'>2</div>
<div title='f'>3</div>
<div title='A2_c'>4</div>
<div title='PFRSoS_E'></div>
<div title='A4_c'>Bye</div>
<div title='PFRSoS_E'></div>

(使用gcc 4.8.2和clang 3.3构建)

答案 1 :(得分:0)

如果您只对数字类型感兴趣,可以使用自定义std::num_put<...>构面来格式化值。但是,其他类型通常不会让您拦截处理。