| // RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter -verify=expected,both %s |
| // RUN: %clang_cc1 -std=c++2c -verify=ref,both %s |
| |
| // both-no-diagnostics |
| |
| namespace std { |
| inline namespace { |
| template <class _Tp, _Tp __v> struct integral_constant { |
| static const _Tp value = __v; |
| }; |
| template <bool _Val> using _BoolConstant = integral_constant<bool, _Val>; |
| template <class _Tp> using __remove_cv_t = __remove_cv(_Tp); |
| template <class _Tp> using remove_cv_t = __remove_cv_t<_Tp>; |
| template <class _From, class _To> |
| constexpr bool is_convertible_v = __is_convertible(_From, _To); |
| template <class _Tp> _Tp __declval(long); |
| template <class _Tp> decltype(__declval<_Tp>(0)) declval(); |
| template <class _From, class _To> |
| concept convertible_to = is_convertible_v<_From, _To> && |
| requires { static_cast<_To>(declval<_From>()); }; |
| template <class _Tp> constexpr bool is_reference_v = __is_reference(_Tp); |
| template <class _Tp> |
| constexpr bool is_lvalue_reference_v = __is_lvalue_reference(_Tp); |
| template <class> |
| constexpr bool is_nothrow_destructible_v = |
| integral_constant<bool, __is_nothrow_destructible(int)>::value; |
| template <class _Tp> |
| concept destructible = is_nothrow_destructible_v<_Tp>; |
| template <class _Tp, class _Up> |
| using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>; |
| template <class... _Args> |
| constexpr bool is_constructible_v = __is_constructible(_Args...); |
| template <class _Tp, class... _Args> |
| concept constructible_from = destructible<_Tp> && is_constructible_v<_Tp>; |
| template <class _Tp> |
| concept move_constructible = |
| constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; |
| template <class _Tp, class _Up> |
| concept __same_as_impl = _IsSame<_Tp, _Up>::value; |
| template <class _Tp, class _Up> |
| concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; |
| template <bool> struct _IfImpl; |
| template <> struct _IfImpl<false> { |
| template <class, class _ElseRes> using _Select = _ElseRes; |
| }; |
| template <bool _Cond, class _IfRes, class _ElseRes> |
| using _If = _IfImpl<_Cond>::template _Select<_IfRes, _ElseRes>; |
| template <class _If> struct conditional { |
| using type = _If; |
| }; |
| template <bool, class _IfRes, class> |
| using conditional_t = conditional<_IfRes>::type; |
| template <class _Tp> |
| using __libcpp_remove_reference_t = __remove_reference_t(_Tp); |
| template <class _Tp> |
| using remove_reference_t = __libcpp_remove_reference_t<_Tp>; |
| template <class _Tp> using __decay_t = __decay(_Tp); |
| template <class _Tp> using __remove_cvref_t = __remove_cvref(_Tp); |
| template <class _Tp> using remove_cvref_t = __remove_cvref_t<_Tp>; |
| struct __copy_cv { |
| template <class _To> using __apply = _To; |
| }; |
| template <class, class _To> using __copy_cv_t = __copy_cv::__apply<_To>; |
| template <class _Xp, class _Yp> |
| using __cond_res = |
| decltype(false ? std::declval<_Xp (&)()>()() : std::declval<_Yp (&)()>()()); |
| template <class _Ap, class _Bp, class = remove_reference_t<_Ap>, |
| class = remove_reference_t<_Bp>> |
| struct __common_ref; |
| template <class _Ap, class _Bp, class, class> |
| struct __common_ref : __common_ref<_Bp, _Ap> {}; |
| template <class _Xp, class _Yp> |
| using __common_ref_t = __common_ref<_Xp, _Yp>::__type; |
| template <class _Xp, class _Yp> |
| using __cv_cond_res = |
| __cond_res<__copy_cv_t<_Xp, _Yp> &, __copy_cv_t<_Yp, _Xp> &>; |
| template <class _Ap, class _Bp, class _Xp, class _Yp> |
| requires requires { typename __cv_cond_res<_Xp, _Yp>; } && |
| is_reference_v<__cv_cond_res<_Xp, _Yp>> |
| struct __common_ref<_Ap, _Bp &, _Xp, _Yp> { |
| using __type = __cv_cond_res<_Xp, _Yp>; |
| }; |
| template <class _Tp, class _Up> |
| using __common_ref_D = __common_ref_t<const _Tp, _Up &>; |
| template <class _Ap, class _Bp, class _Xp, class _Yp> |
| requires requires { typename __common_ref_D<_Xp, _Yp>; } && |
| is_convertible_v<_Ap, __common_ref_D<_Xp, _Yp>> |
| struct __common_ref<_Ap &&, _Bp &, _Xp, _Yp> { |
| using __type = __common_ref_D<_Xp, _Yp>; |
| }; |
| template <class...> struct common_reference; |
| template <class... _Types> |
| using common_reference_t = common_reference<_Types...>::type; |
| template <class, class> struct __common_reference_sub_bullet1; |
| template <class _Tp, class _Up> |
| struct common_reference<_Tp, _Up> : __common_reference_sub_bullet1<_Tp, _Up> {}; |
| template <class _Tp, class _Up> |
| requires is_reference_v<_Tp> && is_reference_v<_Up> && |
| requires { typename __common_ref_t<_Tp, _Up>; } |
| struct __common_reference_sub_bullet1<_Tp, _Up> { |
| using type = __common_ref_t<_Tp, _Up>; |
| }; |
| template <class _Tp, class _Up> |
| concept common_reference_with = |
| same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> && |
| convertible_to<_Tp, common_reference_t<_Tp, _Up>> && |
| convertible_to<_Up, common_reference_t<_Tp, _Up>>; |
| template <class _Tp> |
| using __make_const_lvalue_ref = __libcpp_remove_reference_t<_Tp> &; |
| template <class _Lhs, class _Rhs> |
| concept assignable_from = |
| is_lvalue_reference_v<_Lhs> && |
| common_reference_with<__make_const_lvalue_ref<_Lhs>, |
| __make_const_lvalue_ref<_Rhs>> && |
| requires(_Lhs __lhs, _Rhs __rhs) { |
| { __rhs } -> same_as<_Lhs>; |
| }; |
| template <class _Tp> constexpr __libcpp_remove_reference_t<_Tp> &&move(_Tp &&); |
| typedef int type; |
| template <bool, class = void> using __enable_if_t = type; |
| namespace ranges { |
| inline namespace { |
| auto swap = int{}; |
| } |
| } // namespace ranges |
| template <class _Tp> constexpr bool is_object_v = __is_object(_Tp); |
| template <class _Tp> |
| concept movable = is_object_v<_Tp> && move_constructible<_Tp> && |
| assignable_from<_Tp &, _Tp>; |
| template <decltype(sizeof(int)), class> struct tuple_element; |
| template <class...> class tuple; |
| template <template <class> class _Templ, class... _Args, |
| class = _Templ<_Args...>> |
| integral_constant<bool, true> __sfinae_test_impl(int); |
| template <template <class> class, class> |
| integral_constant<bool, false> __sfinae_test_impl(...); |
| template <template <class> class _Templ, class... _Args> |
| using _IsValidExpansion = |
| decltype(std::__sfinae_test_impl<_Templ, _Args...>(0)); |
| template <class _Tp> |
| using __test_for_primary_template = |
| __enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>; |
| template <class _Tp> |
| using __is_primary_template = |
| _IsValidExpansion<__test_for_primary_template, _Tp>; |
| template <class> struct iterator_traits; |
| template <class> struct __cond_value_type; |
| template <class _Tp> |
| requires is_object_v<_Tp> |
| struct __cond_value_type<_Tp> { |
| using value_type = remove_cv_t<_Tp>; |
| }; |
| template <class> struct indirectly_readable_traits; |
| template <class _Tp> |
| struct indirectly_readable_traits<_Tp *> : __cond_value_type<_Tp> {}; |
| template <bool> struct _OrImpl; |
| template <> struct _OrImpl<true> { |
| template <class, class _First, class... _Rest> |
| using _Result = _OrImpl<!(_First::value) && |
| sizeof...(_Rest)>::template _Result<_First, _Rest...>; |
| }; |
| template <> struct _OrImpl<false> { |
| template <class _Res, class...> using _Result = _Res; |
| }; |
| template <class... _Args> |
| using _Or = |
| _OrImpl<sizeof...(_Args) != |
| 0>::template _Result<integral_constant<bool, false>, _Args...>; |
| template <class _Tp> using __with_reference = _Tp; |
| template <class _Tp> |
| concept __can_reference = requires { typename __with_reference<_Tp>; }; |
| template <class _Tp> |
| concept __dereferenceable = requires(_Tp __t) { |
| { __t }; |
| }; |
| template <__dereferenceable _Tp> |
| using iter_reference_t = decltype(*std::declval<_Tp>()); |
| struct input_iterator_tag {}; |
| struct contiguous_iterator_tag : input_iterator_tag {}; |
| template <class> struct __iter_traits_cache { |
| using type = _If<__is_primary_template<iterator_traits<int>>::value, int, |
| iterator_traits<int>>; |
| }; |
| template <class _Iter> using _ITER_TRAITS = __iter_traits_cache<_Iter>::type; |
| struct __iter_concept_concept_test { |
| template <class _Iter> using _Apply = _ITER_TRAITS<_Iter>::iterator_concept; |
| }; |
| template <class, class _Tester> |
| struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, int>, |
| _Tester {}; |
| template <class _Iter> struct __iter_concept_cache { |
| using type = |
| _Or<__test_iter_concept<_Iter, __iter_concept_concept_test>, |
| __test_iter_concept<_Iter, int>, __test_iter_concept<_Iter, int>>; |
| }; |
| template <class _Iter> |
| using _ITER_CONCEPT = __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; |
| template <class _Tp> |
| requires is_object_v<_Tp> |
| struct iterator_traits<_Tp> { |
| typedef contiguous_iterator_tag iterator_concept; |
| }; |
| template <class _Ip> |
| using iter_value_t = conditional_t< |
| __is_primary_template<iterator_traits<remove_cvref_t<_Ip>>>::value, |
| indirectly_readable_traits<remove_cvref_t<_Ip>>, |
| iterator_traits<remove_cvref_t<_Ip>>>::value_type; |
| template <class _Tp> _Tp *addressof(_Tp &); |
| template <class _Bp, class _Dp> |
| constexpr bool is_base_of_v = __is_base_of(_Bp, _Dp); |
| template <class _Dp, class _Bp> |
| concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v<_Dp *, _Bp *>; |
| namespace ranges { |
| struct Trans_NS___iter_move___fn { |
| template <class _Ip> |
| auto operator()(_Ip __i) -> decltype(std::move(*__i)); |
| }; |
| auto iter_move = Trans_NS___iter_move___fn{}; |
| } // namespace ranges |
| template <__dereferenceable _Tp> |
| requires requires { |
| { ranges::iter_move }; |
| } |
| using iter_rvalue_reference_t = |
| decltype(ranges::iter_move(std::declval<_Tp>())); |
| template <class _In> |
| concept __indirectly_readable_impl = |
| requires { typename iter_value_t<_In>; } && |
| common_reference_with<iter_reference_t<_In>, iter_value_t<_In> &> && |
| common_reference_with<iter_reference_t<_In>, |
| iter_rvalue_reference_t<_In>> && |
| common_reference_with<iter_rvalue_reference_t<_In>, iter_value_t<_In> &>; |
| template <class _In> |
| concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In>>; |
| template <class _Ip> |
| concept weakly_incrementable = |
| !same_as<_Ip, bool> && movable<_Ip> && requires(_Ip __i) { __i; }; |
| template <class _Ip> |
| concept input_or_output_iterator = requires(_Ip __i) { |
| { __i }; |
| } && weakly_incrementable<_Ip>; |
| template <class _Ip> |
| concept input_iterator = |
| input_or_output_iterator<_Ip> && indirectly_readable<_Ip> && requires { |
| typename _ITER_CONCEPT<_Ip>; |
| } && derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>; |
| namespace ranges { |
| struct __fn { |
| template <class _Tp, decltype(sizeof(int)) _Np> |
| constexpr auto operator()(_Tp (&__t)[_Np]) const |
| { |
| return __t; |
| } |
| template <class _Tp> constexpr auto operator()(_Tp __t) const { |
| return static_cast<std::__decay_t<decltype((__t.begin()))>>(__t.begin()); |
| } |
| }; |
| inline namespace { |
| auto begin = __fn{}; |
| } |
| template <class _Tp> |
| using iterator_t = decltype(ranges::begin(std::declval<_Tp &>())); |
| inline namespace { |
| auto end = int{}; |
| } |
| template <class _Derived> |
| class view_interface; |
| template <class _Op, class _Yp> |
| requires is_convertible_v<_Op, view_interface<_Yp>> |
| void __is_derived_from_view_interface(); |
| template <class _Tp> |
| bool enable_view = derived_from<_Tp, int> || |
| requires { ranges::__is_derived_from_view_interface; }; |
| template <class> |
| concept range = requires { ranges::end; }; |
| template <class _Tp> |
| concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>; |
| template <class _Tp> |
| concept view = range<_Tp> && movable<_Tp> && enable_view<_Tp>; |
| template <class _Tp> |
| concept viewable_range = |
| range<_Tp> && |
| ((view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>>) || |
| (!view<remove_cvref_t<_Tp>> && (is_lvalue_reference_v<_Tp>))); |
| } // namespace ranges |
| template <decltype(sizeof(int))...> struct __tuple_indices; |
| template <class _IdxType, _IdxType... _Values> struct __integer_sequence { |
| template <decltype(sizeof(int)) _Sp> |
| using __to_tuple_indices = __tuple_indices<(_Values)...>; |
| }; |
| template <decltype(sizeof(int)) _Ep, decltype(sizeof(int)) _Sp> |
| using __make_indices_imp = |
| __make_integer_seq<__integer_sequence, decltype(sizeof(int)), |
| _Sp>::template __to_tuple_indices<_Sp>; |
| template <int _Ep, decltype(sizeof(int)) _Sp = 0> struct __make_tuple_indices { |
| typedef __make_indices_imp<_Ep, _Sp> type; |
| }; |
| template <class...> struct __tuple_types; |
| namespace ranges { |
| template <class _Derived> |
| class view_interface {}; |
| } // namespace ranges |
| template <decltype(sizeof(int)) _Ip, class... _Types> |
| struct tuple_element<_Ip, __tuple_types<_Types...>> { |
| using type = __type_pack_element<_Ip, _Types...>; |
| }; |
| template <decltype(sizeof(int)) _Ip, class... _Tp> |
| struct tuple_element<_Ip, tuple<_Tp...>> { |
| using type = tuple_element<_Ip, __tuple_types<_Tp...>>::type; |
| }; |
| |
| template <class... _Tp> struct tuple { |
| int __value_; |
| constexpr int get() { return __value_; } |
| }; |
| template <int _Ip, class... _Tp> constexpr void get(tuple<_Tp...> __t) { |
| __t.get(); |
| } |
| namespace ranges { |
| template <class _Tp> |
| struct __range_adaptor_closure {}; |
| template <range _Range> |
| requires is_object_v<_Range> |
| struct ref_view : view_interface<ref_view<_Range>> { |
| _Range *__range_; |
| |
| template <class _Tp> |
| constexpr ref_view(_Tp &&__t) |
| : __range_(std::addressof(static_cast<_Range &>(__t))) {} |
| constexpr iterator_t<_Range> begin() { return ranges::begin(*__range_); } |
| }; |
| template <class _Range> ref_view(_Range &) -> ref_view<_Range>; |
| } // namespace ranges |
| namespace ranges::views { |
| struct __fn : __range_adaptor_closure<__fn> { |
| template <class _Tp> auto operator()(_Tp &&__t) const { |
| return ranges::ref_view{__t}; |
| } |
| }; |
| inline namespace { |
| auto all = __fn{}; |
| } |
| template <ranges::viewable_range _Range> |
| using all_t = decltype(views::all(std::declval<_Range>())); |
| } // namespace ranges::views |
| namespace ranges { |
| template <input_range _View, decltype(sizeof(int)) _Np> |
| struct elements_view : view_interface<elements_view<_View, _Np>> { |
| class __iterator; |
| |
| constexpr elements_view(_View __base) : __base_(std::move(__base)) {} |
| constexpr auto begin() const { return __iterator(ranges::begin(__base_)); } |
| |
| _View __base_ = _View(); |
| }; |
| template <input_range _View, decltype(sizeof(int)) _Np> |
| struct elements_view<_View, _Np>::__iterator { |
| iterator_t<_View> __current_; |
| |
| constexpr void operator*() { |
| auto a = *__current_; |
| } |
| }; |
| namespace views { |
| namespace __elements { |
| template <int _Np> struct __fn : __range_adaptor_closure<__fn<_Np>> { |
| template <class _Range> |
| constexpr auto operator()(_Range &&__range) const |
| -> decltype(elements_view<all_t<_Range>, _Np>(__range)) { |
| return elements_view<all_t<_Range>, _Np>(__range); |
| } |
| }; |
| } // namespace __elements |
| inline namespace { |
| template <decltype(sizeof(int)) _Np> auto elements = __elements::__fn<_Np>{}; |
| } |
| } // namespace views |
| } // namespace ranges |
| } // namespace |
| } // namespace std |
| constexpr bool test() { |
| std::tuple<short, long> ts[]{{}}; |
| |
| |
| auto ev = std::ranges::views::elements<1>(ts); |
| auto it = ev.begin(); |
| |
| *it; |
| return true; |
| } |
| static_assert(test()); |