2

我(打算)使用此答案中的代码从 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::from_string()类似的std::to_string,那么我会做

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

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

我应该怎么做?

4

1 回答 1

0

制作字符串流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");

编辑:为了防止每种T类型的实例化,将流封装在不同的函数中,创建一个辅助函数,该函数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

}
于 2016-04-12T12:23:20.180 回答