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种方法:
-
就像我在评论中所说的那样,您可以专门使用函数
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; }
这种方法的弊端是它引起代码解读。
-
委派使用主要和专业超负荷的辅助功能。
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); }
-
如果您有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; }