我有一个C++函数,它采用逗号分隔的字符串并拆分为一个std::vector<std::string>:
std::vector<std::string> split(const std::string& s, const std::string& delim, const bool keep_empty = true) {
std::vector<std::string> result;
if (delim.empty()) {
result.push_back(s);
return result;
}
std::string::const_iterator substart = s.begin(), subend;
while (true) {
subend = std::search(substart, s.end(), delim.begin(), delim.end());
std::string temp(substart, subend);
if (keep_empty || !temp.empty()) {
result.push_back(temp);
}
if (subend == s.end()) {
break;
}
substart = subend + delim.size();
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
但是,我真的希望能够将此函数应用于多种数据类型。例如,如果我有输入std::string:
1,2,3,4,5,6
Run Code Online (Sandbox Code Playgroud)
然后我希望函数的输出是ints的向量。我对 相当陌生C++,但我知道有一种叫做template类型的东西,对吧?是否可以将此函数创建为通用模板?还是我误解了template函数的工作原理?
您可以将模板函数声明为:
template<class ReturnType>
std::vector<ReturnType> split(const std::string&, const std::string&, const bool = true);
Run Code Online (Sandbox Code Playgroud)
然后将其专门用于您想要允许的每种向量类型:
template<>
std::vector<std::string> split(const std::string& s, const std::string& delim, const bool keep_empty) {
// normal string vector implementation
}
template<>
std::vector<int> split(const std::string& s, const std::string& delim, const bool keep_empty) {
// code for converting string to int
}
// ...
Run Code Online (Sandbox Code Playgroud)
您可以在此处阅读有关 string 到 int 的转换的信息。
然后,您需要调用split:
auto vec = split<int>("1,2,3,4", ",");
Run Code Online (Sandbox Code Playgroud)
你可以“模板化”这个函数——要启动它,你只需要在函数之前std::vector<std::string>用 'std::vector and addtemplate`替换。但是您需要注意如何将字符串放入结果向量中。在您当前的实现中,您只有
result.push_back(temp);
Run Code Online (Sandbox Code Playgroud)
因为result是字符串向量,而 temp 是字符串。在一般情况下,虽然这是不可能的,但如果您想将此函数与例如vector<int>此行一起使用,则将无法编译。然而,这个问题可以用另一个函数轻松解决 - 再次模板 - 它将字符串转换为您想要使用的任何类型split。让我们调用这个函数convert:
template<typename T> T convert(const std::string& s);
Run Code Online (Sandbox Code Playgroud)
然后您需要为您需要的任何类型提供此功能的专业化。例如:
template<> std::string convert(const std::string& s) { return s; }
template<> int convert(const std::string& s) { return std::stoi(s); }
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您不需要像其他答案所建议的那样专门化整个函数,只需要根据类型来专门化部分。应该对线路做同样的事情
result.push_back(s);
Run Code Online (Sandbox Code Playgroud)
在没有分隔符的情况下。