C ++格式的宏/内联ostringstream [英] C++ format macro / inline ostringstream
问题描述
我试图编写一个宏,它允许我做一些类似于: FORMAT(a<<b< c< d)
,结果将是一个字符串 - 与创建ostringstream一样,插入 a ... d
,并返回。 STR()
。像这样:
pre $ c $ string $
$
o<<一个< b<< c< d;
return o.str()
}
实际上, FORMAT(a <<b<< c< d)== f()
。
首先,我试过:
1:#define FORMAT(items)\
((std :: ostringstream& amp; amp; ;)(std :: ostringstream()
第一个项目是一个C字符串( const char *
),它将以十六进制打印字符串的地址,接下来的项目将打印罚款。如果第一个项是 std :: string
,它将无法编译(没有匹配的运算符<<
2:#define FORMAT( (std :: ostringstream())(std :: ostringstream()<<<<<\b'<<< items))。str()
给出了正确的输出,但是 0
和 \ b
出现在字符串当然。
以下似乎工作,但编译警告(以临时地址):
3:#define FORMAT(items)\
$有没有人知道为什么1打印C字符串的地址,并没有用
((std: :ostringstream&)(*((std :: ostream *)(& std :: ostringstream()))<<< items))。str()
std :: string
?是不是1和3基本上是相同的?我怀疑,C ++ 0x可变参数模板将使格式(a,b, c,d)
可能。但现在有没有办法解决这个问题呢? 解决方案
但是要遵循一点点挑战。所以,让我试着总结一下你所说的话...
这里的困难在于: p>
-
我们正在玩一个临时的
ostringstream
对象,因为它是一个临时的,所以我们不能通过强制转换来转换为一个ostream
对象。 -
构造函数[显然]和
str()
都是类ostringstream
方法。
(是的,我们需要使用.str()
。直接使用ostringstream
调用ios :: operator void *()
,返回一个类似于指针的好/坏值,而不是字符串对象。 b -
运算符<(lt;(...)
既作为继承的ostream
方法和全局功能。在任何情况下,它都会返回一个ostream&
引用。 > ostringstream()<<foo< / code>是继承的方法 - 分配一个临时的
ostringstream
。
- 将其转换为
ostream
。 - 附加数据。
- 将它转换回
ostringstream
。 - 并调用
str()
。 -
ostringstream()<< std :: dec //授予* cadabra *
ostream :: operator<<(void *)
运算符<<(ostream&,const char *)
。继承的 ostream ::运算符<<(void *)
胜出,因为我们不能转换为 ostream
对象引用来调用全局函数。 [b] [b] [b] [b] [b] [b] [b] [b] [b] [b] [ >所以,要解决这个问题,我们需要: 分配: ostringstream()
。
$ b
转换: 有几个选择。其他人则建议:
$ b $ li $ ostringstream()<< std :: string()//对* David Norman的赞美*
使用:
-
ostringstream()。 seekp(0,ios_base :: cur)
-
ostringstream()。 write(,0)
-
ostringstream()。 flush()
-
ostringstream()<<刷新
-
ostringstream()<<
ostringstream()<< unitbuf
ostringstream()<< noshowpos
- 或其他任何标准操纵器。 [
#include
] 参考:参见插入带格式的数据这个网页的1/3。 b
$ b我们不能使用: b
运算符<<(lttringstream(),)
(ostream&)ostringstream()
添加: 现在简单明了。
我们可以使用 code>(ostringstream&安培;)。但 dynamic_cast
会更安全。在不太可能的情况下, dynamic_cast
返回 NULL
(它不应该),下面的 .str ()
会触发coredump。 $ b
调用 str()
: 猜猜。
放在一起。
$ b
#define FORMAT(ITEMS)\
((dynamic_cast< ostringstream&>(\
ostringstream()) seekp(0,ios_base :: cur)<< ITEMS)\
).str())
参考文献: b
$ b
。
I'm trying to write a macro that would allow me to do something like: FORMAT(a << "b" << c << d)
, and the result would be a string -- the same as creating an ostringstream, inserting a...d
, and returning .str()
. Something like:
string f(){
ostringstream o;
o << a << "b" << c << d;
return o.str()
}
Essentially, FORMAT(a << "b" << c << d) == f()
.
First, I tried:
1: #define FORMAT(items) \
((std::ostringstream&)(std::ostringstream() << items)).str()
If the very first item is a C string (const char *
), it will print the address of the string in hex, and the next items will print fine. If the very first item is an std::string
, it will fail to compile (no matching operator <<
).
This:
2: #define FORMAT(items) \
((std::ostringstream&)(std::ostringstream() << 0 << '\b' << items)).str()
gives what seems like the right output, but the 0
and \b
are present in the string of course.
The following seems to work, but compiles with warnings (taking address of temporary):
3: #define FORMAT(items) \
((std::ostringstream&)(*((std::ostream*)(&std::ostringstream())) << items)).str()
Does anyone know why 1 prints the address of the c-string and fails to compile with the std::string
? Aren't 1 and 3 essentially the same?
I suspect that C++0x variadic templates will make format(a, "b", c, d)
possible. But is there a way to solve this now?
You've all pretty much nailed this already. But it's a little challenging to follow. So let me take a stab at summarizing what you've said...
That difficulties here are that:
We are playing with a temporary
ostringstream
object, so taking addresses is contra-indicated.Because it's a temporary, we cannot trivially convert to an
ostream
object through casting.Both the constructor [obviously] and
str()
are classostringstream
methods. (Yes, we need to use.str()
. Using theostringstream
object directly would wind up invokingios::operator void*()
, returning a pointer-like good/bad value and not a string object.)operator<<(...)
exists as both inheritedostream
methods and global functions. In all cases it returns anostream&
reference.The choices here for
ostringstream()<<"foo"
are the inherited methodostream::operator<<(void* )
and the global functionoperator<<(ostream&,const char* )
. The inheritedostream::operator<<(void* )
wins out because we can't convert to anostream
object reference to invoke the global function. [Kudos to coppro!]
So, to pull this off, we need to:
- Allocate a temporary
ostringstream
. - Convert it to an
ostream
. - Append data.
- Convert it back to an
ostringstream
. - And invoke
str()
.
Allocating: ostringstream()
.
Converting: There are several choices. Others have suggested:
ostringstream() << std::string() // Kudos to *David Norman*
ostringstream() << std::dec // Kudos to *cadabra*
Or we could use:
ostringstream() . seekp( 0, ios_base::cur )
ostringstream() . write( "", 0 )
ostringstream() . flush()
ostringstream() << flush
ostringstream() << nounitbuf
ostringstream() << unitbuf
ostringstream() << noshowpos
- Or any other standard manipulator. [
#include <iomanip>
] Reference: See "Insert data with format" 1/3 of the way down on this webpage.
We cannot use:
operator<<( ostringstream(), "" )
(ostream &) ostringstream()
Appending: Straightforward now.
Converting back: We could just use (ostringstream&)
. But a dynamic_cast
would be safer. In the unlikely event dynamic_cast
returned NULL
(it shouldn't), the following .str()
will trigger a coredump.
Invoking str()
: Guess.
Putting it all together.
#define FORMAT(ITEMS) \
( ( dynamic_cast<ostringstream &> ( \
ostringstream() . seekp( 0, ios_base::cur ) << ITEMS ) \
) . str() )
References:
.
这篇关于C ++格式的宏/内联ostringstream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!