0

I want to access the first value from a range:

#include <stdio.h>
#include <ranges>
#include <algorithm>
using namespace std;

int main()
{
    auto rg = views::split("hello there!", ' ') | views::transform([](auto word)->char{return word[0];}) ;
    
    for (char c : rg)
        printf("%c", c);

    return 0;
}

should print out the string "ht", but there is a compile error using C++20 g++ compiler (g++12)

main.cpp: In instantiation of ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’:
/usr/include/c++/11/bits/invoke.h:61:36:   required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = char; _Fn = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40:   required from ‘constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}; typename std::__invoke_result<_Functor, _ArgTypes>::type = char]’
/usr/include/c++/11/ranges:1643:26:   required from here
**main.cpp:16:99: error: no match for ‘operator[]’ (operand types are ‘std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type’ and ‘int’)**
   16 |     auto rg = views::split("hello there!", ' ') | views::transform([](auto word)->char{return word[0];}) ;
      |                                                                                               ~~~~^
In file included from /usr/include/c++/11/ranges:46,
                 from main.cpp:10:
/usr/include/c++/11/bits/ranges_util.h:153:9: note: candidate: ‘template  requires  random_access_range<_Range> constexpr decltype(auto) std::ranges::view_interface<_Derived>::operator[](std::ranges::range_difference_t<_Range>) [with _Range = _Range; _Derived = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’
  153 |         operator[](range_difference_t<_Range> __n)
      |         ^~~~~~~~
/usr/include/c++/11/bits/ranges_util.h:153:9: note:   template argument deduction/substitution failed:
/usr/include/c++/11/bits/ranges_util.h:153:9: note: constraints not satisfied
In file included from /usr/include/c++/11/ranges:37,
                 from main.cpp:10:
/usr/include/c++/11/concepts: In substitution of ‘template<class _Range>  requires  random_access_range<_Range> constexpr decltype(auto) std::ranges::view_interface<std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type>::operator[]<_Range>(std::ranges::range_difference_t<_Range>) [with _Range = std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]’:
main.cpp:16:99:   required from ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’
/usr/include/c++/11/bits/invoke.h:61:36:   required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = char; _Fn = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40:   required from ‘constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}; typename std::__invoke_result<_Functor, _ArgTypes>::type = char]’
/usr/include/c++/11/ranges:1643:26:   required from here
/usr/include/c++/11/concepts:67:13:   required for the satisfaction of ‘derived_from<typename std::__detail::__iter_concept_impl<_Iter>::type, std::bidirectional_iterator_tag>’ [with _Iter = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_InnerIter<false>]
/usr/include/c++/11/bits/iterator_concepts.h:649:13:   required for the satisfaction of ‘bidirectional_iterator<decltype (std::ranges::__cust_access::__begin(declval<_Container&>()))>’ [with _Tp = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/bits/ranges_base.h:642:13:   required for the satisfaction of ‘bidirectional_range<_Tp>’ [with _Tp = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/bits/ranges_base.h:647:13:   required for the satisfaction of ‘random_access_range<_Range>’ [with _Range = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/concepts:67:28: note:   ‘std::bidirectional_iterator_tag’ is not a base of ‘std::forward_iterator_tag’
   67 |     concept derived_from = __is_base_of(_Base, _Derived)
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/ranges:46,
                 from main.cpp:10:
main.cpp: In instantiation of ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’:
/usr/include/c++/11/bits/invoke.h:61:36:   required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = char; _Fn = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40:   required from ‘constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}; typename std::__invoke_result<_Functor, _ArgTypes>::type = char]’
/usr/include/c++/11/ranges:1643:26:   required from here
/usr/include/c++/11/bits/ranges_util.h:158:9: note: candidate: ‘template  requires  random_access_range<_Range> constexpr decltype(auto) std::ranges::view_interface<_Derived>::operator[](std::ranges::range_difference_t<_Range>) const [with _Range = _Range; _Derived = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’
  158 |         operator[](range_difference_t<_Range> __n) const
      |         ^~~~~~~~
/usr/include/c++/11/bits/ranges_util.h:158:9: note:   template argument deduction/substitution failed:
/usr/include/c++/11/bits/ranges_util.h:158:9: note: constraints not satisfied
In file included from /usr/include/c++/11/ranges:37,
                 from main.cpp:10:
/usr/include/c++/11/concepts: In substitution of ‘template<class _Range>  requires  random_access_range<_Range> constexpr decltype(auto) std::ranges::view_interface<std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type>::operator[]<_Range>(std::ranges::range_difference_t<_Range>) const [with _Range = std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]’:
main.cpp:16:99:   required from ‘main():: [with auto:19 = std::ranges::split_view, std::ranges::single_view >::_OuterIter::value_type]’
/usr/include/c++/11/bits/invoke.h:61:36:   required from ‘constexpr _Res std::__invoke_impl(std::__invoke_other, _Fn&&, _Args&& ...) [with _Res = char; _Fn = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}]’
/usr/include/c++/11/bits/invoke.h:96:40:   required from ‘constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:19)>&; _Args = {std::ranges::split_view<std::ranges::ref_view<const char [13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type}; typename std::__invoke_result<_Functor, _ArgTypes>::type = char]’
/usr/include/c++/11/ranges:1643:26:   required from here
/usr/include/c++/11/concepts:67:13:   required for the satisfaction of ‘derived_from<typename std::__detail::__iter_concept_impl<_Iter>::type, std::bidirectional_iterator_tag>’ [with _Iter = std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_InnerIter<false>]
/usr/include/c++/11/bits/iterator_concepts.h:649:13:   required for the satisfaction of ‘bidirectional_iterator<decltype (std::ranges::__cust_access::__begin(declval<_Container&>()))>’ [with _Tp = const std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/bits/ranges_base.h:642:13:   required for the satisfaction of ‘bidirectional_range<_Tp>’ [with _Tp = const std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/bits/ranges_base.h:647:13:   required for the satisfaction of ‘random_access_range<_Range>’ [with _Range = const std::ranges::split_view<std::ranges::ref_view<const char[13]>, std::ranges::single_view<char> >::_OuterIter<false>::value_type]
/usr/include/c++/11/concepts:67:28: note:   ‘std::bidirectional_iterator_tag’ is not a base of ‘std::forward_iterator_tag’
   67 |     concept derived_from = __is_base_of(_Base, _Derived)
      |           
cpplearner
  • 13,776
  • 2
  • 47
  • 72
Ludovic Aubert
  • 9,534
  • 4
  • 16
  • 28

1 Answers1

4

The error message points to /usr/include/c++/11/ranges, which suggests that you are using libstdc++ version 11, not 12. This version does not implement P2210R2.

Prior to P2210R2, the element type of split_view can at most be a forward_range, which does not ever support operator[].

P2210R2 renamed the old split_view to lazy_split_view, and added a new split_view whose element type can model stronger range concepts. It supports operator[] when the underlying range is a random_access_range. Thus the code works correctly when P2210R2 is implemented.

cpplearner
  • 13,776
  • 2
  • 47
  • 72