5

In this answer, we can see that we can create our own views. I have tried that:

template <typename Range>
struct squared_view : std::ranges::view_interface<squared_view<Range>> {
    struct iterator;

    constexpr squared_view() = default;
    constexpr squared_view(Range t): t(t) { }

    auto begin() const { return iterator(std::ranges::begin(t)); }
    auto end() const { return iterator(std::ranges::end(t)); }

    Range t;
};

template <typename Range>
struct squared_view<Range>::iterator {
    using value_type = typename std::ranges::iterator_t<Range>::value_type;

    constexpr iterator() = default;
    constexpr iterator(std::ranges::iterator_t<Range> it): it_{it} { }

    iterator& operator++() {
        ++it_;
        return *this;
    }

    iterator operator++(int) {
        const iterator current{*this};
        ++it_;
        return current;
    }

    value_type operator*() const {
        const auto value = *it_;
        return value * value;
    }

    bool operator==(iterator const& rhs) const { return it_ == rhs.it_; }

private:
    std::ranges::iterator_t<Range> it_;
};

template <std::ranges::range Range>
squared_view(Range&&) -> squared_view<std::ranges::views::all_t<Range>>;

struct squared_fn {
    template <typename Rng>
    auto operator()(Rng&& rng) const {
        return squared_view{std::forward<Rng>(rng)};
    }

    template <typename Rng>
    friend decltype(auto) operator|(Rng&& rng, squared_fn fun) {
        return fun(std::forward<Rng>(rng));
    }
};

constexpr squared_fn squared;

and when I thought I have succeeded:

int main() {
    std::vector<int> vec = {1, 2, 3};
    auto rng = vec | squared;

    for (const auto e : rng) {
        std::cout << e << ' ';  // prints 1 4 9
    }
}

it turned out that I actually failed, because std::ranges::range<decltype(rng)> is false.

Trying to figure out why, I tried to take std::ranges::begin(rng), which resulted in a few dozen lines of errors, which, more or less, boiled down to:

note: no operand of the disjunction is satisfied
requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp> || __adl_begin<_Tp>

which is weird, because I did provide member begin() and end() (unless __member_begin<_Tp> doesn't do what it looks like it's doing).

The full error message is as follows:

C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp: In function 'int main()':
C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:72:27: error: no match for call to '(const std::ranges::__cust_access::_Begin) (squared_view<std::ranges::ref_view<std::vector<int> > >&)'
   72 |     std::ranges::begin(rng);
      |                           ^
In file included from C:/msys64/mingw64/include/c++/10.1.0/string:54,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/locale_classes.h:40,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/ios_base.h:41,
                 from C:/msys64/mingw64/include/c++/10.1.0/ios:42,
                 from C:/msys64/mingw64/include/c++/10.1.0/ostream:38,
                 from C:/msys64/mingw64/include/c++/10.1.0/iostream:39,
                 from C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:1:
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:400:2: note: candidate: 'constexpr auto std::ranges::__cust_access::_Begin::operator()(_Tp&&) const [with _Tp = squared_view<std::ranges::ref_view<std::vector<int> > >&]'
  400 |  operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
      |  ^~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:400:2: note: constraints not satisfied
C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp: In instantiation of 'constexpr auto std::ranges::__cust_access::_Begin::operator()(_Tp&&) const [with _Tp = squared_view<std::ranges::ref_view<std::vector<int> > >&]':
C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:72:27:   required from here
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:400:2:   required by the constraints of 'template<class _Tp>  requires (__maybe_borrowed_range<_Tp>) && ((is_array_v<typename std::remove_reference<_Tp>::type>) || (__member_begin<_Tp>) || (__adl_begin<_Tp>)) constexpr auto std::ranges::__cust_access::_Begin::operator()(_Tp&&) const'
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:398:4: note: no operand of the disjunction is satisfied
  397 |  requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  398 |    || __adl_begin<_Tp>
      |    ^~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:397:11: note: the operand 'is_array_v<std::remove_reference_t<_Tp> >' is unsatisfied because
  397 |  requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  398 |    || __adl_begin<_Tp>
      |    ~~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:400:2:   required by the constraints of 'template<class _Tp>  requires (__maybe_borrowed_range<_Tp>) && ((is_array_v<typename std::remove_reference<_Tp>::type>) || (__member_begin<_Tp>) || (__adl_begin<_Tp>)) constexpr auto std::ranges::__cust_access::_Begin::operator()(_Tp&&) const'
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:397:11: note: the expression 'is_array_v<typename std::remove_reference<_Tp>::type> [with _Tp = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >&; _Tp = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >&]' evaluated to 'false'
  397 |  requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:397:50: note: the operand '__member_begin<_Tp>' is unsatisfied because
  397 |  requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
  398 |    || __adl_begin<_Tp>
      |    ~~~~~~~~~~~~~~~~~~~                            
In file included from C:/msys64/mingw64/include/c++/10.1.0/bits/stl_iterator_base_types.h:71,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/stl_algobase.h:65,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/char_traits.h:39,
                 from C:/msys64/mingw64/include/c++/10.1.0/ios:40,
                 from C:/msys64/mingw64/include/c++/10.1.0/ostream:38,
                 from C:/msys64/mingw64/include/c++/10.1.0/iostream:39,
                 from C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:1:
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:847:15:   required for the satisfaction of '__member_begin<_Tp>' [with _Tp = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >&]
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:847:32:   in requirements with '_Tp& __t' [with _Tp = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >&]
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:849:28: note: 'std::__detail::__decay_copy(__t.begin())' does not satisfy return-type-requirement, because
  849 |    { __detail::__decay_copy(__t.begin()) } -> input_or_output_iterator;
      |      ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:849:6: error: deduced expression type does not satisfy placeholder constraints
  849 |    { __detail::__decay_copy(__t.begin()) } -> input_or_output_iterator;
      |    ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:849:6: note: constraints not satisfied
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:507:13:   required for the satisfaction of 'weakly_incrementable<_Iter>' [with _Iter = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >::iterator<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >]
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:522:13:   required for the satisfaction of 'input_or_output_iterator<squared_view<std::ranges::ref_view<std::vector<int> > >::iterator>'
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:509:10:   in requirements with '_Iter __i' [with _Tp = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >::iterator<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >; _Iter = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >::iterator<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >]
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:511:11: note: the required type 'std::iter_difference_t<_Iter>' is invalid, because
  511 |  typename iter_difference_t<_Iter>;
      |  ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h: In substitution of 'template<class _Tp> using __iter_diff_t = typename std::__detail::__iter_traits_impl<_Tp, std::incrementable_traits<_Iter> >::type::difference_type [with _Tp = squared_view<std::ranges::ref_view<std::vector<int> > >::iterator]':
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:185:11:   required by substitution of 'template<class _Tp> using iter_difference_t = std::__detail::__iter_diff_t<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> [with _Tp = squared_view<std::ranges::ref_view<std::vector<int> > >::iterator]'
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:511:11:   required from 'constexpr auto std::ranges::__cust_access::_Begin::operator()(_Tp&&) const [with _Tp = squared_view<std::ranges::ref_view<std::vector<int> > >&]'
C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:72:27:   required from here
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:180:13: error: no type named 'difference_type' in 'std::__detail::__iter_traits<squared_view<std::ranges::ref_view<std::vector<int> > >::iterator, std::incrementable_traits<squared_view<std::ranges::ref_view<std::vector<int> > >::iterator> >' {aka 'struct std::incrementable_traits<squared_view<std::ranges::ref_view<std::vector<int> > >::iterator>'}
  180 |       using __iter_diff_t = typename
      |             ^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h: In instantiation of 'constexpr auto std::ranges::__cust_access::_Begin::operator()(_Tp&&) const [with _Tp = squared_view<std::ranges::ref_view<std::vector<int> > >&]':
C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:72:27:   required from here
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:512:21: note: nested requirement '__is_signed_integer_like<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>' is not satisfied, because
  512 |  requires __detail::__is_signed_integer_like<iter_difference_t<_Iter>>;
      |           ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:498:15:   required for the satisfaction of '__is_signed_integer_like<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>'
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:499:2: note: no operand of the disjunction is satisfied
  498 |       concept __is_signed_integer_like = signed_integral<_Tp>
      |                                          ~~~~~~~~~~~~~~~~~~~~
  499 |  || same_as<_Tp, __max_diff_type>;
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:498:42: note: the operand 'signed_integral<_Tp>' is unsatisfied because
  498 |       concept __is_signed_integer_like = signed_integral<_Tp>
      |                                          ^~~~~~~~~~~~~~~~~~~~
  499 |  || same_as<_Tp, __max_diff_type>;
      |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~         
C:/msys64/mingw64/include/c++/10.1.0/concepts:102:13:   required for the satisfaction of 'integral<_Tp>' [with _Tp = typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>::type>::type> >::type::difference_type]
C:/msys64/mingw64/include/c++/10.1.0/concepts:105:13:   required for the satisfaction of 'signed_integral<_Tp>' [with _Tp = typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>::type>::type> >::type::difference_type]
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:498:15:   required for the satisfaction of '__is_signed_integer_like<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>'
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:512:11: error: no type named 'difference_type' in 'using type = struct std::incrementable_traits<squared_view<std::ranges::ref_view<std::vector<int> > >::iterator>' {aka 'struct std::incrementable_traits<squared_view<std::ranges::ref_view<std::vector<int> > >::iterator>'}
  512 |  requires __detail::__is_signed_integer_like<iter_difference_t<_Iter>>;
      |  ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:499:5: note: the operand 'same_as<_Tp, __int128>' is unsatisfied because
  498 |       concept __is_signed_integer_like = signed_integral<_Tp>
      |                                          ~~~~~~~~~~~~~~~~~~~~
  499 |  || same_as<_Tp, __max_diff_type>;
      |  ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/concepts:57:15:   required for the satisfaction of '__same_as<_Tp, _Up>' [with _Tp = typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>::type>::type> >::type::difference_type; _Up = __int128]
C:/msys64/mingw64/include/c++/10.1.0/concepts:62:13:   required for the satisfaction of 'same_as<_Tp, __int128>' [with _Tp = typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>::type>::type> >::type::difference_type]
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:498:15:   required for the satisfaction of '__is_signed_integer_like<typename std::__detail::__iter_traits_impl<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::incrementable_traits<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type> >::type::difference_type>'
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:512:11: error: no type named 'difference_type' in 'using type = struct std::incrementable_traits<squared_view<std::ranges::ref_view<std::vector<int> > >::iterator>' {aka 'struct std::incrementable_traits<squared_view<std::ranges::ref_view<std::vector<int> > >::iterator>'}
  512 |  requires __detail::__is_signed_integer_like<iter_difference_t<_Iter>>;
      |  ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from C:/msys64/mingw64/include/c++/10.1.0/string:54,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/locale_classes.h:40,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/ios_base.h:41,
                 from C:/msys64/mingw64/include/c++/10.1.0/ios:42,
                 from C:/msys64/mingw64/include/c++/10.1.0/ostream:38,
                 from C:/msys64/mingw64/include/c++/10.1.0/iostream:39,
                 from C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:1:
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:398:7: note: the operand '__adl_begin<_Tp>' is unsatisfied because
  397 |  requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  398 |    || __adl_begin<_Tp>
      |    ~~~^~~~~~~~~~~~~~~~
In file included from C:/msys64/mingw64/include/c++/10.1.0/bits/stl_iterator_base_types.h:71,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/stl_algobase.h:65,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/char_traits.h:39,
                 from C:/msys64/mingw64/include/c++/10.1.0/ios:40,
                 from C:/msys64/mingw64/include/c++/10.1.0/ostream:38,
                 from C:/msys64/mingw64/include/c++/10.1.0/iostream:39,
                 from C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:1:
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:856:15:   required for the satisfaction of '__adl_begin<_Tp>' [with _Tp = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >&]
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:857:5:   in requirements with '_Tp& __t' [with _Tp = squared_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > > >&]
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:859:28: note: the required expression 'std::__detail::__decay_copy(std::__detail::begin(__t))' is invalid, because
  859 |    { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
      |      ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:859:34: error: call of overloaded 'begin(squared_view<std::ranges::ref_view<std::vector<int> > >&)' is ambiguous
  859 |    { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator;
      |                             ~~~~~^~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:852:10: note: candidate: 'void std::__detail::begin(auto:1&) [with auto:1 = squared_view<std::ranges::ref_view<std::vector<int> > >]' (deleted)
  852 |     void begin(auto&) = delete;
      |          ^~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/iterator_concepts.h:853:10: note: candidate: 'void std::__detail::begin(const auto:2&) [with auto:2 = squared_view<std::ranges::ref_view<std::vector<int> > >]' (deleted)
  853 |     void begin(const auto&) = delete;
      |          ^~~~~
In file included from C:/msys64/mingw64/include/c++/10.1.0/string:54,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/locale_classes.h:40,
                 from C:/msys64/mingw64/include/c++/10.1.0/bits/ios_base.h:41,
                 from C:/msys64/mingw64/include/c++/10.1.0/ios:42,
                 from C:/msys64/mingw64/include/c++/10.1.0/ostream:38,
                 from C:/msys64/mingw64/include/c++/10.1.0/iostream:39,
                 from C:\Users\Lenovo\CLionProjects\EasyNamespace\main.cpp:1:
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:51:5: note: candidate: 'constexpr decltype (__cont.begin()) std::begin(_Container&) [with _Container = squared_view<std::ranges::ref_view<std::vector<int> > >; decltype (__cont.begin()) = squared_view<std::ranges::ref_view<std::vector<int> > >::iterator]'
   51 |     begin(_Container& __cont) -> decltype(__cont.begin())
      |     ^~~~~
C:/msys64/mingw64/include/c++/10.1.0/bits/range_access.h:61:5: note: candidate: 'constexpr decltype (__cont.begin()) std::begin(const _Container&) [with _Container = squared_view<std::ranges::ref_view<std::vector<int> > >; decltype (__cont.begin()) = squared_view<std::ranges::ref_view<std::vector<int> > >::iterator]'
   61 |     begin(const _Container& __cont) -> decltype(__cont.begin())
      |     ^~~~~
mingw32-make.exe[3]: *** [CMakeFiles\EasyNamespace.dir\build.make:82: CMakeFiles/EasyNamespace.dir/main.cpp.obj] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:95: CMakeFiles/EasyNamespace.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:102: CMakeFiles/EasyNamespace.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:137: EasyNamespace] Error 2

What exactly did I miss? How do I properly create my own <ranges> extensions?

Fureeish
  • 12,533
  • 4
  • 32
  • 62
  • [works with gcc10.2 -std=c++20](https://godbolt.org/z/7PPdor) What compiler and compiler options are you using? – KamilCuk Aug 23 '20 at 16:31
  • @KamilCuk I know it works (outputs the values). What doesn't work is that `std::ranges::range` is `false` and when I wanted to test why (by calling `std::ranges::begin(rng)`), I was hit with a wall of errors. – Fureeish Aug 23 '20 at 16:40
  • 1
    @Artyer why would you assume it's not moveable? What did I write to prevent the move constructor and the move assignment operator to be implicitly defined? Nonetheless, explicitely providing them did not change a thing. – Fureeish Aug 23 '20 at 16:43
  • 2
    (1) It would help if your program demonstrated the issue, instead of working and having something else entirely fail (leading inevitably to @KamilCuk's comment) and (2) the error tells you what's missing (... eventually ...): iterators need a bunch of type aliases and you're missing most of them. – Barry Aug 23 '20 at 16:49
  • @Barry I didn't think of a better emphasis instead of maybe "I want my view to satisfy `std::ranges::range` concept", but I don't think that would change much. As for the type aliases, that fixes the issue. Not sure whether it's better to close this question or wait for your answer to immediately accept it. Thank you (again) nonetheless! – Fureeish Aug 23 '20 at 17:02

1 Answers1

7

Your iterator doesn't satisfy the std::input_or_output_iterator concept.

It needs to be std::weakly_incrementable, which requires std::iter_difference_t to be valid. Currently, since your type has no difference_type member type or specialiase std::iterator_traits, std::iter_difference_t is invalid.

So just add an alias:

template <typename Range>
struct squared_view<Range>::iterator {
    using difference_type = std::iter_difference_t<std::ranges::iterator_t<Range>>;

    // ...
};
Artyer
  • 31,034
  • 3
  • 47
  • 75