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 static double __test(double); 37 static long double __test(long double); 38 39 typedef decltype(__test(declval<_Tp>())) type; 40 static const bool value = _IsNotSame<type, void>::value; 41 }; 42 43 template <> 44 struct __numeric_type<void> 45 { 46 static const bool value = true; 47 }; 48 49 template <class _A1, class _A2 = void, class _A3 = void, 50 bool = __numeric_type<_A1>::value && 51 __numeric_type<_A2>::value && 52 __numeric_type<_A3>::value> 53 class __promote_imp 54 { 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 { 62 private: 63 typedef typename __promote_imp<_A1>::type __type1; 64 typedef typename __promote_imp<_A2>::type __type2; 65 typedef typename __promote_imp<_A3>::type __type3; 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 { 74 private: 75 typedef typename __promote_imp<_A1>::type __type1; 76 typedef typename __promote_imp<_A2>::type __type2; 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 { 85 public: 86 typedef typename __numeric_type<_A1>::type type; 87 static const bool value = true; 88 }; 89 90 template <class _A1, class _A2 = void, class _A3 = void> 91 class __promote : public __promote_imp<_A1, _A2, _A3> {}; 92 93 _LIBCPP_END_NAMESPACE_STD 94 95 #endif // _LIBCPP___TYPE_TRAITS_PROMOTE_H 96