xref: /freebsd/contrib/llvm-project/libcxx/include/__type_traits/promote.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _LIBCPP___TYPE_TRAITS_PROMOTE_H
10 #define _LIBCPP___TYPE_TRAITS_PROMOTE_H
11 
12 #include <__config>
13 #include <__type_traits/integral_constant.h>
14 #include <__type_traits/is_arithmetic.h>
15 
16 #if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER == 1700
17 #  include <__type_traits/is_same.h>
18 #  include <__utility/declval.h>
19 #endif
20 
21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22 #  pragma GCC system_header
23 #endif
24 
25 _LIBCPP_BEGIN_NAMESPACE_STD
26 
27 // TODO(LLVM-20): Remove this workaround
28 #if !defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER != 1700
29 
30 template <class... _Args>
31 class __promote {
32   static_assert((is_arithmetic<_Args>::value && ...));
33 
34   static float __test(float);
35   static double __test(char);
36   static double __test(int);
37   static double __test(unsigned);
38   static double __test(long);
39   static double __test(unsigned long);
40   static double __test(long long);
41   static double __test(unsigned long long);
42 #  ifndef _LIBCPP_HAS_NO_INT128
43   static double __test(__int128_t);
44   static double __test(__uint128_t);
45 #  endif
46   static double __test(double);
47   static long double __test(long double);
48 
49 public:
50   using type = decltype((__test(_Args()) + ...));
51 };
52 
53 #else
54 
55 template <class _Tp>
56 struct __numeric_type {
57   static void __test(...);
58   static float __test(float);
59   static double __test(char);
60   static double __test(int);
61   static double __test(unsigned);
62   static double __test(long);
63   static double __test(unsigned long);
64   static double __test(long long);
65   static double __test(unsigned long long);
66 #  ifndef _LIBCPP_HAS_NO_INT128
67   static double __test(__int128_t);
68   static double __test(__uint128_t);
69 #  endif
70   static double __test(double);
71   static long double __test(long double);
72 
73   typedef decltype(__test(std::declval<_Tp>())) type;
74   static const bool value = _IsNotSame<type, void>::value;
75 };
76 
77 template <>
78 struct __numeric_type<void> {
79   static const bool value = true;
80 };
81 
82 template <class _A1,
83           class _A2 = void,
84           class _A3 = void,
85           bool      = __numeric_type<_A1>::value && __numeric_type<_A2>::value && __numeric_type<_A3>::value>
86 class __promote_imp {
87 public:
88   static const bool value = false;
89 };
90 
91 template <class _A1, class _A2, class _A3>
92 class __promote_imp<_A1, _A2, _A3, true> {
93 private:
94   typedef typename __promote_imp<_A1>::type __type1;
95   typedef typename __promote_imp<_A2>::type __type2;
96   typedef typename __promote_imp<_A3>::type __type3;
97 
98 public:
99   typedef decltype(__type1() + __type2() + __type3()) type;
100   static const bool value = true;
101 };
102 
103 template <class _A1, class _A2>
104 class __promote_imp<_A1, _A2, void, true> {
105 private:
106   typedef typename __promote_imp<_A1>::type __type1;
107   typedef typename __promote_imp<_A2>::type __type2;
108 
109 public:
110   typedef decltype(__type1() + __type2()) type;
111   static const bool value = true;
112 };
113 
114 template <class _A1>
115 class __promote_imp<_A1, void, void, true> {
116 public:
117   typedef typename __numeric_type<_A1>::type type;
118   static const bool value = true;
119 };
120 
121 template <class _A1, class _A2 = void, class _A3 = void>
122 class __promote : public __promote_imp<_A1, _A2, _A3> {};
123 
124 #endif // !defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER >= 1700
125 
126 _LIBCPP_END_NAMESPACE_STD
127 
128 #endif // _LIBCPP___TYPE_TRAITS_PROMOTE_H
129