|
|
@@ -0,0 +1,173 @@ |
|
|
//===-- Self contained C++ type traits --------------------------*- C++ -*-===// |
|
|
// |
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
|
|
// See https://llvm.org/LICENSE.txt for license information. |
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
|
|
// |
|
|
//===----------------------------------------------------------------------===// |
|
|
|
|
|
#ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPETRAITS_H |
|
|
#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPETRAITS_H |
|
|
|
|
|
#include "UInt.h" |
|
|
|
|
|
namespace __llvm_libc { |
|
|
namespace cpp { |
|
|
|
|
|
template <bool B, typename T> struct enable_if; |
|
|
template <typename T> struct enable_if<true, T> { |
|
|
using type = T; |
|
|
}; |
|
|
template <bool B, typename T = void> |
|
|
using enable_if_t = typename enable_if<B, T>::type; |
|
|
|
|
|
template <typename T, T v> struct integral_constant { |
|
|
using value_type = T; |
|
|
static constexpr T value = v; |
|
|
}; |
|
|
using true_type = cpp::integral_constant<bool, true>; |
|
|
using false_type = cpp::integral_constant<bool, false>; |
|
|
|
|
|
template <typename T> struct type_identity { |
|
|
using type = T; |
|
|
}; |
|
|
|
|
|
template <typename T, typename U> struct is_same : cpp::false_type {}; |
|
|
template <typename T> struct is_same<T, T> : cpp::true_type {}; |
|
|
template <typename T, typename U> |
|
|
inline constexpr bool is_same_v = is_same<T, U>::value; |
|
|
|
|
|
template <typename T> struct remove_cv : public type_identity<T> {}; |
|
|
template <typename T> struct remove_cv<const T> : public type_identity<T> {}; |
|
|
template <typename T> struct remove_cv<volatile T> : public type_identity<T> {}; |
|
|
template <typename T> |
|
|
struct remove_cv<const volatile T> : public type_identity<T> {}; |
|
|
template <typename T> using remove_cv_t = typename remove_cv<T>::type; |
|
|
|
|
|
template <typename T> struct is_integral { |
|
|
private: |
|
|
using unqualified_type = remove_cv_t<T>; |
|
|
|
|
|
public: |
|
|
static constexpr bool value = |
|
|
is_same_v<char, unqualified_type> || |
|
|
is_same_v<signed char, unqualified_type> || |
|
|
is_same_v<unsigned char, unqualified_type> || |
|
|
is_same_v<short, unqualified_type> || |
|
|
is_same_v<unsigned short, unqualified_type> || |
|
|
is_same_v<int, unqualified_type> || |
|
|
is_same_v<unsigned int, unqualified_type> || |
|
|
is_same_v<long, unqualified_type> || |
|
|
is_same_v<unsigned long, unqualified_type> || |
|
|
is_same_v<long long, unqualified_type> || |
|
|
is_same_v<unsigned long long, unqualified_type> || |
|
|
is_same_v<bool, unqualified_type> || |
|
|
// We need to include UInt<128> and __uint128_t when available because |
|
|
// we want to unittest UInt<128>. If we include only UInt128, then on |
|
|
// platform where it resolves to __uint128_t, we cannot unittest |
|
|
// UInt<128>. |
|
|
is_same_v<__llvm_libc::cpp::UInt<128>, unqualified_type> |
|
|
#ifdef __SIZEOF_INT128__ |
|
|
|| is_same_v<__int128_t, unqualified_type> || |
|
|
is_same_v<__uint128_t, unqualified_type> |
|
|
#endif |
|
|
; |
|
|
}; |
|
|
template <typename T> |
|
|
inline constexpr bool is_integral_v = is_integral<T>::value; |
|
|
|
|
|
template <typename T> struct is_enum { |
|
|
static constexpr bool value = __is_enum(T); |
|
|
}; |
|
|
|
|
|
template <typename T> struct is_pointer : cpp::false_type {}; |
|
|
template <typename T> struct is_pointer<T *> : cpp::true_type {}; |
|
|
template <typename T> struct is_pointer<T *const> : cpp::true_type {}; |
|
|
template <typename T> struct is_pointer<T *volatile> : cpp::true_type {}; |
|
|
template <typename T> struct is_pointer<T *const volatile> : cpp::true_type {}; |
|
|
template <typename T> inline constexpr bool is_pointer_v = is_pointer<T>::value; |
|
|
|
|
|
template <typename T> struct is_floating_point { |
|
|
private: |
|
|
using unqualified_type = remove_cv_t<T>; |
|
|
|
|
|
public: |
|
|
static constexpr bool value = is_same_v<float, unqualified_type> || |
|
|
is_same_v<double, unqualified_type> || |
|
|
is_same_v<long double, unqualified_type>; |
|
|
}; |
|
|
template <typename T> |
|
|
inline constexpr bool is_floating_point_v = is_floating_point<T>::value; |
|
|
|
|
|
template <typename T> struct is_arithmetic { |
|
|
static constexpr bool value = |
|
|
is_integral<T>::value || is_floating_point<T>::value; |
|
|
}; |
|
|
template <typename T> |
|
|
inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value; |
|
|
|
|
|
template <typename T> struct is_signed { |
|
|
static constexpr bool value = is_arithmetic<T>::value && (T(-1) < T(0)); |
|
|
constexpr operator bool() const { return value; } |
|
|
constexpr bool operator()() const { return value; } |
|
|
}; |
|
|
template <typename T> inline constexpr bool is_signed_v = is_signed<T>::value; |
|
|
|
|
|
template <typename T> struct make_unsigned; |
|
|
template <> struct make_unsigned<char> { |
|
|
using type = unsigned char; |
|
|
}; |
|
|
template <> struct make_unsigned<signed char> { |
|
|
using type = unsigned char; |
|
|
}; |
|
|
template <> struct make_unsigned<short> { |
|
|
using type = unsigned short; |
|
|
}; |
|
|
template <> struct make_unsigned<int> { |
|
|
using type = unsigned int; |
|
|
}; |
|
|
template <> struct make_unsigned<long> { |
|
|
using type = unsigned long; |
|
|
}; |
|
|
template <> struct make_unsigned<long long> { |
|
|
using type = unsigned long long; |
|
|
}; |
|
|
template <> struct make_unsigned<unsigned char> { |
|
|
using type = unsigned char; |
|
|
}; |
|
|
template <> struct make_unsigned<unsigned short> { |
|
|
using type = unsigned short; |
|
|
}; |
|
|
template <> struct make_unsigned<unsigned int> { |
|
|
using type = unsigned int; |
|
|
}; |
|
|
template <> struct make_unsigned<unsigned long> { |
|
|
using type = unsigned long; |
|
|
}; |
|
|
template <> struct make_unsigned<unsigned long long> { |
|
|
using type = unsigned long long; |
|
|
}; |
|
|
#ifdef __SIZEOF_INT128__ |
|
|
template <> struct make_unsigned<__int128_t> { |
|
|
using type = __uint128_t; |
|
|
}; |
|
|
template <> struct make_unsigned<__uint128_t> { |
|
|
using type = __uint128_t; |
|
|
}; |
|
|
#endif |
|
|
template <typename T> using make_unsigned_t = typename make_unsigned<T>::type; |
|
|
|
|
|
// Compile time type selection. |
|
|
template <bool B, typename T, typename F> struct conditional { |
|
|
using type = T; |
|
|
}; |
|
|
template <typename T, typename F> struct conditional<false, T, F> { |
|
|
using type = F; |
|
|
}; |
|
|
template <bool B, typename T, typename F> |
|
|
using conditional_t = typename conditional<B, T, F>::type; |
|
|
|
|
|
} // namespace cpp |
|
|
} // namespace __llvm_libc |
|
|
|
|
|
#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPETRAITS_H |