Сравнение строковых типов в шаблонной функции - PullRequest
0 голосов
/ 08 апреля 2020

Я хочу написать функтор, который сравнивает строковый тип с другим. Одна сторона сравнения устанавливается один раз при инициализации и используется повторно.

В любом случае я хочу поддерживать типы std::basic_string, std::basic_string_view и char*, но другие, такие как std::byte*, а также std::array и std::vector тоже интересны.

Моя первая реализация выглядит так:

template<typename StringType>
class StrcmpAlgorithm {

    StringType pattern;

  public:
    StrcmpAlgorithm(const StringType& p) : pattern(p) {}

    template<typename InputString>
    bool operator()(const InputString& input)
    {
        return input == pattern;
    }
};

Однако это решение довольно ограничено, так как использование операторов равенства равно типы, которые я могу использовать и даже могу делать не так (например, при сравнении со строкой C).

Я не совсем уверен, как мне следует подходить к этому. Обеспечить несколько перегрузок для оператора вызова? Используйте constexpr-if и проверьте тип?

По существу, наличие lhs сравнения для параметра шаблона (StringType) и rhs для другого параметра шаблона (InputString) приводит к комбинаторной проблеме, даже если STL уже предоставляет некоторые из всех возможных сравнений. Устранение одного из них сделало бы все это намного проще. Но для члена pattern мне нужна как минимум возможность хранить строки с различной шириной символов, а также иметь выбор между значением и ссылочным типом.

1 Ответ

0 голосов
/ 08 апреля 2020

Я полагаю, что обычно лучший подход - это специализация шаблона, то есть класс шаблона будет вести себя по-разному на char *, std :: array, et c.

Обратите внимание, что если у вас есть std::basic_string_view, то вы можете преобразовать все упомянутые вами типы в строковое представление и, таким образом, использовать встроенную функцию сравнения. Поэтому в вашем случае я бы реализовал это немного по-другому:

template<typename T>
std::string_view toStringView(const T& object)
{
    // covers containers (std::string_view, std::array, std::vector, std::string)
    return std::string_view(object.data(), object.size());
}

template<typename T>
std::string_view toStringView(const T* ptr)
{
    // Pointer, in this case you would need a null-terminator string.
    return std::string_view(reinterpret_cast<const char*>(ptr));
}

template<typename StringType>
class StrcmpAlgorithm {

    StringType pattern;

  public:
    StrcmpAlgorithm(StringType p) : pattern(std::move(p)) {}

    template<typename InputString>
    bool operator()(const InputString& input)
    {
        return toStringView(input) == toStringView(pattern);
    }
};

Конечно, этот пример можно и нужно улучшить, чтобы он поддерживал std::wstring_view и не работал на несовместимых типах (таких как char**).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...