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