blob: bccd4eb76579e65a98c4f699b8e5f68fd6ac469e [file] [log] [blame]
//===-- 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