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