Search code examples
c++g++std-rangesc++23

Why can't I use the subscript operator on the result of std::ranges::to<std::vector>()?


Why can't I use the subscript operator on the result of std::ranges::tostd::vector() or even better without and what is the solution? BTW, I am trying this with G++ trunk.

#include <ranges>
#include <string_view>
#include <vector>

using namespace std::literals::string_view_literals;

int main(const int argv, const char *const argc[])
{
    auto test = "a b c"sv | std::views::lazy_split("\\s+"sv) | std::ranges::to<std::vector>();
    static_assert("a"sv == test[0]);
    return 0;
}

The errors I get are:

<source>: In function 'int main(int, const char* const*)':
<source>:10:25: error: no match for 'operator==' (operand types are 'std::basic_string_view<char>' and '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'})
   10 |     static_assert("a"sv == test[0]);
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/iterator:63,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ranges:43,
                 from <source>:1:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_iterator.h:527:5: note: candidate: 'template<class _IteratorL, class _IteratorR> constexpr bool std::operator==(const reverse_iterator<_IteratorL>&, const reverse_iterator<_IteratorR>&) requires requires{{std::operator==::__x->base() == std::operator==::__y->base()} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];}' (reversed)
  527 |     operator==(const reverse_iterator<_IteratorL>& __x,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_iterator.h:527:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} is not derived from 'const std::reverse_iterator<_IteratorL>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_iterator.h:1667:5: note: candidate: 'template<class _IteratorL, class _IteratorR> constexpr bool std::operator==(const move_iterator<_IteratorL>&, const move_iterator<_IteratorR>&) requires requires{{std::operator==::__x->base() == std::operator==::__y->base()} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];}' (reversed)
 1667 |     operator==(const move_iterator<_IteratorL>& __x,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_iterator.h:1667:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} is not derived from 'const std::move_iterator<_IteratorL>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string:43,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/locale_classes.h:40,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/ios_base.h:41,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/streambuf:43,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/streambuf_iterator.h:35,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/iterator:66:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/allocator.h:235:5: note: candidate: 'template<class _T1, class _T2> constexpr bool std::operator==(const allocator<_CharT>&, const allocator<_T2>&)' (reversed)
  235 |     operator==(const allocator<_T1>&, const allocator<_T2>&)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/allocator.h:235:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} is not derived from 'const std::allocator<_CharT>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_algobase.h:64,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string:51:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_pair.h:1010:5: note: candidate: 'template<class _T1, class _T2, class _U1, class _U2> constexpr bool std::operator==(const pair<_T1, _T2>&, const pair<_U1, _U2>&)' (reversed)
 1010 |     operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_pair.h:1010:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} is not derived from 'const std::pair<_T1, _T2>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/basic_string.h:47,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string:54:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string_view:609:5: note: candidate: 'template<class _CharT, class _Traits> constexpr bool std::operator==(basic_string_view<_CharT, _Traits>, type_identity_t<basic_string_view<_CharT, _Traits> >)' (reversed)
  609 |     operator==(basic_string_view<_CharT, _Traits> __x,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string_view:609:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type' is not derived from 'std::basic_string_view<_CharT, _Traits>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/basic_string.h:3772:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> constexpr bool std::operator==(const __cxx11::basic_string<_CharT, _Traits, _Allocator>&, const _CharT*)' (reversed)
 3772 |     operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/basic_string.h:3772:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/uses_allocator_args.h:39,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/memory_resource.h:41,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string:67:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/tuple:2556:5: note: candidate: 'template<class ... _TElements, class ... _UElements> constexpr bool std::operator==(const tuple<_Ts ...>&, const tuple<_Elements ...>&)' (reversed)
 2556 |     operator==(const tuple<_TElements...>& __t,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/tuple:2556:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} is not derived from 'const std::tuple<_Ts ...>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ranges:44:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/optional:1292:5: note: candidate: 'template<class _Tp> constexpr bool std::operator==(const optional<_Tp>&, nullopt_t)' (reversed)
 1292 |     operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/optional:1292:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} is not derived from 'const std::optional<_Tp>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ranges:3451:11: note: candidate: 'constexpr bool std::ranges::operator==(const lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>&, std::default_sentinel_t)' (reversed)
 3451 |           operator==(const _OuterIter& __x, default_sentinel_t)
      |           ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ranges:3451:40: note:   no known conversion for argument 1 from '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} to 'const std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>&'
 3451 |           operator==(const _OuterIter& __x, default_sentinel_t)
      |                      ~~~~~~~~~~~~~~~~~~^~~
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/ios_base.h:46:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/system_error:465:3: note: candidate: 'bool std::operator==(const error_code&, const error_condition&)' (reversed)
  465 |   operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
      |   ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/system_error:465:32: note:   no known conversion for argument 1 from '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} to 'const std::error_code&'
  465 |   operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
      |              ~~~~~~~~~~~~~~~~~~^~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_iterator.h:586:5: note: candidate: 'template<class _Iterator> constexpr bool std::operator==(const reverse_iterator<_IteratorL>&, const reverse_iterator<_IteratorL>&) requires requires{{std::operator==::__x->base() == std::operator==::__y->base()} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];}'
  586 |     operator==(const reverse_iterator<_Iterator>& __x,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_iterator.h:586:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::reverse_iterator<_IteratorL>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_iterator.h:1737:5: note: candidate: 'template<class _Iterator> constexpr bool std::operator==(const move_iterator<_IteratorL>&, const move_iterator<_IteratorL>&)'
 1737 |     operator==(const move_iterator<_Iterator>& __x,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_iterator.h:1737:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::move_iterator<_IteratorL>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/iosfwd:42,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stream_iterator.h:35,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/iterator:65:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/postypes.h:192:5: note: candidate: 'template<class _StateT> bool std::operator==(const fpos<_StateT>&, const fpos<_StateT>&)'
  192 |     operator==(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/postypes.h:192:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::fpos<_StateT>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string_view:609:5: note: candidate: 'constexpr bool std::operator==(basic_string_view<_CharT, _Traits>, type_identity_t<basic_string_view<_CharT, _Traits> >) [with _CharT = char; _Traits = char_traits<char>; type_identity_t<basic_string_view<_CharT, _Traits> > = basic_string_view<char>]'
  609 |     operator==(basic_string_view<_CharT, _Traits> __x,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/string_view:610:68: note:   no known conversion for argument 2 from '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} to 'std::type_identity_t<std::basic_string_view<char> >' {aka 'std::basic_string_view<char>'}
  610 |                type_identity_t<basic_string_view<_CharT, _Traits>> __y)
      |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/basic_string.h:3755:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> constexpr bool std::operator==(const __cxx11::basic_string<_CharT, _Traits, _Allocator>&, const __cxx11::basic_string<_CharT, _Traits, _Allocator>&)'
 3755 |     operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/basic_string.h:3755:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/streambuf_iterator.h:234:5: note: candidate: 'template<class _CharT, class _Traits> bool std::operator==(const istreambuf_iterator<_CharT, _Traits>&, const istreambuf_iterator<_CharT, _Traits>&)'
  234 |     operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/streambuf_iterator.h:234:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::istreambuf_iterator<_CharT, _Traits>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/optional:1232:5: note: candidate: 'template<class _Tp, class _Up> constexpr std::__optional_eq_t<_Tp, _Up> std::operator==(const optional<_Tp>&, const optional<_Up>&)'
 1232 |     operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/optional:1232:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::optional<_Tp>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/optional:1360:5: note: candidate: 'template<class _Tp, class _Up> constexpr std::__optional_eq_t<_Tp, _Up> std::operator==(const optional<_Tp>&, const _Up&)'
 1360 |     operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/optional:1360:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::optional<_Tp>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/optional:1366:5: note: candidate: 'template<class _Tp, class _Up> constexpr std::__optional_eq_t<_Up, _Tp> std::operator==(const _Up&, const optional<_Tp>&)'
 1366 |     operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/optional:1366:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   '__gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>, std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type>::value_type' {aka 'std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type'} is not derived from 'const std::optional<_Tp>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/span:43,
                 from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ranges:45:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/array:303:5: note: candidate: 'template<class _Tp, long unsigned int _Nm> constexpr bool std::operator==(const array<_Tp, _Nm>&, const array<_Tp, _Nm>&)'
  303 |     operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/array:303:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::array<_Tp, _Nm>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ranges:49:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/variant:1266:3: note: candidate: 'template<class ... _Types> constexpr bool std::operator==(const variant<_Types ...>&, const variant<_Types ...>&)'
 1266 |   _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/variant:1266:3: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::variant<_Types ...>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
In file included from /opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/vector:66,
                 from <source>:3:
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_vector.h:2050:5: note: candidate: 'template<class _Tp, class _Alloc> constexpr bool std::operator==(const vector<_Tp, _Alloc>&, const vector<_Tp, _Alloc>&)'
 2050 |     operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/bits/stl_vector.h:2050:5: note:   template argument deduction/substitution failed:
<source>:10:34: note:   'std::basic_string_view<char>' is not derived from 'const std::vector<_Tp, _Alloc>'
   10 |     static_assert("a"sv == test[0]);
      |                                  ^
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/system_error:449:3: note: candidate: 'bool std::operator==(const error_code&, const error_code&)'
  449 |   operator==(const error_code& __lhs, const error_code& __rhs) noexcept
      |   ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/system_error:449:32: note:   no known conversion for argument 1 from 'std::basic_string_view<char>' to 'const std::error_code&'
  449 |   operator==(const error_code& __lhs, const error_code& __rhs) noexcept
      |              ~~~~~~~~~~~~~~~~~~^~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/system_error:480:3: note: candidate: 'bool std::operator==(const error_condition&, const error_condition&)'
  480 |   operator==(const error_condition& __lhs,
      |   ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/system_error:480:37: note:   no known conversion for argument 1 from 'std::basic_string_view<char>' to 'const std::error_condition&'
  480 |   operator==(const error_condition& __lhs,
      |              ~~~~~~~~~~~~~~~~~~~~~~~^~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/variant:1273:18: note: candidate: 'constexpr bool std::operator==(monostate, monostate)'
 1273 |   constexpr bool operator==(monostate, monostate) noexcept { return true; }
      |                  ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/variant:1273:29: note:   no known conversion for argument 1 from 'std::basic_string_view<char>' to 'std::monostate'
 1273 |   constexpr bool operator==(monostate, monostate) noexcept { return true; }
      |                             ^~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ranges:3443:11: note: candidate: 'constexpr bool std::ranges::operator==(const lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>&, const lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>&) requires  forward_range<typename std::__conditional<_Const>::type<const _Vp, _Vp> >'
 3443 |           operator==(const _OuterIter& __x, const _OuterIter& __y)
      |           ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20240503/include/c++/15.0.0/ranges:3443:40: note:   no known conversion for argument 1 from 'std::basic_string_view<char>' to 'const std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>&'
 3443 |           operator==(const _OuterIter& __x, const _OuterIter& __y)
      |                      ~~~~~~~~~~~~~~~~~~^~~
Compiler returned: 1

I do not even understand why the second operator is of type __gnu_cxx::__alloc_traits<std::allocator<std::ranges::lazy_split_view<std::basic_string_view<char>, std::basic_string_view<char> >::_OuterIter<true>::value_type> instead of also being std::basic_string_view<char>.

Link to Compiler Explorer: https://godbolt.org/z/nh4eMc45W

P.S.: The real code does for sure further processing, parses more data and is, btw, in a constexprfunction.


Solution

  • You misunderstand how std::views::lazy_split works. It doesn't give you a neat range of std::string_view as a result; it just operates on ranges and wouldn't know that you want each range to be bundled up into a std::string_view. Rather, it gives you a "range of char ranges" where each range contains characters between the separator:

    for (const auto& r : "ax by c"sv | std::views::lazy_split(" "sv)) {
        for (char c : r) {
            std::cout << c << ' ';
        }
        std::cout << '\n';
    }
    

    This code prints

    a x
    b y
    c
    

    When you do | std::ranges::to<std::vector> in the end, you're not collecting std::string_views, you're just collecting those unspecified char ranges that you could iterate over but not compare with ==.

    Also note that ranges have no regex support; you cannot split over "\\s+"sv (as a regex), only over single characters such as ' ' or over ranges of characters such as " "sv.

    Solution

    Something you could (but probably don't want to) write is:

    auto test = "a b c"sv
        | std::views::lazy_split(" "sv)
        // cannot use std::string_view here because it has no std::from_range constructor:
        | std::views::transform(std::ranges::to<std::vector>())
        // make vector of vectors
        | std::ranges::to<std::vector>();
    static_assert(std::is_same_v<decltype(test), std::vector<std::vector<char>>>);
    

    However, we can work around that by providing some lambda to std::views::transform:

    auto test = "a b c"sv
        // cannot use lazy_split because string_view needs to be fed
        // contiguous iterators, and only split preserves the category
        | std::views::split(" "sv)
        | std::views::transform([](const auto& v) {
            return std::string_view(v.begin(), v.end());
        })
        | std::ranges::to<std::vector>();
    static_assert(std::is_same_v<decltype(test), std::vector<std::string_view>>);