c++stringvectorparameter-passingstring-view

Does it makes sense to take vector<string_view> as a parameter


I want a function that takes as input a vector of strings that I don't want to modify. So I thought about taking as input a vector<string_view>. However, if I do this, I can't pass a vector<string> as a parameter anymore.

Example:

#include <vector>
#include <string>
#include <string_view>

using namespace std;

void takesStringViewVectorRef(vector<string_view> const & v) {}

int main ()
{
  string_view strview; string str;
  takesStringViewVectorRef({"a", "b", strview, str}); // works, cool!

  vector<string> vec;
  takesStringViewVectorRef(vec); // doesn't work

  vector<const char *> vec2;
  takesStringViewVectorRef(vec2); // doesn't work either

  return 0;
}

Is this just a bad idea? Should I stick with vector<string>? I'm a little confused about this


Solution

  • I would create a template function that can work on the string type you put in like this:

    #include <iostream>
    #include <vector>
    #include <string>
    #include <type_traits>
    
    // using namespace std; <-- no don't do this
    // some C++17 style type checking helpers
    
    template<typename type_t>
    constexpr bool is_stringlike_v = std::is_convertible_v<type_t, std::string_view>;
    
    template<typename type_t>
    using requires_stringlike_t = typename std::enable_if_t<is_stringlike_v<type_t>, void>;
    
    // template function that accepts any stringlike type
    template<typename type_t>
    auto do_something_with_strings(const std::vector<type_t>& strings) -> requires_stringlike_t<type_t>
    {
        for (const auto& string : strings)
        {
            std::cout << string << " ";
        }
        std::cout << "\n";
    }
    
    int main()
    {
        std::string_view strview{ "strview" };
        std::string str{ "str" };
    
        // need to explicitly specialize since not all values in the "vector" are of the same type
        do_something_with_strings<std::string_view>({ "a", "b", strview, str }); // works, cool!
    
        std::vector<std::string> vec{ "std::string1", "std::string2" };
        do_something_with_strings(vec);
    
        std::vector<const char*> vec2{ "hello", "world" };
        do_something_with_strings(vec2);
    
        std::vector<int> vec3{1,2,3};
        //do_something_with_strings(vec3); <== will correctly not compile
    
        return 0;
    }