我想实现一个字符串流对象,它表示某种类型的字符串流。
例如
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 中,以及我已经这样做的方式,这是在调试时转储到终端的基本内容。
撇开从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 化",因为插入返回对基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 构建)
如果您只对数值类型感兴趣,则可以使用自定义std::num_put<...>
方面来设置值的格式。但是,其他类型通常不允许您拦截处理。