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