Why string_view constructor doesn't take a pair of iterators

3k Views Asked by At

Both string_ref in boost and string_span in GSL doesn't define constructor that takes a pair of iterator. What is the reason of this decision ?

Usually it's not a big deal, I can just create string_ref like this :

boost::string_ref s(start, std::distance(start, finish));

but the reason I want constructor that take a pair of iterators is because I have code that look like this:

template<typename Type, typename Iterator>
void func(const Iterator& begin, const Iterator& end)
{
    Type s(begin, end);
    //do stuff with s
}

Currently, I can call it like this :

func<std::string>(start, finish)

I want to change it to :

func<boost::string_ref>(start, finish) //compile error

but that code won't compile because the lack of constructor taking a pair of iterator in string_ref

3

There are 3 best solutions below

0
On BEST ANSWER

Looks like I make a mistake. gsl::string_span do have a constructor that takes begin and end iterator. So, there is nothing problematic with creating string_view from iterator pairs and the lack of it in boost::string_ref is probably just an oversight.

For my case, I end up inheriting from boost::string_ref and add the constructor myself.

2
On

Helper function I created, hopefully someone else can find this useful. Briefly tested MSVC14/boost 1.59, MSVC17/boost 1.64, MSVC17/C++17

#include <boost/utility/string_ref.hpp>

// todo:  change to std::basic_string_view<charT> in C++17
template <typename charT> using basic_string_view_type = boost::basic_string_ref<charT>;    

// Creates a string view from a pair of iterators
//  http://stackoverflow.com/q/33750600/882436
template <typename _It>
inline constexpr auto make_string_view( _It begin, _It end )
{
    using result_type = basic_string_view_type<typename std::iterator_traits<_It>::value_type>;

    return result_type{
        ( begin != end ) ? &*begin : nullptr
        ,  (typename result_type::size_type)
        std::max(
            std::distance(begin, end)
            , (typename result_type::difference_type)0
        )
     };
}   // make_string_view
2
On

boost::string_ref is a simple reference to a string in the form of a pointer to a contiguous block of memory with a predefined length. Since iterators are much more generic, you cannot assume that your start, finish range refers to anything like a contiguous block of memory.

On the other hand, a std::string can be constructed from a range defined by Iterators because it will simply make a copy of the range's values, regardless of what the underlying data structure is.