@@ -43,12 +43,6 @@ template <int N, typename... Ts>
43
43
using nth_type_t = typename nth_type<N, Ts...>::type;
44
44
#endif
45
45
46
- template <typename T, typename PropList> struct PrependProperty {};
47
- template <typename T, typename ... Ts>
48
- struct PrependProperty <T, properties_type_list<Ts...>> {
49
- using type = properties_type_list<T, Ts...>;
50
- };
51
-
52
46
// ******************************************************************************
53
47
// Property identification
54
48
// ******************************************************************************
@@ -63,91 +57,6 @@ struct AllPropertyValues<std::tuple<T, Ts...>>
63
57
AllPropertyValues<std::tuple<Ts...>>,
64
58
std::false_type> {};
65
59
66
- // ******************************************************************************
67
- // Property type sorting
68
- // ******************************************************************************
69
-
70
- // Splits a tuple into head and tail if ShouldSplit is true. If ShouldSplit is
71
- // false the head will be void and the tail will be the full tuple.
72
- template <typename T1, bool ShouldSplit> struct HeadSplit {};
73
- template <typename T, typename ... Ts>
74
- struct HeadSplit <properties_type_list<T, Ts...>, true > {
75
- using htype = T;
76
- using ttype = properties_type_list<Ts...>;
77
- };
78
- template <typename ... Ts> struct HeadSplit <properties_type_list<Ts...>, false > {
79
- using htype = void ;
80
- using ttype = properties_type_list<Ts...>;
81
- };
82
-
83
- // Selects the one of two types that is not void. This assumes that at least one
84
- // of the two template arguemnts is void.
85
- template <typename LHS, typename RHS> struct SelectNonVoid {};
86
- template <typename LHS> struct SelectNonVoid <LHS, void > {
87
- using type = LHS;
88
- };
89
- template <typename RHS> struct SelectNonVoid <void , RHS> {
90
- using type = RHS;
91
- };
92
-
93
- // ******************************************************************************
94
- // Property merging
95
- // ******************************************************************************
96
-
97
- // Merges two sets of properties, failing if two properties are the same but
98
- // with different values.
99
- // NOTE: This assumes that the properties are in sorted order.
100
- template <typename LHSPropertyT, typename RHSPropertyT> struct MergeProperties ;
101
-
102
- template <>
103
- struct MergeProperties <properties_type_list<>, properties_type_list<>> {
104
- using type = properties_type_list<>;
105
- };
106
-
107
- template <typename ... LHSPropertyTs>
108
- struct MergeProperties <properties_type_list<LHSPropertyTs...>,
109
- properties_type_list<>> {
110
- using type = properties_type_list<LHSPropertyTs...>;
111
- };
112
-
113
- template <typename ... RHSPropertyTs>
114
- struct MergeProperties <properties_type_list<>,
115
- properties_type_list<RHSPropertyTs...>> {
116
- using type = properties_type_list<RHSPropertyTs...>;
117
- };
118
-
119
- // Identical properties are allowed, but only one will carry over.
120
- template <typename PropertyT, typename ... LHSPropertyTs,
121
- typename ... RHSPropertyTs>
122
- struct MergeProperties <properties_type_list<PropertyT, LHSPropertyTs...>,
123
- properties_type_list<PropertyT, RHSPropertyTs...>> {
124
- using merge_tails =
125
- typename MergeProperties<properties_type_list<LHSPropertyTs...>,
126
- properties_type_list<RHSPropertyTs...>>::type;
127
- using type = typename PrependProperty<PropertyT, merge_tails>::type;
128
- };
129
-
130
- template <typename ... LHSPropertyTs, typename ... RHSPropertyTs>
131
- struct MergeProperties <properties_type_list<LHSPropertyTs...>,
132
- properties_type_list<RHSPropertyTs...>> {
133
- using l_head = nth_type_t <0 , LHSPropertyTs...>;
134
- using r_head = nth_type_t <0 , RHSPropertyTs...>;
135
- static_assert (
136
- PropertyID<l_head>::value != PropertyID<r_head>::value,
137
- " Failed to merge property lists due to conflicting properties." );
138
- static constexpr bool left_has_min =
139
- PropertyID<l_head>::value < PropertyID<r_head>::value;
140
- using l_split =
141
- HeadSplit<properties_type_list<LHSPropertyTs...>, left_has_min>;
142
- using r_split =
143
- HeadSplit<properties_type_list<RHSPropertyTs...>, !left_has_min>;
144
- using min = typename SelectNonVoid<typename l_split::htype,
145
- typename r_split::htype>::type;
146
- using merge_tails = typename MergeProperties<typename l_split::ttype,
147
- typename r_split::ttype>::type;
148
- using type = typename PrependProperty<min, merge_tails>::type;
149
- };
150
-
151
60
// ******************************************************************************
152
61
// Property value tooling
153
62
// ******************************************************************************
@@ -349,6 +258,44 @@ constexpr auto filter_properties(
349
258
return filter_properties_impl<predicate, property_tys...>::apply (props);
350
259
}
351
260
261
+ template <typename ... lhs_property_tys> struct merge_filter {
262
+ template <typename rhs_property_ty>
263
+ struct predicate
264
+ : std::bool_constant<!((std::is_same_v<typename lhs_property_tys::key_t ,
265
+ typename rhs_property_ty::key_t > ||
266
+ ...))> {};
267
+ };
268
+
269
+ template <typename ... lhs_property_tys, typename ... rhs_property_tys>
270
+ constexpr auto merge_properties (
271
+ const properties<properties_type_list<lhs_property_tys...>> &lhs,
272
+ const properties<properties_type_list<rhs_property_tys...>> &rhs) {
273
+ auto rhs_unique_props =
274
+ filter_properties<merge_filter<lhs_property_tys...>::template predicate>(
275
+ rhs);
276
+ if constexpr (std::is_same_v<std::decay_t <decltype (rhs)>,
277
+ std::decay_t <decltype (rhs_unique_props)>>) {
278
+ // None of RHS properties share keys with LHS, no conflicts possible.
279
+ return properties{
280
+ lhs.template get_property <typename lhs_property_tys::key_t >()...,
281
+ rhs.template get_property <typename rhs_property_tys::key_t >()...};
282
+ } else {
283
+ // Ensure no conflicts, then merge.
284
+ constexpr auto has_conflict = [](auto *lhs_prop) constexpr {
285
+ using lhs_property_ty = std::remove_pointer_t <decltype (lhs_prop)>;
286
+ return (((std::is_same_v<typename lhs_property_ty::key_t ,
287
+ typename rhs_property_tys::key_t > &&
288
+ (!std::is_same_v<lhs_property_ty, rhs_property_tys> ||
289
+ !std::is_empty_v<lhs_property_ty>)) ||
290
+ ...));
291
+ };
292
+ static_assert (
293
+ !((has_conflict (static_cast <lhs_property_tys *>(nullptr )) || ...)),
294
+ " Failed to merge property lists due to conflicting properties." );
295
+ return merge_properties (lhs, rhs_unique_props);
296
+ }
297
+ }
298
+
352
299
} // namespace detail
353
300
} // namespace ext::oneapi::experimental
354
301
} // namespace _V1
0 commit comments