И string_ref в boost, и string_span в GSL не определяют конструктор, который принимает пару итераторов. В чем причина этого решения?
Обычно это не имеет большого значения, я могу просто создать string_ref следующим образом:
boost::string_ref s(start, std::distance(start, finish));
но причина, по которой я хочу, чтобы конструктор использовал пару итераторов, заключается в том, что у меня есть код, который выглядит следующим образом:
template<typename Type, typename Iterator>
void func(const Iterator& begin, const Iterator& end)
{
Type s(begin, end);
//do stuff with s
}
В настоящее время я могу назвать это так:
func<std::string>(start, finish)
Я хочу изменить это на:
func<boost::string_ref>(start, finish) //compile error
но этот код не скомпилируется, потому что отсутствие конструктора, принимающего пару итераторов в string_ref
boost::string_ref
простая ссылка на строку в виде указателя на смежный блок памяти с заданной длиной. Поскольку итераторы гораздо более общие, вы не можете предполагать, что ваши start, finish
Диапазон относится к чему-либо как непрерывный блок памяти.
С другой стороны, std::string
может быть создан из диапазона, определенного Итераторами, потому что он просто сделает копию значений диапазона, независимо от того, что является базовой структурой данных.
Вспомогательная функция, которую я создал, надеюсь, кто-то еще может найти это полезным. Кратко протестировано 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
Похоже, я ошибаюсь. gsl::string_span
У меня есть конструктор, который принимает начальный и конечный итератор. Таким образом, нет ничего проблемного в создании string_view из пар итераторов и его отсутствии в boost::string_ref
это, вероятно, просто недосмотр.
В моем случае я в конечном итоге наследую от boost::string_ref
и добавить конструктор сам.