VCCC  2024.05
VisualCamp Common C++ library
common_type.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 2023/10/27.
3 //
4 
5 #ifndef VCCC_TYPE_TRAITS_COMMON_TYPE_HPP
6 #define VCCC_TYPE_TRAITS_COMMON_TYPE_HPP
7 
8 #include <chrono>
9 #include <type_traits>
10 #include <utility>
11 
16 
17 namespace vccc {
18 
115 
116 template<typename ...T>
117 struct common_type;
118 
119 namespace detail {
120 
121 struct no_common_type {};
122 
123 template<typename T, typename U>
124 using common_type_ternary = std::decay_t<decltype(false ? std::declval<T>() : std::declval<U>())>;
125 
126 template<typename CR1, typename CR2>
127 struct common_type_test_3_1 {
128  using type = common_type_ternary<CR1, CR2>;
129 };
130 
131 // C++20 check
132 template<typename CR1, typename CR2, typename = void>
133 struct common_type_test_3 : no_common_type {};
134 
135 template<typename CR1, typename CR2>
136 struct common_type_test_3<CR1, CR2, void_t<common_type_ternary<CR1, CR2>>>
137  : common_type_test_3_1<CR1, CR2> {};
138 
139 // Check if referencable
140 template<typename T1, typename T2,
141  bool v1 = is_referencable<std::remove_reference_t<T1>>::value,
142  bool v2 = is_referencable<std::remove_reference_t<T2>>::value>
143 struct common_type_test_2 : no_common_type {};
144 
145 template<typename T1, typename T2>
146 struct common_type_test_2<T1, T2, true, true>
147  : common_type_test_3<const std::remove_reference_t<T1>&, const std::remove_reference_t<T2>&> {};
148 
149 template<typename T1, typename T2>
150 struct common_type_test_1_1 {
151  using type = common_type_ternary<T1, T2>;
152 };
153 
154 template<typename T1, typename T2, typename = void>
155 struct common_type_test_1 : common_type_test_2<T1, T2> {};
156 
157 template<typename T1, typename T2>
158 struct common_type_test_1<T1, T2, void_t<common_type_ternary<T1, T2>>>
159  : common_type_test_1_1<T1, T2> {};
160 
161 
162 template<typename T1, typename T2, bool /* false */>
163 struct common_type_tuple_like_3 : common_type_test_1<T1, T2> {};
164 
165 template<template<typename...> class Tuple, typename... T, typename... U>
166 struct common_type_tuple_like_3<Tuple<T...>, Tuple<U...>, true> {
167  using type = Tuple<typename common_type<T, U>::type...>;
168 };
169 
170 template<
171  typename T1,
172  typename T2,
174 >
175 struct common_type_tuple_like_2 : common_type_test_1<T1, T2> {};
176 
177 template<template<typename...> class TTuple, template<typename...> class UTuple, typename... T, typename... U>
178 struct common_type_tuple_like_2<TTuple<T...>, UTuple<U...>, true>
179  : common_type_tuple_like_3<
180  TTuple<T...>,
181  UTuple<U...>,
182  conjunction<
183  has_typename_type<common_type<T, U>>...
184  >::value
185  > {};
186 
187 template<
188  typename T1,
189  typename T2,
190  bool = conjunction<
191  tuple_like<T1>,
192  tuple_like<T2>,
193  std::is_same<T1, std::decay_t<T1>>,
194  std::is_same<T2, std::decay_t<T2>>
195  >::value /* true */
196 >
197 struct common_type_tuple_like : common_type_tuple_like_2<T1, T2> {};
198 
199 template<typename T1, typename T2>
200 struct common_type_tuple_like<T1, T2, false> : common_type_test_1<T1, T2> {};
201 
202 
203 template<bool HasType /* false */, typename CommonType, typename... Ts>
204 struct common_type_test_three_or_more : no_common_type {};
205 
206 template<typename CommonType, typename... Ts>
207 struct common_type_test_three_or_more<true, CommonType, Ts...>
208  : common_type<typename CommonType::type, Ts...> {};
209 
210 } // namespace detail
211 
212 template<>
213 struct common_type<> : detail::no_common_type {};
214 
215 template<typename T>
216 struct common_type<T> : common_type<T, T> {};
217 
218 template<typename T1, typename T2>
219 struct common_type<T1, T2> : detail::common_type_tuple_like<std::decay_t<T1>, std::decay_t<T2>> {};
220 
221 template<typename T1, typename T2, typename ...Ts>
222 struct common_type<T1, T2, Ts...>
223  : detail::common_type_test_three_or_more<
224  has_typename_type<common_type<T1, T2>>::value,
225  common_type<T1, T2>,
226  Ts...> {};
227 
228 template<typename ...T>
229 using common_type_t = typename common_type<T...>::type;
230 
231 
232 // Specialization for std
233 namespace detail {
234 
235 template<typename T, typename U, bool /* false */>
236 struct common_type_specialization_impl : no_common_type {};
237 
238 template<template<typename...> class C, typename... T, typename... U>
239 struct common_type_specialization_impl<C<T...>, C<U...>, true> {
240  using type = C<common_type_t<T, U>...>;
241 };
242 
243 template<typename T, typename U>
244 struct common_type_specialization;
245 
246 template<template<typename...> class C, typename... T, typename... U>
247 struct common_type_specialization<C<T...>, C<U...>>
248  : common_type_specialization_impl<
249  C<T...>,
250  C<U...>,
251  conjunction<
252  has_typename_type<common_type<T, U>>...
253  >::value
254  > {};
255 
256 } // namespace detail
257 
258 template<typename T1, typename T2, typename U1, typename U2>
259 struct common_type<std::pair<T1, T2>, std::pair<U1, U2>>
260  : detail::common_type_specialization<std::pair<T1, T2>, std::pair<U1, U2>> {};
261 
262 template<typename Rep1, typename Period1, typename Rep2, typename Period2>
263 struct common_type<std::chrono::duration<Rep1, Period1>, std::chrono::duration<Rep2, Period2>>
264  : detail::common_type_specialization<std::chrono::duration<Rep1, Period1>, std::chrono::duration<Rep2, Period2>> {};
265 
266 template<typename Clock, typename Duration1, typename Duration2>
267 struct common_type<std::chrono::time_point<Clock, Duration1>, std::chrono::time_point<Clock, Duration2>>
268  : detail::common_type_specialization<std::chrono::time_point<Clock, Duration1>, std::chrono::time_point<Clock, Duration2>> {};
269 
270 
272 
273 } // namespace vccc
274 
275 #endif // VCCC_TYPE_TRAITS_COMMON_TYPE_HPP
std::integral_constant< bool, v > bool_constant
Definition: bool_constant.hpp:19
typename common_type< T... >::type common_type_t
Definition: common_type.hpp:229
void void_t
Definition: void_t.hpp:19
Definition: matrix.hpp:495
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: common_type.hpp:117