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