如何避免在转换字符串令牌流时重复istringstream构造

How to avoid repeated istringstream construction when converting stream of string tokens

本文关键字:istringstream 构造 令牌 何避免 转换 字符串      更新时间:2023-10-16

我(打算)使用这个答案中的代码从CSV中读取一些内容。本质上,我得到了一个迭代器,用于连续,字符之间的字符串;但我不想把它们放在字符串向量中,而是想把这些字符串解析成(任意)类型T的元素,这来自于模板参数。所以…

template <typename T>
void foo(const std::string& line) 
{
    // ....
    std::vector<T> vec;
    using namespace boost;
    tokenizer<escaped_list_separator<char> > tk(
       line, escaped_list_separator<char>('', ',', '"'));
    for (tokenizer<escaped_list_separator<char> >::iterator i(tk.begin());
       i!=tk.end();++i) 
    {
       /* magic goes here */
    }

我可以使用istringstream`(例如这里建议的):

std::istringstream iss(*i);
T t; iss >> t;
vec.push_back(t);

但这太夸张了(我可能在这里建造了两次甚至三次)。如果C++有一个像std::to_string一样的std::from_string(),那么我就只做

vec.emplace_back(std::from_string(*i));

但这并不存在。也许是boost::lexical_cast?我真的宁愿用一些标准的东西。

我该怎么办?

使分发流static thread_local

T parse (const string& line){
  static thread_local istringstream stream;
  stream.str(""); //flush the stream
  //keep using stream
}

如果你的应用程序是单线程的,你可以放弃thread_local

另一个不涉及将流保持为函数静态的解决方案是用Parser对象包裹流,并继续使用该对象,用str 刷新其内部缓冲区

class Parser{
  std::stringstream stream;
  public:
  void parse(const std::string& data){
     stream.str("");
     // the rest
  }
}
Parser parser;
parser.parse("my,data");
parser.parse("other,data");

编辑:为了防止每个CCD_ 9类型的不稳定、将流封装在不同的函数中,制作一个助手函数,从每个线程构造一次std::istringstream

namespace detail {
istringstream& getStream(){
      static thread_local istringstream stream;
      stream.str("");
      return stream;
}
} // namespace detail
template<class T>
void parse(){
   auto& stream = detail::getStream();
   //do soemthing with stream
}