xref: /openbsd-src/gnu/llvm/libcxx/include/__type_traits/promote.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
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_same.h>
15 #include <__utility/declval.h>
16 #include <cstddef>
17 
18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19 #  pragma GCC system_header
20 #endif
21 
22 _LIBCPP_BEGIN_NAMESPACE_STD
23 
24 template <class _Tp>
25 struct __numeric_type
26 {
27    static void __test(...);
28    static float __test(float);
29    static double __test(char);
30    static double __test(int);
31    static double __test(unsigned);
32    static double __test(long);
33    static double __test(unsigned long);
34    static double __test(long long);
35    static double __test(unsigned long long);
36 #ifndef _LIBCPP_HAS_NO_INT128
37    static double __test(__int128_t);
38    static double __test(__uint128_t);
39 #endif
40    static double __test(double);
41    static long double __test(long double);
42 
43    typedef decltype(__test(std::declval<_Tp>())) type;
44    static const bool value = _IsNotSame<type, void>::value;
45 };
46 
47 template <>
48 struct __numeric_type<void>
49 {
50    static const bool value = true;
51 };
52 
53 template <class _A1, class _A2 = void, class _A3 = void,
54           bool = __numeric_type<_A1>::value &&
55                  __numeric_type<_A2>::value &&
56                  __numeric_type<_A3>::value>
57 class __promote_imp
58 {
59 public:
60     static const bool value = false;
61 };
62 
63 template <class _A1, class _A2, class _A3>
64 class __promote_imp<_A1, _A2, _A3, true>
65 {
66 private:
67     typedef typename __promote_imp<_A1>::type __type1;
68     typedef typename __promote_imp<_A2>::type __type2;
69     typedef typename __promote_imp<_A3>::type __type3;
70 public:
71     typedef decltype(__type1() + __type2() + __type3()) type;
72     static const bool value = true;
73 };
74 
75 template <class _A1, class _A2>
76 class __promote_imp<_A1, _A2, void, true>
77 {
78 private:
79     typedef typename __promote_imp<_A1>::type __type1;
80     typedef typename __promote_imp<_A2>::type __type2;
81 public:
82     typedef decltype(__type1() + __type2()) type;
83     static const bool value = true;
84 };
85 
86 template <class _A1>
87 class __promote_imp<_A1, void, void, true>
88 {
89 public:
90     typedef typename __numeric_type<_A1>::type type;
91     static const bool value = true;
92 };
93 
94 template <class _A1, class _A2 = void, class _A3 = void>
95 class __promote : public __promote_imp<_A1, _A2, _A3> {};
96 
97 _LIBCPP_END_NAMESPACE_STD
98 
99 #endif // _LIBCPP___TYPE_TRAITS_PROMOTE_H
100