Phi
common_type.hpp
1 #ifndef INCG_PHI_CORE_TYPE_TRAITS_COMMON_TYPE_HPP
2 #define INCG_PHI_CORE_TYPE_TRAITS_COMMON_TYPE_HPP
3 
4 #include "phi/phi_config.hpp"
5 
6 #if PHI_HAS_EXTENSION_PRAGMA_ONCE()
7 # pragma once
8 #endif
9 
10 #include "phi/core/declval.hpp"
11 #include "phi/type_traits/conditional.hpp"
12 #include "phi/type_traits/decay.hpp"
13 #include "phi/type_traits/is_same.hpp"
14 #include "phi/type_traits/remove_cvref.hpp"
15 #include "phi/type_traits/void_t.hpp"
16 
17 DETAIL_PHI_BEGIN_NAMESPACE()
18 
19 template <typename... TypesT>
20 struct common_type;
21 
22 namespace detail
23 {
24  // Let COND_RES(X, Y) be:
25  template <typename TypeT, typename OtherT>
26  using condition_type = decltype(false ? declval<TypeT>() : declval<OtherT>());
27 
28  template <typename TypeT, typename OtherT, typename = void>
30  {};
31 
32  // sub-bullet 4 - "if COND_RES(CREF(D1), CREF(D2)) denotes a type..."
33  template <typename TypeT, typename OtherT>
34  struct common_type3_impl<TypeT, OtherT, void_t<condition_type<const TypeT&, const OtherT&>>>
35  {
36  using type = remove_cvref_t<condition_type<const TypeT&, const OtherT&>>;
37  };
38 
39  template <typename TypeT, typename OtherT, typename = void>
40  struct common_type2_impl : public common_type3_impl<TypeT, OtherT>
41  {};
42 
43  // sub-bullet 3 - "if decay_t<decltype(false ? declval<D1>() : declval<D2>())> ..."
44  template <typename TypeT, typename OtherT>
46  TypeT, OtherT,
47  typename void_t<decltype(true ? declval<TypeT>() : declval<OtherT>())>::type>
48  {
49  using type = typename decay<decltype(true ? declval<TypeT>() : declval<OtherT>())>::type;
50  };
51 
52  template <typename, typename = void>
54  {};
55 
56  template <typename... TypeT>
57  struct common_types;
58 
59  template <typename TypeT, typename OtherT>
60  struct common_type_impl<common_types<TypeT, OtherT>,
61  typename void_t<typename common_type<TypeT, OtherT>::type>::type>
62  {
63  using type = typename common_type<TypeT, OtherT>::type;
64  };
65 
66  template <typename TypeT, typename OtherT, typename ThirdT, typename... RestT>
67  struct common_type_impl<common_types<TypeT, OtherT, ThirdT, RestT...>,
68  typename void_t<typename common_type<TypeT, OtherT>::type>::type>
69  : public common_type_impl<
70  common_types<typename common_type<TypeT, OtherT>::type, ThirdT, RestT...>>
71  {};
72 } // namespace detail
73 
74 // bullet 1 - sizeof...(Tp) == 0
75 
76 template <>
77 struct common_type<>
78 {};
79 
80 // bullet 2 - sizeof...(Tp) == 1
81 
82 template <typename TypeT>
83 struct common_type<TypeT> : public common_type<TypeT, TypeT>
84 {};
85 
86 // bullet 3 - sizeof...(Tp) == 2
87 
88 // sub-bullet 1 - "If is_same_v<T1, D1> is false or ..."
89 template <typename TypeT, typename OtherT>
90 struct common_type<TypeT, OtherT>
91  : public conditional<
92  is_same<TypeT, typename decay<TypeT>::type>::value &&
93  is_same<OtherT, typename decay<OtherT>::type>::value,
94  detail::common_type2_impl<TypeT, OtherT>,
95  common_type<typename decay<TypeT>::type, typename decay<OtherT>::type>>::type
96 {};
97 
98 // bullet 4 - sizeof...(Tp) > 2
99 
100 template <typename TypeT, typename OtherT, typename ThirdT, typename... RestT>
101 struct common_type<TypeT, OtherT, ThirdT, RestT...>
102  : public detail::common_type_impl<detail::common_types<TypeT, OtherT, ThirdT, RestT...>>
103 {};
104 
105 template <typename... TypeT>
106 using common_type_t = typename common_type<TypeT...>::type;
107 
108 DETAIL_PHI_END_NAMESPACE()
109 
110 #endif // INCG_PHI_CORE_TYPE_TRAITS_COMMON_TYPE_HPP
Definition: common_type.hpp:29
Definition: conditional.hpp:13
Definition: common_type.hpp:57
Definition: decay.hpp:56
Definition: swap.hpp:23
Definition: common_type.hpp:40
Definition: common_type.hpp:53
Definition: common_type.hpp:20