C++ format macro / inline ostringstream(C++ 格式宏/内联 ostringstream)
问题描述
我正在尝试编写一个允许我执行以下操作的宏:FORMAT(a << "b" << c << d),以及结果将是一个字符串——与创建 ostringstream、插入 a...d 并返回 .str() 相同.类似的东西:
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()
}
本质上,FORMAT(a << "b" << c << d) == f().
首先,我尝试过:
1: #define FORMAT(items)
((std::ostringstream&)(std::ostringstream() << items)).str()
如果第一项是 C 字符串(const char *),它将以十六进制打印字符串的地址,接下来的项将正常打印.如果第一项是 std::string,它将无法编译(没有匹配的运算符 <<).
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 <<).
这个:
2: #define FORMAT(items)
((std::ostringstream&)(std::ostringstream() << 0 << '' << items)).str()
给出了看似正确的输出,但 0 和 当然存在于字符串中.
gives what seems like the right output, but the 0 and 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()
有谁知道为什么 1 会打印 c 字符串的地址并且无法使用 std::string 进行编译?1 和 3 本质上不是一样的吗?
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?
我怀疑 C++0x 可变参数模板将使 format(a, "b", c, d) 成为可能.但是现在有办法解决这个问题吗?
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...
这里的困难在于:
我们正在使用一个临时的
ostringstream对象,所以取地址是禁忌的.
We are playing with a temporary
ostringstreamobject, so taking addresses is contra-indicated.
因为它是临时的,我们不能通过强制转换简单地转换为 ostream 对象.
Because it's a temporary, we cannot trivially convert to an ostream object through casting.
构造函数[显然]和str()都是ostringstream类的方法.(是的,我们需要使用 .str().直接使用 ostringstream 对象会导致调用 ios::operator void*(),返回类似指针的好/坏值而不是字符串对象.)
Both the constructor [obviously] and str() are class ostringstream methods.
(Yes, we need to use .str(). Using the ostringstream object directly would wind up invoking ios::operator void*(), returning a pointer-like good/bad value and not a string object.)
operator<<(...) 作为继承的 ostream 方法和全局函数存在.在所有情况下,它都会返回一个 ostream& 引用.
operator<<(...) exists as both inherited ostream methods and global functions. In all cases it returns an ostream& reference.
这里ostringstream()<<"foo"的选择是继承的方法ostream::operator<<(void*)和全局函数operator<<(ostream&,const char*).继承的 ostream::operator<<(void* ) 胜出,因为我们无法转换为 ostream 对象引用来调用全局函数.[感谢coppro!]
The choices here for ostringstream()<<"foo" are the inherited method ostream::operator<<(void* ) and the global function operator<<(ostream&,const char* ). The inherited ostream::operator<<(void* ) wins out because we can't convert to an ostream object reference to invoke the global function. [Kudos to coppro!]
因此,要实现这一目标,我们需要:
So, to pull this off, we need to:
- 分配一个临时的
ostringstream. - 将其转换为
ostream. - 附加数据.
- 将其转换回
ostringstream. - 并调用
str().
分配: ostringstream().
转换:有多种选择.其他人建议:
Converting: There are several choices. Others have suggested:
ostringstream() <<std::string()//感谢 *David Norman*ostringstream() <<std::dec//感谢 *cadabra*
或者我们可以使用:
ostringstream() .seekp( 0, ios_base::cur )ostringstream() .写( "", 0 )ostringstream() .冲洗()ostringstream() <<冲洗ostringstream() <<nounitbufostringstream() <<unitbufostringstream() <<noshowpos- 或任何其他标准操纵器.[
#include] 参考:请参阅本网页下方 1/3 处的按格式插入数据".
我们不能使用:
operator<<( ostringstream(), "" )(ostream &) ostringstream()
附加:现在很简单.
Appending: Straightforward now.
转换回来:我们可以只使用 (ostringstream&).但是 dynamic_cast 会更安全.在不太可能发生的事件 dynamic_cast 返回 NULL(它不应该),下面的 .str() 将触发核心转储.
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.
调用 str(): 猜.
把它们放在一起.
#define FORMAT(ITEMS)
( ( dynamic_cast<ostringstream &> (
ostringstream() . seekp( 0, ios_base::cur ) << ITEMS )
) . str() )
<小时>
参考文献:
References:
- IOstream 库
ostringstreamostream::operator<<()代码>- 类型转换教程
- 维基:类型转换
.
这篇关于C++ 格式宏/内联 ostringstream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C++ 格式宏/内联 ostringstream
基础教程推荐
- 如何通过C程序打开命令提示符Cmd 2022-12-09
- 这个宏可以转换成函数吗? 2022-01-01
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 常量变量在标题中不起作用 2021-01-01
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 我有静态或动态 boost 库吗? 2021-01-01
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
