@@ -26,6 +26,10 @@ inline namespace reflection_v2
26
26
// std::meta::info
27
27
using info = decltype(^int);
28
28
29
+ // concept reflection_range
30
+ template <typename R>
31
+ concept reflection_range = see below;
32
+
29
33
// name and location
30
34
consteval auto name_of(info) -> string_view;
31
35
consteval auto display_name_of(info) -> string_view;
@@ -54,15 +58,27 @@ consteval auto subobjects_of(info class_type) -> vector<info>;
54
58
consteval auto enumerators_of(info enum_type) -> vector<info>;
55
59
56
60
// substitute
57
- consteval auto can_substitute(info templ, span<info const>) -> bool;
58
- consteval auto substitute(info templ, span<info const>) -> info;
61
+ template <reflection_range R = span<info const>>
62
+ consteval auto can_substitute(info templ, R &&args) -> bool;
63
+ template <reflection_range R = span<info const>>
64
+ consteval auto substitute(info templ, R &&args) -> info;
65
+
66
+ // reflect_invoke
67
+ template <reflection_range R = span<info const>>
68
+ consteval auto reflect_invoke(info target, R &&args) -> info;
69
+
70
+ // reflect expression results
71
+ consteval auto reflect_value(auto) -> info;
72
+ consteval auto reflect_object(auto &) -> info;
73
+ consteval auto reflect_function(auto &) -> info;
59
74
60
75
// extract<T>
61
76
template <typename Ty>
62
77
consteval auto extract(info) -> T;
63
78
64
79
// test_type
65
80
consteval auto test_type(info templ, info type) -> bool;
81
+ template <reflection_range R = span<info const>>
66
82
consteval auto test_types(info templ, span<info const> types) -> bool;
67
83
68
84
// other type predicates
@@ -103,18 +119,11 @@ consteval auto is_constructor(info) -> bool;
103
119
consteval auto is_destructor(info) -> bool;
104
120
consteval auto is_special_member(info) -> bool;
105
121
106
- // reflect expression results
107
- consteval auto reflect_value(auto) -> info;
108
- consteval auto reflect_object(auto &) -> info;
109
- consteval auto reflect_function(auto &) -> info;
110
-
111
- // reflect_invoke
112
- consteval auto reflect_invoke(info target, span<info const> args) -> info;
113
-
114
122
// define_class
115
123
struct data_member_options_t;
116
124
consteval auto data_member_spec(info class_type,
117
125
data_member_options = {}) -> info;
126
+ template <reflection_range R = span<info const>>
118
127
consteval auto define_class(info class_type, span<info const>) -> info;
119
128
120
129
// data layout
@@ -137,6 +146,7 @@ consteval auto has_default_argument(info) -> bool;
137
146
138
147
#include < experimental/__config>
139
148
#include < optional>
149
+ #include < ranges>
140
150
#include < source_location>
141
151
#include < span>
142
152
#include < string_view>
@@ -150,6 +160,12 @@ _LIBCPP_BEGIN_NAMESPACE_META_V2
150
160
// An opaque handle to a reflected entity.
151
161
using info = decltype(^int );
152
162
163
+ template <typename R>
164
+ concept reflection_range =
165
+ ranges::input_range<R> &&
166
+ same_as<ranges::range_value_t <R>, info> &&
167
+ same_as<remove_cvref_t <ranges::range_reference_t <R>>, info>;
168
+
153
169
namespace detail {
154
170
enum : unsigned {
155
171
@@ -613,26 +629,41 @@ consteval auto enumerators_of(info r) -> vector<info> {
613
629
}
614
630
615
631
// Returns whether 'templ' substituted with 'args' forms a valid template-id.
616
- consteval auto can_substitute (info templ, span<info const > args) -> bool {
617
- return __metafunction (detail::__metafn_can_substitute, templ,
618
- args.data (), args.size ());
632
+ template <reflection_range R = span<info const >>
633
+ consteval auto can_substitute (info templ, R &&args) -> bool {
634
+ if constexpr (ranges::contiguous_range<R>) {
635
+ return __metafunction (detail::__metafn_can_substitute, templ,
636
+ ranges::data (args), ranges::size (args));
637
+ } else {
638
+ vector vargs = args | ranges::to<vector>();
639
+ return __metafunction (detail::__metafn_can_substitute, templ,
640
+ vargs.data (), vargs.size ());
641
+ }
619
642
}
620
643
621
644
// Returns a reflection representing the template instantiation of the entity
622
645
// reflected by 'templ' with the entities reflected by 'args'.
623
- consteval auto substitute (info templ, span<info const > args) -> info {
624
- return __metafunction (detail::__metafn_substitute, templ,
625
- args.data (), args.size ());
646
+ template <reflection_range R = span<info const >>
647
+ consteval auto substitute (info templ, R &&args) -> info {
648
+ if constexpr (ranges::contiguous_range<R>) {
649
+ return __metafunction (detail::__metafn_substitute, templ,
650
+ ranges::data (args), ranges::size (args));
651
+ } else {
652
+ vector vargs = args | ranges::to<vector>();
653
+ return __metafunction (detail::__metafn_substitute, templ, vargs.data (),
654
+ vargs.size ());
655
+ }
626
656
}
627
657
628
658
// Returns the value or object from 'r' if 'r' is a reflection of a value
629
659
// or object having type 'T'.
630
- template <typename Ty> requires (!std:: is_rvalue_reference_v<Ty>)
660
+ template <typename Ty> requires (!is_rvalue_reference_v<Ty>)
631
661
consteval auto extract(info r) -> Ty {
632
662
return __metafunction (detail::__metafn_extract, ^Ty, r);
633
663
}
634
664
635
- consteval auto test_types (info templ, span<info const > args) -> bool {
665
+ template <reflection_range R = span<info const >>
666
+ consteval auto test_types (info templ, R &&args) -> bool {
636
667
return extract<bool >(substitute (templ, args));
637
668
}
638
669
@@ -806,25 +837,34 @@ consteval auto is_special_member(info r) -> bool {
806
837
807
838
// Returns a reflection of the value held by the provided argument.
808
839
consteval auto reflect_value (auto r) -> info {
809
- constexpr std::meta::info Ty = type_of (^r);
840
+ static_assert (!is_reference_v<decltype (r)>,
841
+ " values cannot have reference type" );
842
+
843
+ constexpr info Ty = type_of (^r);
810
844
811
845
return __metafunction (detail::__metafn_reflect_result, Ty,
812
846
static_cast <typename [:Ty:]>(r));
813
847
}
814
848
815
849
// Returns a reflection of the object designated by the provided argument.
816
850
consteval auto reflect_object (auto &r) -> info {
851
+ static_assert (is_lvalue_reference_v<decltype (r)>,
852
+ " objects must be designated by lvalue references" );
853
+
817
854
constexpr auto Ty = type_of (^r);
818
855
819
- static_assert (!is_function_v<std:: remove_reference<typename [:Ty:]>>,
856
+ static_assert (!is_function_v<remove_reference<typename [:Ty:]>>,
820
857
" use 'reflect_function' for references to functions" );
821
858
return __metafunction (detail::__metafn_reflect_result, Ty, r);
822
859
}
823
860
824
861
// Returns a reflection of the object designated by the provided argument.
825
862
consteval auto reflect_function (auto &r) -> info {
863
+ static_assert (is_lvalue_reference_v<decltype (r)>,
864
+ " functions must be designated by lvalue references" );
865
+
826
866
constexpr auto Ty = type_of (^r);
827
- using UnrefTy = std:: remove_reference_t <[:Ty:]>;
867
+ using UnrefTy = remove_reference_t <[:Ty:]>;
828
868
829
869
constexpr bool IsPtr = is_pointer_v<UnrefTy>;
830
870
static_assert (!IsPtr, " use 'reflect_value' for pointers to functions" );
@@ -838,9 +878,16 @@ consteval auto reflect_function(auto &r) -> info {
838
878
839
879
// Returns a reflection of the constant value obtained from calling
840
880
// target(args...)
841
- consteval auto reflect_invoke (info target, span<info const > args) -> info {
842
- return __metafunction (detail::__metafn_reflect_invoke, target,
843
- args.data (), args.size ());
881
+ template <reflection_range R = span<info const >>
882
+ consteval auto reflect_invoke (info target, R &&args) -> info {
883
+ if constexpr (ranges::contiguous_range<R>) {
884
+ return __metafunction (detail::__metafn_reflect_invoke, target,
885
+ ranges::data (args), ranges::size (args));
886
+ } else {
887
+ vector vargs = args | ranges::to<vector>();
888
+ return __metafunction (detail::__metafn_reflect_invoke, target,
889
+ vargs.data (), vargs.size ());
890
+ }
844
891
}
845
892
846
893
// Representation of a data member which may be passed to 'data_member_spec'.
@@ -869,10 +916,16 @@ consteval auto data_member_spec(info member_type,
869
916
870
917
// Completes the definition of the record type reflected by 'class_type' with
871
918
// the members described by the reflections in the provided span.
872
- consteval auto define_class (info class_type,
873
- span<info const > members) -> info {
874
- return __metafunction (detail::__metafn_define_class, class_type,
875
- members.size (), members.data ());
919
+ template <reflection_range R = span<info const >>
920
+ consteval auto define_class (info class_type, R &&members) -> info {
921
+ if constexpr (ranges::contiguous_range<R>) {
922
+ return __metafunction (detail::__metafn_define_class, class_type,
923
+ ranges::size (members), ranges::data (members));
924
+ } else {
925
+ vector vmembers = members | ranges::to<vector>();
926
+ return __metafunction (detail::__metafn_define_class, class_type,
927
+ vmembers.size (), vmembers.data ());
928
+ }
876
929
}
877
930
878
931
// Returns the offset of the reflected entity.
@@ -928,7 +981,7 @@ template <typename Ty>
928
981
consteval auto reflect_result (Ty r) -> info {
929
982
constexpr auto DTy = dealias (^Ty);
930
983
constexpr auto RTy = is_class_v<[:DTy:]> || is_reference_v<[:DTy:]> ?
931
- DTy : ^std:: remove_cv_t <[:DTy:]>;
984
+ DTy : ^remove_cv_t <[:DTy:]>;
932
985
933
986
return __metafunction (detail::__metafn_reflect_result, dealias (RTy),
934
987
static_cast <typename [:DTy:]>(r));
0 commit comments