template<sized_range _Range>
using range_size_t = decltype(ranges::size(std::declval<_Range&>()));
+ template<typename _Derived>
+ requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
+ class view_interface; // defined in <bits/ranges_util.h>
+
+ namespace __detail
+ {
+ template<typename _Tp, typename _Up>
+ requires (!same_as<_Tp, view_interface<_Up>>)
+ void __is_derived_from_view_interface_fn(const _Tp&,
+ const view_interface<_Up>&); // not defined
+
+ // Returns true iff _Tp has exactly one public base class that's a
+ // specialization of view_interface.
+ template<typename _Tp>
+ concept __is_derived_from_view_interface
+ = requires (_Tp __t) { __is_derived_from_view_interface_fn(__t, __t); };
+ }
+
/// [range.view] The ranges::view_base type.
struct view_base { };
/// [range.view] The ranges::enable_view boolean.
template<typename _Tp>
- inline constexpr bool enable_view = derived_from<_Tp, view_base>;
+ inline constexpr bool enable_view = derived_from<_Tp, view_base>
+ || __detail::__is_derived_from_view_interface<_Tp>;
/// [range.view] The ranges::view concept.
template<typename _Tp>
{ return __y.__equal(__x); }
};
+ _Vp _M_base = _Vp();
[[no_unique_address]] __detail::__box<_Pred> _M_pred;
[[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin;
- _Vp _M_base = _Vp();
public:
filter_view() requires (default_initializable<_Vp>
constexpr
filter_view(_Vp __base, _Pred __pred)
- : _M_pred(std::move(__pred)), _M_base(std::move(__base))
+ : _M_base(std::move(__base)), _M_pred(std::move(__pred))
{ }
constexpr _Vp
friend _Sentinel<!_Const>;
};
- [[no_unique_address]] __detail::__box<_Fp> _M_fun;
_Vp _M_base = _Vp();
+ [[no_unique_address]] __detail::__box<_Fp> _M_fun;
public:
transform_view() requires (default_initializable<_Vp>
constexpr
transform_view(_Vp __base, _Fp __fun)
- : _M_fun(std::move(__fun)), _M_base(std::move(__base))
+ : _M_base(std::move(__base)), _M_fun(std::move(__fun))
{ }
constexpr _Vp
friend _Sentinel<!_Const>;
};
- range_difference_t<_Vp> _M_count = 0;
_Vp _M_base = _Vp();
+ range_difference_t<_Vp> _M_count = 0;
public:
take_view() requires default_initializable<_Vp> = default;
constexpr
take_view(_Vp base, range_difference_t<_Vp> __count)
- : _M_count(std::move(__count)), _M_base(std::move(base))
+ : _M_base(std::move(base)), _M_count(std::move(__count))
{ }
constexpr _Vp
friend _Sentinel<!_Const>;
};
- [[no_unique_address]] __detail::__box<_Pred> _M_pred;
_Vp _M_base = _Vp();
+ [[no_unique_address]] __detail::__box<_Pred> _M_pred;
public:
take_while_view() requires (default_initializable<_Vp>
constexpr
take_while_view(_Vp base, _Pred __pred)
- : _M_pred(std::move(__pred)), _M_base(std::move(base))
+ : _M_base(std::move(base)), _M_pred(std::move(__pred))
{ }
constexpr _Vp
class drop_view : public view_interface<drop_view<_Vp>>
{
private:
- range_difference_t<_Vp> _M_count = 0;
_Vp _M_base = _Vp();
+ range_difference_t<_Vp> _M_count = 0;
// ranges::next(begin(base), count, end(base)) is O(1) if _Vp satisfies
// both random_access_range and sized_range. Otherwise, cache its result.
constexpr
drop_view(_Vp __base, range_difference_t<_Vp> __count)
- : _M_count(__count), _M_base(std::move(__base))
+ : _M_base(std::move(__base)), _M_count(__count)
{ __glibcxx_assert(__count >= 0); }
constexpr _Vp
class drop_while_view : public view_interface<drop_while_view<_Vp, _Pred>>
{
private:
+ _Vp _M_base = _Vp();
[[no_unique_address]] __detail::__box<_Pred> _M_pred;
[[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin;
- _Vp _M_base = _Vp();
public:
drop_while_view() requires (default_initializable<_Vp>
constexpr
drop_while_view(_Vp __base, _Pred __pred)
- : _M_pred(std::move(__pred)), _M_base(std::move(__base))
+ : _M_base(std::move(__base)), _M_pred(std::move(__pred))
{ }
constexpr _Vp
friend _Sentinel<!_Const>;
};
+ _Vp _M_base = _Vp();
[[no_unique_address]]
__detail::__non_propagating_cache<remove_cv_t<_InnerRange>> _M_inner;
- _Vp _M_base = _Vp();
public:
join_view() requires default_initializable<_Vp> = default;
{ ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); }
};
+ _Vp _M_base = _Vp();
_Pattern _M_pattern = _Pattern();
// XXX: _M_current is "present only if !forward_range<V>"
[[no_unique_address]]
__detail::__maybe_present_t<!forward_range<_Vp>,
__detail::__non_propagating_cache<iterator_t<_Vp>>> _M_current;
- _Vp _M_base = _Vp();
public:
constexpr
lazy_split_view(_Vp __base, _Pattern __pattern)
- : _M_pattern(std::move(__pattern)), _M_base(std::move(__base))
+ : _M_base(std::move(__base)), _M_pattern(std::move(__pattern))
{ }
template<input_range _Range>
&& constructible_from<_Pattern, single_view<range_value_t<_Range>>>
constexpr
lazy_split_view(_Range&& __r, range_value_t<_Range> __e)
- : _M_pattern(views::single(std::move(__e))),
- _M_base(views::all(std::forward<_Range>(__r)))
+ : _M_base(views::all(std::forward<_Range>(__r))),
+ _M_pattern(views::single(std::move(__e)))
{ }
constexpr _Vp
class split_view : public view_interface<split_view<_Vp, _Pattern>>
{
private:
+ _Vp _M_base = _Vp();
_Pattern _M_pattern = _Pattern();
__detail::__non_propagating_cache<subrange<iterator_t<_Vp>>> _M_cached_begin;
- _Vp _M_base = _Vp();
struct _Iterator;
struct _Sentinel;
constexpr
split_view(_Vp __base, _Pattern __pattern)
- : _M_pattern(std::move(__pattern)),
- _M_base(std::move(__base))
+ : _M_base(std::move(__base)), _M_pattern(std::move(__pattern))
{ }
template<forward_range _Range>
&& constructible_from<_Pattern, single_view<range_value_t<_Range>>>
constexpr
split_view(_Range&& __r, range_value_t<_Range> __e)
- : _M_pattern(views::single(std::move(__e))),
- _M_base(views::all(std::forward<_Range>(__r)))
+ : _M_base(views::all(std::forward<_Range>(__r))),
+ _M_pattern(views::single(std::move(__e)))
{ }
constexpr _Vp
&& sized_sentinel_for<sentinel_t<_Vp>,
iterator_t<_Vp>>);
+ _Vp _M_base = _Vp();
[[no_unique_address]]
__detail::__maybe_present_t<_S_needs_cached_begin,
__detail::_CachedPosition<_Vp>>
_M_cached_begin;
- _Vp _M_base = _Vp();
public:
reverse_view() requires default_initializable<_Vp> = default;
template<typename T>
struct test_view
: __gnu_test::test_random_access_range<T>, std::ranges::view_base
-{
- // views must be default-initializable:
- test_view() : __gnu_test::test_random_access_range<T>(nullptr, nullptr) { }
-};
+{ };
static_assert(std::ranges::view<test_view<int>>);
constexpr bool std::ranges::enable_view<test_view<long>> = false;
static_assert(!std::ranges::view<test_view<long>>);
+
+void
+test01()
+{
+ // Verify LWG 3549 changes to ranges::enable_view.
+ using std::ranges::view_interface;
+
+ struct v1
+ : __gnu_test::test_random_access_range<int>, view_interface<v1> { };
+ static_assert(!std::derived_from<v1, std::ranges::view_base>);
+ static_assert(std::ranges::enable_view<v1>);
+
+ struct v2 : v1, view_interface<v2> { };
+ static_assert(!std::derived_from<v2, std::ranges::view_base>);
+ static_assert(!std::ranges::enable_view<v2>);
+
+ struct v3 : __gnu_test::test_random_access_range<int> { };
+ static_assert(!std::derived_from<v3, std::ranges::view_base>);
+ static_assert(!std::ranges::enable_view<v3>);
+
+ struct v4 { };
+ static_assert(!std::ranges::enable_view<view_interface<v4>>);
+}