ostringstream 的奇怪行为
我试图想出一种巧妙的方法,将各种内容连接到函数的单个字符串参数中,而不必显式使用 ostringstream
。我想到:
#define OSS(...) \
dynamic_cast<std::ostringstream const&>(std::ostringstream() << __VA_ARGS__).str()
然而,给定:
void f( string const &s ) {
cout << s << endl;
}
int main() {
char const *const s = "hello";
f( OSS( '{' << s << '}' ) );
ostringstream oss;
oss << '{' << s << '}';
cout << oss.str() << endl;
}
它在运行时打印:
123hello}
{hello}
其中 123 是 }
的 ASCII 代码。为什么使用宏会出错?
仅供参考:我目前在 Mac OS X 上使用 g++ 4.2.1 作为 Xcode 3.x 的一部分。
我现在使用的解决方案
class string_builder {
public:
template<typename T>
string_builder& operator,( T const &t ) {
oss_ << t;
return *this;
}
operator std::string() const {
return oss_.str();
}
private:
std::ostringstream oss_;
};
#define BUILD_STRING(...) (string_builder(), __VA_ARGS__)
using namespace std;
void f( string const &s ) {
cout << s << endl;
}
int main() {
char const *const s = "hello";
f( BUILD_STRING( '{', s, '}' ) );
}
I was trying to think of a clever way to concatenate various things into a single string argument for a function without having to use an ostringstream
explicitly. I thought of:
#define OSS(...) \
dynamic_cast<std::ostringstream const&>(std::ostringstream() << __VA_ARGS__).str()
However, given:
void f( string const &s ) {
cout << s << endl;
}
int main() {
char const *const s = "hello";
f( OSS( '{' << s << '}' ) );
ostringstream oss;
oss << '{' << s << '}';
cout << oss.str() << endl;
}
it prints when run:
123hello}
{hello}
where 123 is the ASCII code for }
. Why does using the macro get it wrong?
FYI: I'm currently using g++ 4.2.1 on Mac OS X as part of Xcode 3.x.
Solution I'm now using
class string_builder {
public:
template<typename T>
string_builder& operator,( T const &t ) {
oss_ << t;
return *this;
}
operator std::string() const {
return oss_.str();
}
private:
std::ostringstream oss_;
};
#define BUILD_STRING(...) (string_builder(), __VA_ARGS__)
using namespace std;
void f( string const &s ) {
cout << s << endl;
}
int main() {
char const *const s = "hello";
f( BUILD_STRING( '{', s, '}' ) );
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
std::ostringstream()
是临时的,因此只能绑定到 const 引用。独立操作员<< (将非常量引用作为第一个参数)不被考虑,只有成员被考虑。其中对于 char 的最佳匹配是将 char 转换为 int。此问题通常发生在随后显示其地址的字符串文字上。
要解决这个问题,关键是找到一种方法来转换引用中的临时值。成员
operator<<
可以做到这一点,但只有操纵器的成员可以做到这一点,并且没有副作用,并且只有当操纵器是noop时才能使用flush。成员flush和write也是候选人。例如std::ostringstream()
is temporary which thus can be bound only to const references. Standalone operator<< (which take non const references as first argument) aren't considered and only the member one are. The best match in these for a char is converting the char to int.This problems occurs often with string literals whose address is then displayed.
To solve the problem, the trick is to find a way to transform the temporary in a reference. The member
operator<<
s do that, but only the one for manipulator does it without side effect and only if the manipulator is a noop -- flush could be used. The members flush and write are also candidates. So for instance更好的线程安全解决方案,无需涉及繁琐的宏。
对函数的原始调用是这样的:
如果调用只是这样呢:
其中
stringbuilder
实现为:Test :
输出:
在线演示:http://ideone.com/QHFf4
A better thread-safe solution without involving the cumbersome macro.
The original call to function is this:
How about if the call is just this:
where
stringbuilder
is implemented as:Test:
Output:
Online Demo : http://ideone.com/QHFf4