从带有空格的std :: stringstream中提取流

时间:2019-07-04 13:41:10

标签: c++

我有这个模板函数,它从std::map中获取一个元素作为字符串,并将其通过T转换为通用std::stringstream operator>>并返回。

但是提取运算符仅提取流中的第一个单词。

我已经尝试过.str(),但是对于模板功能却没有。我也尝试过ss >> std::noskipws >> result;,但它似乎未返回有效数据。

template<typename T>
T CConfig::get(const char *setting)
{
    std::stringstream ss;
    ss << this->m_settings[setting];
    // this->m_settings[setting] = "this is a test"

    T result;
    ss >> result;
    // result = "this"

    return result;
}

我的期望是,如果m_settings [setting]为"this is a test",则在我的get函数中将返回相同的字符串。同时,我不想通过硬编码ss.str()并对字符串使用其他函数来破坏模板。

2 个答案:

答案 0 :(得分:3)

您必须准确确定想要字符串的行为。如果要提取整行,可以使用std::getline()。或者在这种情况下,可能只是return this->m_settings[setting];

无论您最终做什么,解决方案都是将变体行为放入get<std::string>专门化中。

请小心,专用行为与主代码的行为不要偏离得太远,因为这可能会使您的用户(包括您自己!)感到困惑。

答案 1 :(得分:1)

有3种方法:

  1. 就像我在评论中说的那样,您可以专用于功能get<std::string>并从那里调用std::getline()

    template<typename T>
    T CConfig::get(const char* settings) {
      std::istringstream stream(m_settings[settings]);
      T t; assert(stream >> t);
      return t;
    }
    
    template<>
    std::string CConfig::get<std::string>(const char* settings) {
      std::istringstream stream(m_settings[settings]);
      T t; assert((std::getline(stream, t)));
      return t;
    }
    

    这种方法的缺点是会导致代码重复。

  2. 委托给使用主要和专门的重载的辅助函数。

    template<typename T>
    T CConfig::get(const char* settings) {
      T t;
      assert(
        do_get(std::istringstream(m_settings[settings]) >> std::skipws, t);
      );
      return t;
    }
    
    template<typename T>
    bool do_get(std::istringstream& stream, T& data) {
      return stream >> data;
    }
    
    template<>
    bool do_get(std::istringstream& stream, std::string& data) {
      return std::getline(stream, data);
    }
    
  3. 如果您有,则只需使用if constexpr

    template<class T>
    T CConfig::get(const char* settings) {
      T t;
      std::istringstream stream(m_settings[settings]);
      if constexpr(std::is_same_v<T, std::string>) {
        assert((std::getline(stream, t)));
      } else {
        assert(stream >> t);
      }
      return t;
    }