VCCC  2024.05
VisualCamp Common C++ library
common_reference.hpp
Go to the documentation of this file.
1 //
2 // Created by cosge on 2023-12-03.
3 //
4 
5 #ifndef VCCC_TYPE_TRAITS_COMMON_REFERENCE_HPP_
6 #define VCCC_TYPE_TRAITS_COMMON_REFERENCE_HPP_
7 
8 #include <functional>
9 #include <type_traits>
10 #include <tuple>
11 #include <utility>
12 
26 
27 namespace vccc {
28 namespace detail {
29 
30 struct no_common_reference {};
31 
32 template<typename T, typename U,
33  template<typename> class TQual, template<typename> class UQual,
34  bool = conjunction<tuple_like<T>, tuple_like<U>>::value /* false */>
35 struct basic_common_reference_tuple_like : no_common_reference {};
36 
37 }
38 
49 
50 template<typename...>
52 
53 template<typename... T>
54 using common_reference_t = typename common_reference<T...>::type;
55 
56 template<typename T, typename U, template<typename> class TQual, template<typename> class UQual>
57 struct basic_common_reference : detail::basic_common_reference_tuple_like<T, U, TQual, UQual> {};
58 
61 
62 namespace impl {
63 
64 template<typename T>
66  template<typename U>
68 };
69 
70 template<typename T1, typename T2>
71 struct common_reference_tag_1 : has_typename_type<simple_common_reference<T1, T2>> {};
72 
73 template<typename T1, typename T2>
76  basic_common_reference<
77  remove_cvref_t<T1>,
78  remove_cvref_t<T2>,
79  basic_common_reference_qual_gen<T1>::template qual,
80  basic_common_reference_qual_gen<T2>::template qual
81  >
82  > {};
83 
84 template<typename T> T common_reference_val();
85 
86 template<typename T1, typename T2, typename = void>
87 struct common_reference_tag_3 : std::false_type {};
88 
89 template<typename T1, typename T2>
91  T1,
92  T2,
93  void_t<decltype( false ? common_reference_val<T1>() : common_reference_val<T2>() )>
94  > : std::true_type {};
95 
96 template<typename T1, typename T2, typename = void>
97 struct common_reference_tag_4 : std::false_type {};
98 
99 template<typename T1, typename T2>
100 struct common_reference_tag_4<T1, T2, void_t<std::common_type_t<T1, T2>>> : std::true_type {};
101 
102 template<typename T1, typename T2>
104  : std::conditional_t<
105  common_reference_tag_1<T1, T2>::value, std::integral_constant<int, 1>,
106  std::conditional_t<
107  common_reference_tag_2<T1, T2>::value, std::integral_constant<int, 2>,
108  std::conditional_t<
109  common_reference_tag_3<T1, T2>::value, std::integral_constant<int, 3>,
110  std::conditional_t<
111  common_reference_tag_4<T1, T2>::value, std::integral_constant<int, 4>,
112  std::integral_constant<int, 0>
113  >>>> {};
114 
115 
118 
119 template<typename T1, typename T2>
120 struct common_reference_two<T1, T2, 0> {}; // no common reference type
121 
122 template<typename T1, typename T2>
123 struct common_reference_two<T1, T2, 1> {
125 };
126 
127 template<typename T1, typename T2>
128 struct common_reference_two<T1, T2, 2> {
129  using type = typename basic_common_reference<
134 };
135 
136 template<typename T1, typename T2>
137 struct common_reference_two<T1, T2, 3> {
138  using type = decltype( false ? common_reference_val<T1>() : common_reference_val<T2>() );
139 };
140 
141 template<typename T1, typename T2>
142 struct common_reference_two<T1, T2, 4> {
143  using type = std::common_type_t<T1, T2>;
144 };
145 
146 template<bool /*true*/, typename T1, typename T2, typename... R>
147 struct common_reference_three : common_reference<common_reference_t<T1, T2>, R...> {};
148 
149 template<typename T1, typename T2, typename... R>
150 struct common_reference_three<false, T1, T2, R...> {};
151 
152 } // namespace impl
153 
154 template<>
155 struct common_reference<> {};
156 
157 template<typename T>
158 struct common_reference<T> {
159  using type = T;
160 };
161 
162 template<typename T1, typename T2>
163 struct common_reference<T1, T2> : impl::common_reference_two<T1, T2> {};
164 
165 template<typename T1, typename T2, typename... R>
166 struct common_reference<T1, T2, R...>
168  has_typename_type<common_reference<T1, T2>>::value,
169  T1,
170  T2,
171  R...
172  > {};
173 
174 // specializations of basic_common_reference
175 
176 namespace detail {
177 
178 template<typename TTuple, typename UTuple, template<typename> class TQual, template<typename> class UQual, typename Index>
179 struct basic_common_reference_tuple_like_impl_2;
180 
181 template<
182  typename TTuple, typename UTuple,
183  template<typename> class TQual, template<typename> class UQual,
184  std::size_t... I
185 >
186 struct basic_common_reference_tuple_like_impl_2<TTuple, UTuple, TQual, UQual, std::index_sequence<I...>> {
187  using type = std::tuple<
189  TQual< std::tuple_element_t<I, TTuple> >,
190  UQual< std::tuple_element_t<I, UTuple> >
191  >... >;
192 };
193 
194 
195 template<
196  typename TTuple, typename UTuple,
197  template<typename> class TQual, template<typename> class UQual,
198  typename Index
199 >
200 struct basic_common_reference_tuple_like_impl_1;
201 
202 template<
203  typename TTuple, typename UTuple,
204  template<typename> class TQual, template<typename> class UQual,
205  std::size_t... I
206 >
207 struct basic_common_reference_tuple_like_impl_1<TTuple, UTuple, TQual, UQual, std::index_sequence<I...>>
208  : std::conditional_t<
209  conjunction<
210  has_typename_type< common_reference<TQual<std::tuple_element_t<I, TTuple>>,
211  UQual<std::tuple_element_t<I, UTuple>>> >...
212  >::value,
213  basic_common_reference_tuple_like_impl_2<TTuple, UTuple, TQual, UQual, std::index_sequence<I...>>,
214  no_common_reference
215  >{};
216 
217 
218 template<typename TTuple, typename UTuple, template<typename> class TQual, template<typename> class UQual>
219 struct basic_common_reference_tuple_like<TTuple, UTuple, TQual, UQual, true>
220  : std::conditional_t<
221  conjunction<
222  disjunction< is_specialization<TTuple, std::tuple>, is_specialization<UTuple, std::tuple> >,
223  std::is_same<TTuple, std::decay_t<TTuple>>,
224  std::is_same<UTuple, std::decay_t<UTuple>>,
225  bool_constant<(std::tuple_size<remove_cvref_t<TTuple>>::value == std::tuple_size<remove_cvref_t<UTuple>>::value)>
226  >::value,
227  basic_common_reference_tuple_like_impl_1<TTuple, UTuple, TQual, UQual, std::make_index_sequence<std::tuple_size<remove_cvref_t<TTuple>>::value>>,
228  no_common_reference
229  >{};
230 
231 template<typename T, typename U,
232  template<typename> class TQual, template<typename> class UQual,
233  bool /* false */>
234 struct basic_common_reference_pair {};
235 
236 template<typename T1, typename T2, typename U1, typename U2,
237  template<typename> class TQual, template<typename> class UQual>
238 struct basic_common_reference_pair<std::pair<T1, T2>, std::pair<U1, U2>, TQual, UQual, true> {
239  using type = std::pair< common_reference_t<TQual<T1>, UQual<U1>>,
240  common_reference_t<TQual<T2>, UQual<U2>> >;
241 };
242 
243 template<
244  typename R, typename T, typename RQ, typename TQ,
245  bool =
246  conjunction<
247  negation< is_specialization<T, std::reference_wrapper> >,
248  has_typename_type< common_reference<R&, TQ> >
249  >::value /* false */
250 >
251 struct basic_common_reference_ref_wrap {};
252 
253 template<
254  typename R, typename T, typename RQ, typename TQ
255 >
256 struct basic_common_reference_ref_wrap<R, T, RQ, TQ, true>
257  : std::conditional_t<
258  convertible_to<RQ, common_reference_t<R&, TQ>>::value,
259  type_identity<common_reference_t<R&, TQ>>,
260  empty
261  > {};
262 
263 } // namespace detail
264 
265 template<typename T1, typename T2, typename U1, typename U2,
266  template<typename> class TQual, template<typename> class UQual>
267 struct basic_common_reference<std::pair<T1, T2>, std::pair<U1, U2>, TQual, UQual>
268  : detail::basic_common_reference_pair<
269  std::pair<T1, T2>, std::pair<U1, U2>,
270  TQual, UQual,
271  conjunction<
272  has_typename_type< common_reference< TQual<T1>, UQual<U1> > >,
273  has_typename_type< common_reference< TQual<T2>, UQual<U2> > >
274  >::value
275  > {};
276 
277 template<typename R, typename T, template<typename> class RQual, template<typename> class TQual>
278 struct basic_common_reference<std::reference_wrapper<R>, T, RQual, TQual>
279  : detail::basic_common_reference_ref_wrap<R, T, RQual<R>, TQual<T>> {};
280 
281 template<typename R, typename T, template<typename> class RQual, template<typename> class TQual>
282 struct basic_common_reference<T, std::reference_wrapper<R>, TQual, RQual>
283  : detail::basic_common_reference_ref_wrap<R, T, RQual<R>, TQual<T>> {};
284 
285 
286 } // namespace vccc
287 
288 #endif // VCCC_TYPE_TRAITS_COMMON_REFERENCE_HPP_
typename common_reference< T... >::type common_reference_t
Definition: common_reference.hpp:54
typename common_type< T... >::type common_type_t
Definition: common_type.hpp:229
typename remove_cvref< T >::type remove_cvref_t
Definition: remove_cvref.hpp:24
void void_t
Definition: void_t.hpp:19
typename copy_cvref< From, To >::type copy_cvref_t
Definition: copy_cvref.hpp:99
Definition: matrix.hpp:495
T common_reference_val()
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: common_reference.hpp:57
T type
Definition: common_reference.hpp:159
Definition: common_reference.hpp:51
Definition: has_typename_type.hpp:18
Definition: common_reference.hpp:65
copy_cvref_t< T, U > qual
Definition: common_reference.hpp:67
Definition: common_reference.hpp:71
Definition: common_reference.hpp:82
Definition: common_reference.hpp:87
Definition: common_reference.hpp:97
Definition: common_reference.hpp:113
Definition: common_reference.hpp:147
typename simple_common_reference< T1, T2 >::type type
Definition: common_reference.hpp:124
typename basic_common_reference< remove_cvref_t< T1 >, remove_cvref_t< T2 >, basic_common_reference_qual_gen< T1 >::template qual, basic_common_reference_qual_gen< T2 >::template qual >::type type
Definition: common_reference.hpp:133
decltype(false ? common_reference_val< T1 >() :common_reference_val< T2 >()) type
Definition: common_reference.hpp:138
std::common_type_t< T1, T2 > type
Definition: common_reference.hpp:143
Definition: common_reference.hpp:117
Definition: simple_common_reference.hpp:94