Подтвердить что ты не робот

Можно ли написать одну функцию для std::string и 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);
}

Это правильный способ сделать это? Есть ли подводные камни с этой идеей. Я не говорю об этой функции, а об общей концепции использования шаблонного класса StdStringClass и вызова обычных std::string функций, таких как find, replace, erase и т.д.

4b9b3361

Ответ 1

Это хорошая идея, но я бы построил шаблон поверх 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);
}

Я бы также ударил "inout" нотацию MSDN в favro для более простого имени, например str. программист догадается, что str является результатом, поскольку он передается как неконстантная ссылка, а функция возвращает void.

я изменил unsigned int на auto. все стандартные контейнеры/строки С++ возвращают size_t при возврате индексов. size_t может не быть unsigned int. auto соответствует самому правильному возвращаемому значению.

Ответ 2

Предполагая, что ваш шаблон работает так, как ожидалось (не проверял... извините), другой вариант заключается в том, чтобы обернуть функцию в классе и контролировать, какие типы классов строк вы хотите, чтобы функция была применена к использованию конструкторов.

EDIT: добавлена ​​иллюстративная структура

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