简体   繁体   English

使用ostringstream的奇怪行为

[英]Odd behavior with ostringstream

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. 我试图想出一种巧妙的方法将各种事物连接成函数的单个字符串参数,而不必显式使用ostringstream 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 } . 其中123是}的ASCII码。 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. 仅供参考:我目前在Mac OS X上使用g ++ 4.2.1作为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, '}' ) );
}

std::ostringstream() is temporary which thus can be bound only to const references. std::ostringstream()是临时的,因此只能绑定到const引用。 Standalone operator<< (which take non const references as first argument) aren't considered and only the member one are. 不考虑独立运算符<<(将非const引用作为第一个参数),仅考虑成员1。 The best match in these for a char is converting the char to int. 这些对char的最佳匹配是将char转换为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. 成员operator<< s这样做,但只有操纵器的operator<<没有副作用,只有当操纵器是noop时才可以使用。 The members flush and write are also candidates. 成员刷新和写作也是候选人。 So for instance 所以举个例子

#define OSS(...) \
    dynamic_cast<std::ostringstream const&>(std::ostringstream().flush() << __VA_ARGS__).str()

A better thread-safe solution without involving the cumbersome macro. 一个更好的线程安全解决方案,不涉及繁琐的宏。

The original call to function is this: 对函数的原始调用是这样的:

f( OSS( '{' << s << '}' ) );

How about if the call is just this: 如果电话是这样的话怎么样:

 f(stringbuilder() << '{' << s << '}' ); 

where stringbuilder is implemented as: 其中stringbuilder实现为:

struct stringbuilder
{
   std::ostringstream ss;
   template<typename T>
   stringbuilder & operator << (const T &data)
   {
        ss << data;
        return *this;
   }
   operator string() { return ss.str(); }
};

void f( string const &s ) {
  cout << s << endl;
}

Test: 测试:

int main() {
  char const *const s = "hello";

  f(stringbuilder() << '{' << s << '}' );

}

Output: 输出:

{hello}

Online Demo : http://ideone.com/QHFf4 在线演示: http//ideone.com/QHFf4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM