Search code examples
c++c++17string-view

Best way to remove string prefix from std::string_view?


As of C++20 string_view has remove_prefix but it is "wrong"(wrong for my usecase) thing. It takes as an argument number of chars, instead of a prefix(string like thing).

I have this code, but I wonder if there is some nicer way to do what I want(note that my code cares about if prefix was removed so I return boolean):

static bool Consume(std::string_view& view, const std::string_view prefix)
{
    if (view.starts_with(prefix))
    {
        view.remove_prefix(prefix.size());
        return true;
    }
    return false;
}

note: I know I could return optional<string_view> instead of bool + out arg, but that is a different style discussion, I mostly care about having something like nonexistant

bool /*prefix removed*/string_view::remove_prefix(string_view prefix);

note2: tagged this C++17 because that is when string_view "arrived", I am fine with any C++20 alternatives.


Solution

  • I mostly care about having something like nonexistant

    bool /*prefix removed*/string_view::remove_prefix(string_view prefix);
    

    Indeed, such function is not in standard library. But you've now written such function, and your function is thus a nicer way to do something like what you want.


    If you're open for a different design, I would suggest following alternatives:

    constexpr std::string_view
    remove_prefix(std::string_view sv, std::string_view prefix) noexcept
    {
        return sv.starts_with(prefix)
            ? sv.substr(prefix.size())
            : sv;
    }
    
    // usage
    string_view no_prefix = remove_prefix(view, prefix);
    bool was_removed = no_prefix.size() != view.size();
    

    Or return a class:

    struct modify_result {
        std::string_view result;
        bool modified;
    };
    
    constexpr modify_result
    remove_prefix(std::string_view sv, std::string_view prefix) noexcept
    {
        return sv.starts_with(prefix)
            ? modify_result{sv.substr(prefix.size()), true}
            : modify_result{sv, false};
    }
    
    
    // usage
    auto [no_prefix, was_removed] = remove_prefix(view, prefix);
    

    I'm not saying these are better for your use case. These are just alternative solutions which may apply to different use cases.