简体   繁体   English

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

[英]Stream extracting from std::stringstream with spaces

I have this template function that gets an element from an std::map as a string, converts it to generic T through std::stringstream operator>> and returns it. 我有这个模板函数,它以字符串的形式从std::map获取元素,然后通过std::stringstream operator>>将其转换为通用T并返回它。

However the extraction operator only extracts the first word in the stream. 但是,提取运算符仅提取流中的第一个单词。

I have tried .str() , but for a template function it won't do. 我已经尝试过.str() ,但是对于模板功能却无法做到。 I have also tried ss >> std::noskipws >> result; 我也尝试过ss >> std::noskipws >> result; but it does not seem to return valid data. 但它似乎未返回有效数据。

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;
}

My expectation is that if m_settings[setting] is "this is a test" , the same string will be returned in my get function. 我的期望是,如果m_settings [setting]为"this is a test" ,则将在我的get函数中返回相同的字符串。 And at the same time, I don't want to break the template by hardcoding ss.str() and using a different function for strings. 同时,我也不想通过对ss.str()进行硬编码ss.str()字符串使用其他函数来破坏模板。

You have to decide exactly what you want the behaviour to be for strings. 您必须准确确定想要字符串的行为。 If you want to extract a whole line, you can use std::getline() . 如果要提取整行,可以使用std::getline() Or in this case, perhaps just return this->m_settings[setting]; 或者在这种情况下,也许只return this->m_settings[setting]; .

Whatever you end up doing, the solution is to put the variant behaviour into a specialisation for get<std::string> . 无论您最终做什么,解决方案都是将变体行为归类get<std::string>特殊化

Just be careful that the specialised behaviour doesn't deviate too far from that of the primary code, because that might be confusing to your users (which includes yourself!). 请注意,专用行为与主代码的行为不会相差太远,因为这可能会使您的用户(包括您自己!)感到困惑。

Here are 3 ways: 这是3种方式:

  1. Like I said in my comment, you can specialize the function get<std::string> and call std::getline() from there. 就像我在评论中说的那样,您可以专门使用get<std::string>函数, 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; } 

    The cons of this approach is that it causes code-duplication. 这种方法的缺点是它会导致代码重复。

  2. Delegate to a helper function that uses a primary and specialized overload. 委托给使用主要和专用重载的辅助函数。

     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 you have then just use if constexpr : 如果您有则只需使用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; } 

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

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