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