C++ 可以为std::string和std::wstring编写一个函数吗?

C++ 可以为std::string和std::wstring编写一个函数吗?,c++,string,templates,stl,stdstring,C++,String,Templates,Stl,Stdstring,我刚刚为std::string编写了一个简单的实用函数。然后我注意到,如果std::string是std::wstring或std::u32string,则函数看起来完全相同。这里可以使用模板函数吗?我对模板不是很熟悉,std::string和std::wstring本身就是模板,这可能是一个问题 template<class StdStringClass> inline void removeOuterWhitespace(StdStringClass & strInOut

我刚刚为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);
}
模板
内联空位移除外层空位(标准stringclass和strInOut)
{
const unsigned int uiBegin=strInOut.find_first_not_of(“\t\n”);
if(uiBegin==StdStringClass::npos)
{
//整个字符串都是空白
strInOut.clear();
返回;
}
const unsigned int uiEnd=strInOut.find_last_not_of(“\t\n”);
strInOut=strInOut.substr(uiBegin,uiEnd-uiBegin+1);
}

这样做合适吗?这种想法有缺陷吗。我说的不是这个函数,而是使用模板类
StdStringClass
并调用通常的
std::string
函数(如查找、替换、擦除等)的一般概念。这是个好主意,但我会在
std::basic_string
的基础上构建模板,而不是在general
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);
}
模板
内联void removeerwhitespace(标准::基本字符串和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::npos)
{
//整个字符串都是空白
strInOut.clear();
返回;
}
const auto uiEnd=strInOut.find_last_not_of(delim);
strInOut=strInOut.substr(uiBegin,uiEnd-uiBegin+1);
}
对于更简单的名称,如
str
,我也会放弃favro中MSDN样式的“inout”符号。程序员会猜测
str
是结果,因为它作为非常量引用传递,函数返回
void


另外,我将
unsigned int
更改为
auto
。当返回索引时,所有的标准C++容器/字符串返回<代码> siZigt < /Cord>。code>size\u t可能不是
unsigned int
<代码>自动将自身匹配到正确的返回值。

假设模板按预期工作(未选中…抱歉),另一个选项是将函数包装到类中,并使用构造函数控制要将函数应用到哪些类型的字符串类

编辑:添加了说明性框架

EDIT2编译者(至少使用vs2015):-)

class-StringType1;
StringTypeN类;
类str{
//模板函数
模板
内联空位移除外层空位(标准stringclass和strInOut)
{
//.
//.
//.
}
公众:
//建设者
str(StringType1&s1){removeOuterWhitespace(s1);}
//.
//.
//.
str(StringTypeN&sN){removeerwhitespace(sN);}
};
int main(){
返回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;
}
#包括
等级递增{
//模板函数
模板
内联void removeOuterWhitespace(增量(&n)
{
n++;
}
公众:
//建设者
incr(int&n1){移除外层空间(n1);}
增量(双&n1){移除外层空间(n1);}
增量(浮动和n1){移除外层空间(n1);}
};
int main(){
int n1=1;
双n2=2;
浮点数n3=3;

std::难道我看不出有什么特别的错误吗?对我来说,我们的模板似乎很好。使用某些特定函数没有问题。如果你给出一个在模板中没有使用函数的参数,它就不会编译。
find
replace
将需要一些技巧,因为字符类型不同。例如,函数above不适用于
std::wstring
,因为
std::wstring::find_first_not_of
不采用
const char*
,而是采用
const wchar\u t*
。对我来说似乎也没问题,除了使用
unsigned int
之外,我建议使用
typename StdStringClass::size\u type
,如果启用了c++11,则使用auto code>。@Benjamin可能搜索的字符串
“\t\n”
应该包装到
StdStringClass(“\t\n”)
,它能解决这个问题吗?@Radek:不,因为这会试图调用一个不存在于
wstring
的构造函数。请进一步详细说明并添加一些代码来说明您的答案。现在这不是一个有用的答案,因为它不能为OP问题提供一个明确的解决方案。假设我正确理解您的意思,我不知道该怎么做这将减少代码重复。在课堂上,我仍然需要为每种类型的字符串实现上述代码。我的目标是坚持干式原则。使用一个模板方法对我来说似乎更优雅。Fabian,@Revolver_Ocelot,我编辑了答案并添加了说明性代码。Fabian,是的,我知道还有一些额外的代码,但是好处是您可以获得控制权。干杯!(1)此代码不会编译(语法错误,构造函数中没有实际的函数调用)(2)这比简单地调用模板函数好多少?@Revolver\u Ocelot它是
不是
更好,它只是添加了控制权,因为无论何时您可能想要避免运行时错误。is
T(0)
应该是
T(“”)
?它应该是空终止符。再看一遍,我忘记了空格,我将添加它。答案很好。不幸的是,C++11对我来说不可用。我希望能够绕过
自动
。gcc编译器在不久前我使用
大小
时抱怨,因此我切换到
无符号int
。你可以直到用C++03来完成它。除了
constepr auto…
之外,只需编写
const T
std::basic_string::size_type
就可以了。我建议不要在这里显式地使用
basic_string
,原因很好
#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;
}