我正在尝试编写一个允许我执行以下操作的宏:FORMAT(a << "b" << c << d)
,结果将是一个字符串 - 与创建ostringstream,插入a...d
和返回相同.str()
.就像是:
string f(){ ostringstream o; o << a << "b" << c << d; return o.str() }
基本上,FORMAT(a << "b" << c << d) == f()
.
首先,我试过:
1: #define FORMAT(items) \ ((std::ostringstream&)(std::ostringstream() << items)).str()
如果第一个项目是C字符串(const char *
),它将以十六进制格式打印字符串的地址,接下来的项目将打印正常.如果第一个项目是a std::string
,则将无法编译(没有匹配的运算符<<
).
这个:
2: #define FORMAT(items) \ ((std::ostringstream&)(std::ostringstream() << 0 << '\b' << items)).str()
带给你的似乎是一个正确的输出,但0
和\b
存在当然的字符串中.
以下似乎工作,但编译警告(采取临时地址):
3: #define FORMAT(items) \ ((std::ostringstream&)(*((std::ostream*)(&std::ostringstream())) << items)).str()
有谁知道为什么1打印出c-string的地址而无法编译std::string
?1和3不是基本相同吗?
我怀疑C++ 0x可变参数模板是format(a, "b", c, d)
可行的.但现在有办法解决这个问题吗?
这是我使用的.它都适合头文件中的一个整洁的类定义.
更新:感谢litb对代码的重大改进.
// makestring.h: class MakeString { public: std::stringstream stream; operator std::string() const { return stream.str(); } templateMakeString& operator<<(T const& VAR) { stream << VAR; return *this; } };
以下是它的使用方法:
string myString = MakeString() << a << "b" << c << d;
你们几乎已经把这个钉死了.但要遵循它有点挑战.那么让我来总结一下你所说的......
这里的困难是:
我们正在玩一个临时ostringstream
对象,因此禁止使用地址.
因为它是暂时的,我们ostream
不能通过强制转换来简单地转换为对象.
构造函数[显然] str()
都是类ostringstream
方法.(是的,我们需要使用.str()
.ostringstream
直接使用对象会结束调用ios::operator void*()
,返回类似指针的好/坏值而不是字符串对象.)
operator<<(...)
作为继承ostream
方法和全局函数存在.在所有情况下,它都返回一个ostream&
引用.
这里的选择ostringstream()<<"foo"
是继承方法ostream::operator<<(void* )
和全局函数operator<<(ostream&,const char* )
.继承ostream::operator<<(void* )
胜出因为我们无法转换为ostream
对象引用来调用全局函数.[ 感谢coppro!]
所以,为了解决这个问题,我们需要:
分配一个临时的ostringstream
.
将其转换为ostream
.
附加数据.
将其转换回ostringstream
.
并调用str()
.
分配: ostringstream()
.
转换: 有几种选择.其他人建议:
ostringstream() << std::string() // Kudos to *David Norman*
ostringstream() << std::dec // Kudos to *cadabra*
或者我们可以使用:
ostringstream() . seekp( 0, ios_base::cur )
ostringstream() . write( "", 0 )
ostringstream() . flush()
ostringstream() << flush
ostringstream() << nounitbuf
ostringstream() << unitbuf
ostringstream() << noshowpos
或任何其他标准操纵器.[ #include
] 参考:请参阅本网页上的"以格式插入数据"的 1/3.
我们不能使用:
operator<<( ostringstream(), "" )
(ostream &) ostringstream()
追加: 现在直截了当.
转换回: 我们可以使用(ostringstream&)
.但是一个dynamic_cast
会更安全.在dynamic_cast
返回的不太可能的事件中NULL
(它不应该),以下.str()
将触发coredump.
调用str()
: 猜猜.
把它们放在一起.
#define FORMAT(ITEMS) \ ( ( dynamic_cast( \ ostringstream() . seekp( 0, ios_base::cur ) << ITEMS ) \ ) . str() )
参考文献:
IOstream库
ostringstream
ostream::operator<<()
键入Casting Tutorial
维基:类型铸造
.