Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Howto use a fold expression with a specific type?

I've a function to check if a std::string contains a substring. I pass the strings around as std::string_view, such that no copy takes place.

bool containsSubstr(std::string_view str, std::string_view substr)
{
    return str.find(substr) != std::string::npos;
}

I now want to make a function, using the new C++17 fold expressions, to check if a string contains several substrings. Again, I want to pass them by std::string_views.

How can I do that?

template<typename... Substrs>
bool containsAllSubstr(std::string_view str, Substrs... substrs)
{
    return  (containsSubstr(str, substrs) && ...);
}

As far as I know, the above version will take the substring's as the type with which they came in. So a std::string would be copied. How can I fix the type to std::string_view? Something like:

template<> // does not compile
bool containsAllSubstr(std::string_view str, std::string_view... substrs)
{
    return  (containsSubstr(str, substrs) && ...);
}
like image 825
dani Avatar asked Mar 19 '18 13:03

dani


1 Answers

You can't have a function parameter pack of a specific type. But this is fine (once you add const&):

template <typename... Substrs>
bool containsAllSubstr(std::string_view str, Substrs const&... substrs)
{
    return  (containsSubstr(str, substrs) && ...);
}

That won't make any copies, and just won't compile if you pass in something not convertible to string_view. If you want to make it SFINAE-friendly, could just add a condition:

template <typename... Substrs,
    std::enable_if_t<(std::is_convertible_v<Substrs const&, std::string_view> && ...), int> = 0>
bool containsAllSubstr(std::string_view str, Substrs const&... substrs)
{
    return  (containsSubstr(str, substrs) && ...);
}

Or, if you're open to a slight change in syntax, you could take an array:

template <size_t N>
bool containsAllSubstr(std::string_view str, std::string_view (&substrs)[N]);

but then you don't actually have a pack immediately. But then, you could just write a loop. Or if you don't need compile-time size at all:

bool containsAllSubstr(std::string_view str, std::initializer_list<std::string_view> substrs);
like image 176
Barry Avatar answered Nov 05 '22 23:11

Barry