流从STD :: Stringstream带有空间的流



i具有此模板函数,该函数从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_SETTING [设置]为"this is a test",则将在我的get函数中返回相同的字符串。同时,我不想通过硬编码ss.str()并使用其他功能来打破模板。

您必须准确地确定想要的行为的行为。如果要提取一条线,则可以使用std::getline()。或在这种情况下,也许只是return this->m_settings[setting];

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

请注意,专业行为不会偏离主要代码的距离,因为这可能会使您的用户感到困惑(其中包括您自己!(。

这有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. 如果您有C 17,则只需使用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;
    }
    

最新更新