@Mercury13
Программист на «си с крестами» и не только

Как сделать, чтобы шаблонная функция принимала const char*?

namespace str {
    /// @brief remainderSv
    ///         remainderSv("string", "st") = "ring"
    template <class C, class T = std::char_traits<C>>
    std::basic_string_view<C,T> remainderSv(
            std::basic_string_view<C,T> s,
            std::basic_string_view<C,T> prefix)
    {
        if (s.length() <= prefix.length()
                || !s.starts_with(prefix))
            return {};
        return s.substr(prefix.length(), s.length() - prefix.length());
    }
}  // namespace str

// Тест, сделанный системой Google test
TEST (RemainderSv, Pref)
{
    std::string_view s = "string";
    EXPECT_EQ("ing", str::remainderSv(s, "str"));
}

Как сделать, чтобы код компилировался? А то пока не допускает и string_view/const char*, и string_view/string.
Если добавить нешаблонную функцию, всё работает, но зачем?
  • Вопрос задан
  • 219 просмотров
Решения вопроса 1
@Mercury13 Автор вопроса
Программист на «си с крестами» и не только
template <class T> struct string_traits;

    template <class C, class T, class A>
    struct string_traits<std::basic_string<C,T,A>> {
        using Ch = C;
        using Tr = T;
        using Sv = std::basic_string_view<C,T>;
    };

    template <class C, class T>
    struct string_traits<std::basic_string_view<C,T>> {
        using Ch = C;
        using Tr = T;
        using Sv = std::basic_string_view<C,T>;
    };

    template <class C>
    struct string_traits<const C*> {
        using Ch = C;
        using Tr = std::char_traits<C>;
        using Sv = std::basic_string_view<C>;
    };

    template <class C, size_t N>
    struct string_traits<C[N]> {
        using Ch = C;
        using Sv = std::basic_string_view<C>;
    };

    template<class S>
    using s_v_t = typename string_traits<std::remove_cvref_t<S>>::Sv;

    namespace detail {
        template <class Sv>
        Sv remainderSv(Sv s, Sv prefix)
        {
            if (s.length() <= prefix.length()
                    || !s.starts_with(prefix))
                return {};
            return s.substr(prefix.length(), s.length() - prefix.length());
        }
    }

    /// @brief remainderSv
    ///    Same for prefix only
    template <class A>
    inline auto remainderSv(const A& s, s_v_t<A> prefix) -> s_v_t<A>
        { return detail::remainderSv<s_v_t<A>>(s, prefix); }
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы