是否可以为 std::string 和 std::wstring 编写一个函数?
Is it possible to write one function for std::string and std::wstring?
我刚刚为 std::string 写了一个简单的实用函数。然后我注意到如果 std::string
是 std::wstring
或 std::u32string
,函数看起来完全一样。这里可以使用模板函数吗?我对模板不是很熟悉,std::string
和std::wstring
本身就是模板,这可能是个问题。
template<class StdStringClass>
inline void removeOuterWhitespace(StdStringClass & strInOut)
{
const unsigned int uiBegin = strInOut.find_first_not_of(" \t\n");
if (uiBegin == StdStringClass::npos)
{
// the whole string is whitespace
strInOut.clear();
return;
}
const unsigned int uiEnd = strInOut.find_last_not_of(" \t\n");
strInOut = strInOut.substr(uiBegin, uiEnd - uiBegin + 1);
}
这样做正确吗?这个想法有陷阱吗?我不是在谈论这个功能,而是使用模板 class StdStringClass
并调用通常的 std::string
功能,如查找、替换、擦除等的一般概念
这是个好主意,但我会在 std::basic_string
而不是通用 StdStringclass
的基础上构建模板
template<class T>
inline void removeOuterWhitespace(std::basic_string<T>& strInOut)
{
constexpr auto delim[] = {T(' '),T('\t'),T('\n'),T(0)};
const auto uiBegin = strInOut.find_first_not_of(delim);
if (uiBegin == std::basic_string<T>::npos)
{
// the whole string is whitespace
strInOut.clear();
return;
}
const auto uiEnd = strInOut.find_last_not_of(delim);
strInOut = strInOut.substr(uiBegin, uiEnd - uiBegin + 1);
}
我还会在 favro 中放弃 MSDN 风格的 "inout" 符号,使用更简单的名称,例如 str
。程序员会自己猜测 str
是 结果,因为它作为非常量引用和函数 returns void
.[=22= 传递]
还有,我把unsigned int
改成了auto
。所有标准 C++ containers/strings return size_t
当 returning 索引时。 size_t
可能不是 unsigned int
。 auto
将自身匹配到正确的 return 值。
假设您的模板按预期工作(尚未检查...抱歉),另一种选择是将函数包装在 class 中,并控制您使用的字符串类型 class希望将函数应用于使用构造函数。
编辑:添加说明性框架
EDIT2 编译的(至少用 vs2015):-)
class StringType1;
class StringTypeN;
class str {
//template function
template<class StdStringClass>
inline void removeOuterWhitespace(StdStringClass & strInOut)
{
//.
//.
//.
}
public:
//constructors
str(StringType1 &s1) { removeOuterWhitespace(s1); }
//.
//.
//.
str(StringTypeN &sN) { removeOuterWhitespace(sN); }
};
int main() {
return 0;
}
EDIT3 概念验证
#include <iostream>
class incr {
//template function
template<class incrementor>
inline void removeOuterWhitespace(incrementor & n)
{
n++;
}
public:
//constructors
incr(int &n1) { removeOuterWhitespace(n1); }
incr(double &n1) { removeOuterWhitespace(n1); }
incr(float &n1) { removeOuterWhitespace(n1); }
};
int main() {
int n1 = 1;
double n2 = 2;
float n3 = 3;
std::cout << n1 << "\t" << n2 << "\t" << n3 << std::endl;
auto test1 = incr(n1);
auto test2 = incr(n2);
auto test3 = incr(n3);
//all variables modified
std::cout << "all variables modified by constructing incr" << std::endl;
std::cout << n1 << "\t" << n2 << "\t" << n3 << std::endl;
return 0;
}
我刚刚为 std::string 写了一个简单的实用函数。然后我注意到如果 std::string
是 std::wstring
或 std::u32string
,函数看起来完全一样。这里可以使用模板函数吗?我对模板不是很熟悉,std::string
和std::wstring
本身就是模板,这可能是个问题。
template<class StdStringClass>
inline void removeOuterWhitespace(StdStringClass & strInOut)
{
const unsigned int uiBegin = strInOut.find_first_not_of(" \t\n");
if (uiBegin == StdStringClass::npos)
{
// the whole string is whitespace
strInOut.clear();
return;
}
const unsigned int uiEnd = strInOut.find_last_not_of(" \t\n");
strInOut = strInOut.substr(uiBegin, uiEnd - uiBegin + 1);
}
这样做正确吗?这个想法有陷阱吗?我不是在谈论这个功能,而是使用模板 class StdStringClass
并调用通常的 std::string
功能,如查找、替换、擦除等的一般概念
这是个好主意,但我会在 std::basic_string
而不是通用 StdStringclass
template<class T>
inline void removeOuterWhitespace(std::basic_string<T>& strInOut)
{
constexpr auto delim[] = {T(' '),T('\t'),T('\n'),T(0)};
const auto uiBegin = strInOut.find_first_not_of(delim);
if (uiBegin == std::basic_string<T>::npos)
{
// the whole string is whitespace
strInOut.clear();
return;
}
const auto uiEnd = strInOut.find_last_not_of(delim);
strInOut = strInOut.substr(uiBegin, uiEnd - uiBegin + 1);
}
我还会在 favro 中放弃 MSDN 风格的 "inout" 符号,使用更简单的名称,例如 str
。程序员会自己猜测 str
是 结果,因为它作为非常量引用和函数 returns void
.[=22= 传递]
还有,我把unsigned int
改成了auto
。所有标准 C++ containers/strings return size_t
当 returning 索引时。 size_t
可能不是 unsigned int
。 auto
将自身匹配到正确的 return 值。
假设您的模板按预期工作(尚未检查...抱歉),另一种选择是将函数包装在 class 中,并控制您使用的字符串类型 class希望将函数应用于使用构造函数。
编辑:添加说明性框架
EDIT2 编译的(至少用 vs2015):-)
class StringType1;
class StringTypeN;
class str {
//template function
template<class StdStringClass>
inline void removeOuterWhitespace(StdStringClass & strInOut)
{
//.
//.
//.
}
public:
//constructors
str(StringType1 &s1) { removeOuterWhitespace(s1); }
//.
//.
//.
str(StringTypeN &sN) { removeOuterWhitespace(sN); }
};
int main() {
return 0;
}
EDIT3 概念验证
#include <iostream>
class incr {
//template function
template<class incrementor>
inline void removeOuterWhitespace(incrementor & n)
{
n++;
}
public:
//constructors
incr(int &n1) { removeOuterWhitespace(n1); }
incr(double &n1) { removeOuterWhitespace(n1); }
incr(float &n1) { removeOuterWhitespace(n1); }
};
int main() {
int n1 = 1;
double n2 = 2;
float n3 = 3;
std::cout << n1 << "\t" << n2 << "\t" << n3 << std::endl;
auto test1 = incr(n1);
auto test2 = incr(n2);
auto test3 = incr(n3);
//all variables modified
std::cout << "all variables modified by constructing incr" << std::endl;
std::cout << n1 << "\t" << n2 << "\t" << n3 << std::endl;
return 0;
}