I have access to GCC 10 and compile with -std=c++20, and need views such as generate
cache1
, concat
etc that aren't slated until possibly C++23.
I wrote a simple program below that outputs '1 2 2 3 3 3' using range-v3. I tried to mix the range-v3 views and the views from the ranges
include without success. The 'ranges' library seems to expect views to inherit from the view_interface
, so I created a wrap_view_t
to help with that (not shown). To see the working range-v3 code, comment the line:
//#define MIX_RANGES_WITH_RANGE_V3
Code follows:
#include <iostream>
#define MIX_RANGES_WITH_RANGE_V3
#ifdef MIX_RANGES_WITH_RANGE_V3
#include <ranges>
namespace test { using namespace std::ranges; }
#else
#include <range/v3/view/all.hpp>
#include <range/v3/view/interface.hpp>
#include <range/v3/view/join.hpp>
#include <range/v3/view/take_while.hpp>
#include <range/v3/view/transform.hpp>
namespace test { using namespace ranges; }
#endif
#include <range/v3/view/generate.hpp>
#include <range/v3/view/cache1.hpp>
auto my_view()
{
auto gen{ ranges::views::generate( [ n = 0 ]() mutable
{
return std::vector< int >( ++n, n );
} )
| ranges::views::cache1
};
return std::move( gen )
| test::views::take_while( []( auto const & value ) { return value.size() < 4; } )
| test::views::transform( []( auto const & value )
{ return test::views::all( value ); } );
}
int main()
{
for( auto const value : my_view() | test::views::join )
{
std::cout <<value <<" ";
}
std::cout <<std::endl;
return 0;
}
And the compiler error(s)
test_rng/test_rng_simpler.C: In function ‘auto my_view()’:
test_rng/test_rng_simpler.C:28:3: error: no match for ‘operator|’ (operand types are ‘std::remove_reference<ranges::cache1_view<ranges::generate_view<my_view()::<lambda()> > >&>::type’ {aka ‘ranges::cache1_view<ranges::generate_view<my_view()::<lambda()> > >’} and ‘std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{my_view()::<lambda(const auto:16&)>}>::<lambda(_Range&&)> >’)
27 | return std::move( gen )
| ~~~~~~~~~~~~~~~~
| |
| std::remove_reference<ranges::cache1_view<ranges::generate_view<my_view()::<lambda()> > >&>::type {aka ranges::cache1_view<ranges::generate_view<my_view()::<lambda()> > >}
28 | | test::views::take_while( []( auto const & value ) { return value.size() < 4; } )
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{my_view()::<lambda(const auto:16&)>}>::<lambda(_Range&&)> >
In file included from test_rng/test_rng_simpler.C:6:
/opt/rh/devtoolset-10/root/usr/include/c++/10/ranges:1180:4: note: candidate: ‘template<class _Tp> constexpr auto std::ranges::views::__adaptor::operator|(const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>&, const std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{my_view()::<lambda(const auto:16&)>}>::<lambda(_Range&&)> >&)’
1180 | operator|(const _RangeAdaptorClosure<_Tp>& __x,
| ^~~~~~~~
/opt/rh/devtoolset-10/root/usr/include/c++/10/ranges:1180:4: note: template argument deduction/substitution failed:
test_rng/test_rng_simpler.C:28:84: note: ‘std::remove_reference<ranges::cache1_view<ranges::generate_view<my_view()::<lambda()> > >&>::type’ {aka ‘ranges::cache1_view<ranges::generate_view<my_view()::<lambda()> > >’} is not derived from ‘const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>’
28 | | test::views::take_while( []( auto const & value ) { return value.size() < 4; } )
| ^
In file included from test_rng/test_rng_simpler.C:6:
/opt/rh/devtoolset-10/root/usr/include/c++/10/ranges:1175:4: note: candidate: ‘constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>&) [with _Range = ranges::cache1_view<ranges::generate_view<my_view()::<lambda()> > >; _Callable = std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{my_view()::<lambda(const auto:16&)>}>::<lambda(_Range&&)>]’
1175 | operator|(_Range&& __r, const _RangeAdaptorClosure& __o)
| ^~~~~~~~
/opt/rh/devtoolset-10/root/usr/include/c++/10/ranges:1175:4: note: constraints not satisfied
test_rng/test_rng_simpler.C: In instantiation of ‘constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, const std::ranges::views::__adaptor::_RangeAdaptorClosure<_Callable>&) [with _Range = ranges::cache1_view<ranges::generate_view<my_view()::<lambda()> > >; _Callable = std::ranges::views::__adaptor::_RangeAdaptor<_Callable>::operator()<{my_view()::<lambda(const auto:16&)>}>::<lambda(_Range&&)>]’:
test_rng/test_rng_simpler.C:28:84: required from here
/opt/rh/devtoolset-10/root/usr/include/c++/10/ranges:78:13: required for the satisfaction of ‘viewable_range<_Range>’ [with _Range = ranges::cache1_view<ranges::generate_view<my_view::._anon_131> >]
/opt/rh/devtoolset-10/root/usr/include/c++/10/ranges:79:31: note: no operand of the disjunction is satisfied
79 | && (borrowed_range<_Tp> || view<remove_cvref_t<_Tp>>);
| ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Perhaps I should stick with 'range-v3' until all of the views I need are available in the 'ranges' include?
Since the adapters in range-v3 do not inherit
ranges::view_interface
, this makes them not aview
in the standard. In order to avoid the danger of dangling, the standard prohibits passing arange
that does not model theborrowed_range
orview
(gen
in your example) into the pipe.What you need to do is to use a temporary variable to accept
generate
to make it an lvaluerange
, so that theborrowed_range
can be satisfied and the standard pipe operation can be used:Demo.