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