我建议使用基于命名空间的替代方案:
#include <string>
#include <algorithm>
namespace inplace {
std::string& lowercase(std::string& src) {
std::transform(src.begin(), src.end(), src.begin(), ::tolower);
return src;
}
} // namespace inplace
std::string lowercase(std::string src) {
return inplace::lowercase(src);
}
这样,函数名称相同,接口相同,但命名空间清楚地定义了您打算做什么:
int main() {
std::string a = "ThIs Is A sTrInG";
std::string b = "ThIs Is AnOtHeR sTrInG";
// it is clear that I intend to lowercase-in-place
inplace::lowercase(a);
// I can document that, in the absence of namespace, all mutations
// create a copy
auto c = lowercase(b);
std::cout << "a: " << a << "\n"
<< "b: " << b << "\n"
<< "c: " << c << "\n";
}
输出:
a: this is a string
b: ThIs Is AnOtHeR sTrInG
c: this is another string
请注意,用户无法发出指令
using namespace inplace;
因为它会导致歧义;这是编译错误的一部分:
error: call of overloaded 'lowercase(std::__cxx11::string&)' is ambiguous
auto c = lowercase(b);
^
因此,编译器将确保您必须使用 inplace 函数的完全限定名称。
以下代码显示了字符串突变及其复制副本的集合。
#include <iostream>
#include <string>
#include <algorithm>
namespace inplace {
bool is_not_space(char c) {
return not std::isspace(c);
}
inline std::string& uppercase(std::string& src) {
std::transform(src.begin(), src.end(), src.begin(), ::toupper);
return src;
}
inline std::string& lowercase(std::string& src) {
std::transform(src.begin(), src.end(), src.begin(), ::tolower);
return src;
}
// Credit for the idea of ltrim, rtrim, and trim goes to Stackoverflow
// user Evan Teran: http://stackoverflow.com/users/13430/evan-teran
inline std::string& ltrim(std::string& src) {
src.erase(src.begin(), std::find_if(src.begin(), src.end(), is_not_space));
return src;
}
inline std::string& rtrim(std::string& src) {
src.erase(std::find_if(src.rbegin(), src.rend(), is_not_space).base(), src.end());
return src;
}
inline std::string& trim(std::string& src) {
return ltrim(rtrim(src));
}
inline std::string& normalize(std::string& src) {
return lowercase(trim(src));
}
}
// The create-a-copy versions simply forward the call to the in-place
// versions after having taken their argument by value.
inline std::string lowercase(std::string src) { return inplace::lowercase(src); }
inline std::string uppercase(std::string src) { return inplace::uppercase(src); }
inline std::string ltrim(std::string src) { return inplace::ltrim(src); }
inline std::string rtrim(std::string src) { return inplace::rtrim(src); }
inline std::string trim(std::string src) { return inplace::trim(src); }
inline std::string normalize(std::string src) { return inplace::normalize(src); }
int main() {
std::string a = "ThIs Is A sTrInG";
std::string b = "ThIs Is AnOtHeR sTrInG";
// it is clear that I intend to lowercase-in-place
inplace::lowercase(a);
// I can document that, in the absence of namespace, all mutations
// create a copy
auto c = lowercase(b);
std::cout << "a: " << a << "\n"
<< "b: " << b << "\n"
<< "c: " << c << "\n";
std::string d = " I NEED to normaliZE ThIs StrINg\r\n\t\t ";
std::string e = "\t\t\n\rAnD THIS one Too \n\t\t ";
// again: transparent that I will do this in-place
inplace::normalize(d);
auto f = normalize(e);
std::cout << "-->" << d << "<--\n"
<< "-->" << e << "<--\n"
<< "-->" << f << "<--\n";
}
结果:
a: this is a string
b: ThIs Is AnOtHeR sTrInG
c: this is another string
-->i need to normalize this string<--
-->
AnD THIS one Too
<--
-->and this one too<--