是否可以为std :: string和std :: wstring编写一个函数?

时间:2016-03-03 09:10:34

标签: c++ string templates stl stdstring

我刚刚为std :: string编写了一个简单的实用函数。然后我注意到,如果std::stringstd::wstringstd::u32string,则该函数看起来完全相同。这里可以使用模板功能吗?我对模板不太熟悉,std::stringstd::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);
}

这是一种正确的方法吗?这个想法是否存在陷阱?我不是在谈论这个函数,而是使用模板化的类StdStringClass并调用常见的std::string函数(如查找,替换,擦除等)的一般概念。

2 个答案:

答案 0 :(得分:6)

这是一个好主意,但我会在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);
}

对于像str这样的简单名称,我也会抛弃MSDN风格的“inout”符号。程序员会猜测自己str 结果,因为它作为非const引用传递,函数返回void

另外,我将unsigned int更改为auto。返回索引时,所有标准C ++容器/字符串都返回size_tsize_t可能不是unsigned intauto将自己与正确的返回值匹配。

答案 1 :(得分:-1)

假设你的模板按预期工作(没有检查......对不起),另一种选择是将函数包装在类中,并控制你喜欢函数的类型的字符串类适用于使用构造函数。

编辑:添加说明性框架

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;
}