@@ -63,7 +63,8 @@ struct properties_sorter<std::integer_sequence<int, IdxSeq...>,
63
63
static constexpr auto sorted_indices = []() constexpr {
64
64
int idx = 0 ;
65
65
int N = sizeof ...(property_tys);
66
- // TODO: Use C++20 constexpr std::sort if available.
66
+ // std::sort isn't constexpr until C++20. Also, it's possible there will be
67
+ // a compiler builtin to sort types, in which case we should start using it.
67
68
std::array to_sort{std::pair{property_tys::property_name, idx++}...};
68
69
auto swap_pair = [](auto &x, auto &y) constexpr {
69
70
auto tmp_first = x.first ;
@@ -89,8 +90,10 @@ struct properties_sorter<std::integer_sequence<int, IdxSeq...>,
89
90
nth_type_t <sorted_indices[IdxSeq], property_tys...>...>;
90
91
};
91
92
93
+ // Is used to implement `is_property_v`.
92
94
struct property_key_tag_base {};
93
95
96
+ // We support incomplete property_key_t, so need to wrap it.
94
97
template <typename property_key_t >
95
98
struct property_key_tag : property_key_tag_base {};
96
99
@@ -99,8 +102,10 @@ struct property_base : property_key_tag<property_key_t> {
99
102
protected:
100
103
using key_t = property_key_t ;
101
104
constexpr property_t get_property (property_key_tag<key_t >) const {
102
- // https://godbolt.org/z/MY6849jGh for a reduced test reflecting original
103
- // implementation that worked with clang/msvc and failed with gcc.
105
+ // In fact, `static_cast` below works just fine with clang/msvc but not with
106
+ // gcc, see https://godbolt.org/z/MY6849jGh for a reduced test. However, we
107
+ // need to support all ,so special case for compile-time properties (when
108
+ // `is_empty_v` is true).
104
109
if constexpr (std::is_empty_v<property_t >) {
105
110
return property_t {};
106
111
} else {
@@ -132,6 +137,11 @@ inline constexpr bool properties_are_sorted = []() constexpr {
132
137
} else {
133
138
const std::array sort_keys = {property_tys::property_name...};
134
139
// std::is_sorted isn't constexpr until C++20.
140
+ //
141
+ // Sorting is an implementation detail while uniqueness of the property_keys
142
+ // is an API restriction. This internal check actually combines both
143
+ // conditions as we expect that user error is handled before the internal
144
+ // `properties_are_sorted` assert is checked.
135
145
for (std::size_t idx = 1 ; idx < sort_keys.size (); ++idx)
136
146
if (sort_keys[idx - 1 ] >= sort_keys[idx])
137
147
return false ;
@@ -153,10 +163,14 @@ inline constexpr bool is_property_v =
153
163
std::is_base_of_v<detail::property_key_tag_base, T> &&
154
164
!is_property_list_v<T>;
155
165
166
+ // Empty property list.
156
167
template <> class properties <detail::properties_type_list<>, void > {
157
168
template <typename > static constexpr bool has_property () { return false ; }
158
169
};
159
170
171
+ // Base implementation to provide nice user error in case of mis-use. Without it
172
+ // an error "base class '<property>' specified more than once as a direct base
173
+ // class" is reported prior to static_assert's error.
160
174
template <typename ... property_tys>
161
175
class properties <
162
176
detail::properties_type_list<property_tys...>,
@@ -184,7 +198,6 @@ class __SYCL_EBO
184
198
constexpr properties (unsorted_property_tys... props)
185
199
: unsorted_property_tys(props)... {}
186
200
187
- // TODO: add a unit-test for this.
188
201
template <
189
202
typename ... other_property_list_tys, typename ... other_property_tys,
190
203
typename = std::enable_if_t <((is_property_v<other_property_tys> && ...))>>
0 commit comments