Type traits

This commit is contained in:
2024-08-06 00:34:57 +02:00
parent 4228e82740
commit 75b10758ba
22 changed files with 680 additions and 335 deletions

18
asl/BUILD.bazel Normal file
View File

@ -0,0 +1,18 @@
cc_library(
name = "asl",
hdrs = [
"integers.hpp",
"meta.hpp",
],
visibility = ["//visibility:public"],
)
[cc_test(
name = "%s_tests" % name,
srcs = [
"%s_tests.cpp" % name,
],
deps = [
":asl",
],
) for name in ["integers", "meta"]]

View File

@ -1,18 +0,0 @@
cc_library(
name = "base",
hdrs = [
"integers.hpp",
],
visibility = ["//visibility:public"],
)
cc_test(
name = "integers_tests",
srcs = [
"integers_tests.cpp",
],
deps = [
":base",
],
)

View File

@ -1,4 +1,4 @@
#include "asl/base/integers.hpp" #include "asl/integers.hpp"
static_assert(sizeof(int8_t) == 1); static_assert(sizeof(int8_t) == 1);
static_assert(sizeof(int16_t) == 2); static_assert(sizeof(int16_t) == 2);

View File

@ -1,10 +0,0 @@
cc_library(
name = "memory",
hdrs = [
"layout.hpp",
],
deps = [
"//asl/base",
],
visibility = ["//visibility:public"],
)

View File

@ -1,6 +0,0 @@
#pragma once
namespace asl {
} // namespace asl

89
asl/meta.hpp Normal file
View File

@ -0,0 +1,89 @@
#pragma once
namespace asl {
template<typename T, T kValue> struct integral_constant { static constexpr T value = kValue; };
template<bool B> using bool_constant = integral_constant<bool, B>;
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;
using nullptr_t = decltype(nullptr);
template<typename T> struct un_ref { using type = T; };
template<typename T> struct un_ref<T&> { using type = T; };
template<typename T> struct un_ref<T&&> { using type = T; };
template<typename T> using un_ref_t = un_ref<T>::type;
template<typename T> struct un_const { using type = T; };
template<typename T> struct un_const<const T> { using type = T; };
template<typename T> using un_const_t = un_const<T>::type;
template<typename T> struct un_volatile { using type = T; };
template<typename T> struct un_volatile<volatile T> { using type = T; };
template<typename T> using un_volatile_t = un_volatile<T>::type;
template<typename T> using un_qual_t = un_const_t<un_volatile_t<T>>;
template<typename T> using un_qualref_t = un_qual_t<un_ref_t<T>>;
template<typename U, typename V> struct _is_same_helper : false_type {};
template<typename T> struct _is_same_helper<T, T> : true_type {};
template<typename U, typename V>
concept is_same = _is_same_helper<U, V>::value && _is_same_helper<V, U>::value;
template<typename T> struct _is_const_helper : false_type {};
template<typename T> struct _is_const_helper<const T> : true_type {};
template<typename T> concept is_const = _is_const_helper<T>::value;
template<typename T> concept is_void = is_same<un_qual_t<T>, void>;
template<typename T> concept is_nullptr = is_same<un_qual_t<T>, nullptr_t>;
template<typename T> concept is_integral = __is_integral(T);
template<typename T> concept is_floating_point = __is_floating_point(T);
template<typename T> concept is_arithmetic = is_integral<T> || is_floating_point<T>;
template<typename T> struct _is_array_helper : false_type {};
template<typename T> struct _is_array_helper<T[]> : true_type {};
template<typename T, size_t N> struct _is_array_helper<T[N]> : true_type {};
template<typename T> concept is_array = _is_array_helper<T>::value;
template<typename T> concept is_class = __is_class(T);
template<typename T> concept is_union = __is_union(T);
template<typename T> concept is_enum = __is_enum(T);
template<typename T> struct _is_ptr_helper : false_type {};
template<typename T> struct _is_ptr_helper<T*> : true_type {};
template<typename T> concept is_ptr = _is_ptr_helper<un_qual_t<T>>::value;
template<typename T> struct _is_ref_helper { static constexpr bool lref = false; static constexpr bool rref = false; };
template<typename T> struct _is_ref_helper<T&> { static constexpr bool lref = true; static constexpr bool rref = false; };
template<typename T> struct _is_ref_helper<T&&> { static constexpr bool lref = false; static constexpr bool rref = true; };
template<typename T> concept is_lref = _is_ref_helper<T>::lref;
template<typename T> concept is_rref = _is_ref_helper<T>::rref;
template<typename T> concept is_ref = is_lref<T> || is_rref<T>;
template<typename T> concept is_func = !is_const<const T> && !is_ref<T>;
template<typename T> struct _is_member_ptr_helper : false_type {};
template<typename T, typename U> struct _is_member_ptr_helper<T U::*> : true_type {};
template<typename T> struct _is_member_func_ptr_helper : false_type {};
template<typename T, typename U> struct _is_member_func_ptr_helper<T U::*> : bool_constant<is_func<T>> {};
template<typename T> concept is_member_ptr = _is_member_ptr_helper<un_qual_t<T>>::value;
template<typename T> concept is_member_func_ptr = _is_member_func_ptr_helper<un_qual_t<T>>::value;
template<typename T> concept is_member_object_ptr = is_member_ptr<T> && !is_member_func_ptr<T>;
template<typename T> concept is_fundamental = is_arithmetic<T> || is_void<T> || is_nullptr<T>;
template<typename T> concept is_compound = !is_fundamental<T>;
template<typename T> concept is_scalar = (is_fundamental<T> && !is_void<T>) || is_enum<T> || is_ptr<T> || is_member_ptr<T>;
template<typename T> concept is_object = is_scalar<T> || is_array<T> || is_class<T> || is_union<T>;
} // namespace asl

View File

@ -1,27 +0,0 @@
cc_library(
name = "meta",
hdrs = [
"empty.hpp",
"funcs.hpp",
"quals.hpp",
"refs.hpp",
"types.hpp",
],
srcs = [
"internal/quals.hpp",
"internal/refs.hpp",
"internal/types.hpp",
],
visibility = ["//visibility:public"],
)
[cc_test(
name = "%s_tests" % name,
srcs = [
"%s_tests.cpp" % name,
],
deps = [
":meta",
],
) for name in ["empty", "quals", "refs", "types", "funcs"]]

View File

@ -1,11 +0,0 @@
#pragma once
#include "asl/meta/types.hpp"
#include "asl/meta/quals.hpp"
namespace asl {
template<typename T> concept is_void = same<un_qual_t<T>, void>;
} // namespace asl

View File

@ -1,17 +0,0 @@
#include "asl/meta/empty.hpp"
using namespace asl;
struct Empty {};
static_assert(is_void<void>);
static_assert(is_void<const void>);
static_assert(is_void<volatile void>);
static_assert(is_void<const void>);
static_assert(!is_void<Empty>);
static_assert(!is_void<int>);
static_assert(!is_void<int&>);
static_assert(!is_void<int()>);
int main() { return 0; }

View File

@ -1,11 +0,0 @@
#pragma once
#include "asl/meta/internal/quals.hpp"
#include "asl/meta/refs.hpp"
namespace asl {
template<typename T> concept is_func = internal::is_const<typename internal::const_helper<T>::remove> && !is_any_ref<T>;
} // namespace asl

View File

@ -1,14 +0,0 @@
#include "asl/meta/funcs.hpp"
using namespace asl;
static_assert(!is_func<int>);
static_assert(!is_func<int&>);
static_assert(!is_func<const int>);
static_assert(!is_func<void>);
static_assert(is_func<void()>);
static_assert(is_func<void() const>);
static_assert(is_func<void() &&>);
static_assert(!is_func<void(*)()>);
int main() { return 0; }

View File

@ -1,16 +0,0 @@
#pragma once
#include "asl/meta/types.hpp"
namespace asl::internal {
template<typename T> struct const_helper { using add = const T; using remove = T; };
template<typename T> struct const_helper<const T> { using add = const T; using remove = T; };
template<typename T> concept is_const = same<T, typename internal::const_helper<T>::add>;
template<typename T> struct volatile_helper { using add = volatile T; using remove = T; };
template<typename T> struct volatile_helper<volatile T> { using add = volatile T; using remove = T; };
} // namespace asl::internal

View File

@ -1,45 +0,0 @@
#pragma once
#include "asl/meta/types.hpp"
namespace asl::internal {
template<typename T, typename = void>
inline constexpr bool is_referenceable = false;
template<typename T>
inline constexpr bool is_referenceable<T, void_t<T&>> = true;
template<typename T, bool = is_referenceable<T>>
struct as_ref_helper { using lvalue = T; using rvalue = T; };
template<typename T>
struct as_ref_helper<T, true> { using lvalue = T&; using rvalue = T&&; };
template<typename T> struct un_ref_helper { using type = T; };
template<typename T> struct un_ref_helper<T&> { using type = T; };
template<typename T> struct un_ref_helper<T&&> { using type = T; };
template<typename T>
struct is_ref_helper
{
static inline constexpr bool lref = false;
static inline constexpr bool rref = false;
};
template<typename T>
struct is_ref_helper<T&>
{
static inline constexpr bool lref = true;
static inline constexpr bool rref = false;
};
template<typename T>
struct is_ref_helper<T&&>
{
static inline constexpr bool lref = false;
static inline constexpr bool rref = true;
};
} // namespace asl::internal

View File

@ -1,9 +0,0 @@
#pragma once
namespace asl::internal {
template<typename U, typename V> inline constexpr bool is_same = false;
template<typename T> inline constexpr bool is_same<T, T> = true;
} // namespace asl::internal

View File

@ -1,22 +0,0 @@
#pragma once
#include "asl/meta/types.hpp"
#include "asl/meta/funcs.hpp"
#include "asl/meta/refs.hpp"
#include "asl/meta/internal/quals.hpp"
namespace asl {
template<typename T> concept is_const = internal::is_const<T>;
template<typename T> concept is_volatile = !is_any_ref<T> && !is_func<T> && same<T, typename internal::volatile_helper<T>::add>;
template<typename T> using as_const_t = internal::const_helper<T>::add;
template<typename T> using un_const_t = internal::const_helper<T>::remove;
template<typename T> using as_volatile_t = internal::volatile_helper<T>::add;
template<typename T> using un_volatile_t = internal::volatile_helper<T>::remove;
template<typename T> using un_qual_t = un_volatile_t<un_const_t<T>>;
} // namespace asl

View File

@ -1,51 +0,0 @@
#include "asl/meta/quals.hpp"
#include "asl/meta/types.hpp"
using namespace asl;
static_assert(!is_const<int>);
static_assert(is_const<const int>);
static_assert(!is_const<volatile int>);
static_assert(is_const<const volatile int>);
static_assert(!is_volatile<int>);
static_assert(!is_volatile<const int>);
static_assert(is_volatile<volatile int>);
static_assert(is_volatile<const volatile int>);
static_assert(!is_const<const int*>);
static_assert(is_const<const int* const>);
static_assert(is_const<const int&>);
static_assert(is_const<int&>);
static_assert(is_const<void()>);
static_assert(is_const<void() const>);
static_assert(is_const<void() const &>);
static_assert(!is_volatile<int&>);
static_assert(!is_volatile<void()>);
static_assert(same<as_const_t<int>, const int>);
static_assert(same<as_const_t<const int>, const int>);
static_assert(same<un_const_t<int>, int>);
static_assert(same<un_const_t<const int>, int>);
static_assert(same<as_const_t<int[]>, const int[]>);
static_assert(same<as_const_t<int[5]>, const int[5]>);
static_assert(same<as_volatile_t<int>, volatile int>);
static_assert(same<as_volatile_t<volatile int>, volatile int>);
static_assert(same<un_volatile_t<int>, int>);
static_assert(same<un_volatile_t<volatile int>, int>);
static_assert(same<as_volatile_t<int[]>, volatile int[]>);
static_assert(same<as_volatile_t<int[5]>, volatile int[5]>);
static_assert(same<un_qual_t<int>, int>);
static_assert(same<un_qual_t<const int>, int>);
static_assert(same<un_qual_t<volatile int>, int>);
static_assert(same<un_qual_t<const volatile int>, int>);
static_assert(same<un_qual_t<volatile const int>, int>);
int main() { return 0; }

View File

@ -1,21 +0,0 @@
#pragma once
#include "asl/meta/internal/refs.hpp"
namespace asl {
template<typename T> concept referenceable = internal::is_referenceable<T>;
template<typename T> concept is_ref = internal::is_ref_helper<T>::lref;
template<typename T> concept is_rref = internal::is_ref_helper<T>::rref;
template<typename T> concept is_any_ref = is_ref<T> || is_rref<T>;
template<typename T> using as_ref_t = internal::as_ref_helper<T>::lvalue;
template<typename T> using as_rref_t = internal::as_ref_helper<T>::rvalue;
template<typename T> using un_ref_t = internal::un_ref_helper<T>::type;
#define AslMove(expr_) (static_cast<::asl::as_rref_t<::asl::un_ref_t<decltype(expr_)>>>(expr_))
#define AslForward(expr_) (static_cast<::asl::as_rref_t<decltype(expr_)>>(expr_))
} // namespace asl

View File

@ -1,33 +0,0 @@
#include "asl/meta/refs.hpp"
#include "asl/meta/types.hpp"
using namespace asl;
static_assert(referenceable<int>);
static_assert(referenceable<int&>);
static_assert(referenceable<int&&>);
static_assert(!referenceable<void>);
static_assert(referenceable<void*>);
static_assert(referenceable<void()>);
static_assert(referenceable<void(*)()>);
static_assert(!referenceable<void() const>);
static_assert(!referenceable<void() &>);
static_assert(!referenceable<void() const &&>);
static_assert(!is_ref<int>);
static_assert(!is_rref<int>);
static_assert(!is_any_ref<int>);
static_assert(is_ref<int&>);
static_assert(!is_rref<int&>);
static_assert(is_any_ref<int&>);
static_assert(!is_ref<int&&>);
static_assert(is_rref<int&&>);
static_assert(is_any_ref<int&&>);
static_assert(!is_any_ref<void()>);
static_assert(!is_any_ref<void() const>);
static_assert(!is_any_ref<void() &>);
int main() { return 0; }

View File

@ -1,13 +0,0 @@
#pragma once
#include "asl/meta/internal/types.hpp"
namespace asl {
template<typename T> using void_t = void;
template<typename U, typename V>
concept same = internal::is_same<U, V> && internal::is_same<V, U>;
} // namespace asl

View File

@ -1,10 +0,0 @@
#include "asl/meta/types.hpp"
using namespace asl;
static_assert(same<int, int>);
static_assert(same<void, void>);
static_assert(!same<const float, float>);
static_assert(!same<int, float>);
int main() { return 0; }

572
asl/meta_tests.cpp Normal file
View File

@ -0,0 +1,572 @@
#include "asl/meta.hpp"
struct Struct { int b: 4; };
union Union {};
enum Enum { EnumVariant = 0, };
enum EnumClass { Variant = 0, };
static_assert(!asl::is_same<long, short>);
static_assert(asl::is_same<int, int>);
static_assert(asl::is_same<asl::un_ref_t<int>, int>);
static_assert(asl::is_same<asl::un_ref_t<int&>, int>);
static_assert(asl::is_same<asl::un_ref_t<int&&>, int>);
static_assert(asl::is_same<asl::un_const_t<int>, int>);
static_assert(asl::is_same<asl::un_const_t<const int>, int>);
static_assert(asl::is_same<asl::un_volatile_t<int>, int>);
static_assert(asl::is_same<asl::un_volatile_t<volatile int>, int>);
static_assert(asl::is_same<asl::un_qual_t<int>, int>);
static_assert(asl::is_same<asl::un_qual_t<volatile int>, int>);
static_assert(asl::is_same<asl::un_qual_t<const int>, int>);
static_assert(asl::is_same<asl::un_qual_t<const volatile int>, int>);
static_assert(asl::is_same<asl::un_qualref_t<int&>, int>);
static_assert(asl::is_same<asl::un_qualref_t<volatile int&&>, int>);
static_assert(asl::is_same<asl::un_qualref_t<const int>, int>);
static_assert(asl::is_same<asl::un_qualref_t<const volatile int&>, int>);
static_assert(!asl::is_const<void>);
static_assert(asl::is_const<const int>);
static_assert(!asl::is_const<const int*>);
static_assert(asl::is_const<int* const>);
static_assert(asl::is_void<void>);
static_assert(asl::is_void<const void>);
static_assert(!asl::is_void<int>);
static_assert(asl::is_nullptr<asl::nullptr_t>);
static_assert(asl::is_nullptr<decltype(nullptr)>);
static_assert(!asl::is_nullptr<decltype(0)>);
static_assert(!asl::is_nullptr<void*>);
static_assert(!asl::is_ptr<decltype(nullptr)>);
static_assert(asl::is_integral<int>);
static_assert(asl::is_integral<decltype(Struct::b)>);
static_assert(asl::is_integral<const int>);
static_assert(asl::is_integral<bool>);
static_assert(!asl::is_integral<int*>);
static_assert(!asl::is_integral<float>);
static_assert(!asl::is_integral<void>);
static_assert(!asl::is_integral<asl::nullptr_t>);
static_assert(!asl::is_integral<int&>);
static_assert(!asl::is_integral<int&&>);
static_assert(!asl::is_integral<int[25]>);
static_assert(!asl::is_integral<int[]>);
static_assert(!asl::is_integral<int()>);
static_assert(!asl::is_integral<Struct>);
static_assert(!asl::is_integral<Union>);
static_assert(!asl::is_integral<Enum>);
static_assert(!asl::is_integral<EnumClass>);
static_assert(asl::is_floating_point<float>);
static_assert(!asl::is_floating_point<void>);
static_assert(!asl::is_floating_point<asl::nullptr_t>);
static_assert(!asl::is_floating_point<int>);
static_assert(!asl::is_floating_point<decltype(Struct::b)>);
static_assert(!asl::is_floating_point<const int>);
static_assert(!asl::is_floating_point<bool>);
static_assert(!asl::is_floating_point<int*>);
static_assert(!asl::is_floating_point<int&>);
static_assert(!asl::is_floating_point<int&&>);
static_assert(!asl::is_floating_point<int[25]>);
static_assert(!asl::is_floating_point<int[]>);
static_assert(!asl::is_floating_point<int()>);
static_assert(!asl::is_floating_point<Struct>);
static_assert(!asl::is_floating_point<Union>);
static_assert(!asl::is_floating_point<Enum>);
static_assert(!asl::is_floating_point<EnumClass>);
static_assert(asl::is_arithmetic<float>);
static_assert(!asl::is_arithmetic<void>);
static_assert(!asl::is_arithmetic<asl::nullptr_t>);
static_assert(asl::is_arithmetic<int>);
static_assert(asl::is_arithmetic<decltype(Struct::b)>);
static_assert(asl::is_arithmetic<const int>);
static_assert(asl::is_arithmetic<bool>);
static_assert(!asl::is_arithmetic<int*>);
static_assert(!asl::is_arithmetic<int&>);
static_assert(!asl::is_arithmetic<int&&>);
static_assert(!asl::is_arithmetic<int[25]>);
static_assert(!asl::is_arithmetic<int[]>);
static_assert(!asl::is_arithmetic<int()>);
static_assert(!asl::is_arithmetic<Struct>);
static_assert(!asl::is_arithmetic<Union>);
static_assert(!asl::is_arithmetic<Enum>);
static_assert(!asl::is_arithmetic<EnumClass>);
static_assert(asl::is_fundamental<float>);
static_assert(asl::is_fundamental<void>);
static_assert(asl::is_fundamental<asl::nullptr_t>);
static_assert(asl::is_fundamental<int>);
static_assert(asl::is_fundamental<decltype(Struct::b)>);
static_assert(asl::is_fundamental<const int>);
static_assert(asl::is_fundamental<bool>);
static_assert(!asl::is_fundamental<int*>);
static_assert(!asl::is_fundamental<int&>);
static_assert(!asl::is_fundamental<int&&>);
static_assert(!asl::is_fundamental<int[25]>);
static_assert(!asl::is_fundamental<int[]>);
static_assert(!asl::is_fundamental<int()>);
static_assert(!asl::is_fundamental<Struct>);
static_assert(!asl::is_fundamental<Union>);
static_assert(!asl::is_fundamental<Enum>);
static_assert(!asl::is_fundamental<EnumClass>);
static_assert(!asl::is_array<float>);
static_assert(!asl::is_array<void>);
static_assert(!asl::is_array<asl::nullptr_t>);
static_assert(!asl::is_array<int>);
static_assert(!asl::is_array<decltype(Struct::b)>);
static_assert(!asl::is_array<const int>);
static_assert(!asl::is_array<bool>);
static_assert(!asl::is_array<int*>);
static_assert(!asl::is_array<int&>);
static_assert(!asl::is_array<int&&>);
static_assert(asl::is_array<int[25]>);
static_assert(asl::is_array<int[]>);
static_assert(asl::is_array<int*[]>);
static_assert(!asl::is_array<int(&)[]>);
static_assert(!asl::is_array<int(*)[]>);
static_assert(asl::is_array<int[]>);
static_assert(asl::is_array<Struct[4]>);
static_assert(asl::is_array<Union[]>);
static_assert(asl::is_array<Enum[]>);
static_assert(!asl::is_array<int()>);
static_assert(!asl::is_array<Struct>);
static_assert(!asl::is_array<Union>);
static_assert(!asl::is_array<Enum>);
static_assert(!asl::is_array<EnumClass>);
static_assert(!asl::is_class<float>);
static_assert(!asl::is_class<void>);
static_assert(!asl::is_class<asl::nullptr_t>);
static_assert(!asl::is_class<int>);
static_assert(!asl::is_class<decltype(Struct::b)>);
static_assert(!asl::is_class<const int>);
static_assert(!asl::is_class<bool>);
static_assert(!asl::is_class<int*>);
static_assert(!asl::is_class<int&>);
static_assert(!asl::is_class<int&&>);
static_assert(!asl::is_class<int[25]>);
static_assert(!asl::is_class<int[]>);
static_assert(!asl::is_class<int*[]>);
static_assert(!asl::is_class<int(&)[]>);
static_assert(!asl::is_class<int(*)[]>);
static_assert(!asl::is_class<int[]>);
static_assert(!asl::is_class<Struct[4]>);
static_assert(!asl::is_class<Union[]>);
static_assert(!asl::is_class<Enum[]>);
static_assert(!asl::is_class<int()>);
static_assert(asl::is_class<Struct>);
static_assert(asl::is_class<const Struct>);
static_assert(!asl::is_class<Struct&>);
static_assert(!asl::is_class<Struct*>);
static_assert(!asl::is_class<Union>);
static_assert(!asl::is_class<Enum>);
static_assert(!asl::is_class<EnumClass>);
static_assert(!asl::is_union<float>);
static_assert(!asl::is_union<void>);
static_assert(!asl::is_union<asl::nullptr_t>);
static_assert(!asl::is_union<int>);
static_assert(!asl::is_union<decltype(Struct::b)>);
static_assert(!asl::is_union<const int>);
static_assert(!asl::is_union<bool>);
static_assert(!asl::is_union<int*>);
static_assert(!asl::is_union<int&>);
static_assert(!asl::is_union<int&&>);
static_assert(!asl::is_union<int[25]>);
static_assert(!asl::is_union<int[]>);
static_assert(!asl::is_union<int*[]>);
static_assert(!asl::is_union<int(&)[]>);
static_assert(!asl::is_union<int(*)[]>);
static_assert(!asl::is_union<int[]>);
static_assert(!asl::is_union<Struct[4]>);
static_assert(!asl::is_union<Union[]>);
static_assert(!asl::is_union<Enum[]>);
static_assert(!asl::is_union<int()>);
static_assert(!asl::is_union<Struct>);
static_assert(asl::is_union<Union>);
static_assert(asl::is_union<const Union>);
static_assert(!asl::is_union<Union*>);
static_assert(!asl::is_union<Union&>);
static_assert(!asl::is_union<Enum>);
static_assert(!asl::is_union<EnumClass>);
static_assert(!asl::is_enum<float>);
static_assert(!asl::is_enum<void>);
static_assert(!asl::is_enum<asl::nullptr_t>);
static_assert(!asl::is_enum<int>);
static_assert(!asl::is_enum<decltype(Struct::b)>);
static_assert(!asl::is_enum<const int>);
static_assert(!asl::is_enum<bool>);
static_assert(!asl::is_enum<int*>);
static_assert(!asl::is_enum<int&>);
static_assert(!asl::is_enum<int&&>);
static_assert(!asl::is_enum<int[25]>);
static_assert(!asl::is_enum<int[]>);
static_assert(!asl::is_enum<int*[]>);
static_assert(!asl::is_enum<int(&)[]>);
static_assert(!asl::is_enum<int(*)[]>);
static_assert(!asl::is_enum<int[]>);
static_assert(!asl::is_enum<Struct[4]>);
static_assert(!asl::is_enum<Union[]>);
static_assert(!asl::is_enum<Enum[]>);
static_assert(!asl::is_enum<int()>);
static_assert(!asl::is_enum<Struct>);
static_assert(!asl::is_enum<const Struct>);
static_assert(!asl::is_enum<Struct&>);
static_assert(!asl::is_enum<Struct*>);
static_assert(!asl::is_enum<Union>);
static_assert(asl::is_enum<Enum>);
static_assert(asl::is_enum<EnumClass>);
static_assert(!asl::is_enum<Enum&>);
static_assert(!asl::is_enum<EnumClass*>);
static_assert(asl::is_enum<const Enum>);
static_assert(asl::is_enum<volatile EnumClass>);
static_assert(!asl::is_ptr<float>);
static_assert(!asl::is_ptr<void>);
static_assert(!asl::is_ptr<asl::nullptr_t>);
static_assert(!asl::is_ptr<int>);
static_assert(!asl::is_ptr<decltype(Struct::b)>);
static_assert(!asl::is_ptr<const int>);
static_assert(!asl::is_ptr<bool>);
static_assert(asl::is_ptr<int*>);
static_assert(asl::is_ptr<const int*>);
static_assert(asl::is_ptr<int* const>);
static_assert(asl::is_ptr<int* const volatile>);
static_assert(asl::is_ptr<int const* volatile>);
static_assert(!asl::is_ptr<int Struct::*>);
static_assert(!asl::is_ptr<int&>);
static_assert(!asl::is_ptr<int&&>);
static_assert(!asl::is_ptr<int[25]>);
static_assert(!asl::is_ptr<int[]>);
static_assert(!asl::is_ptr<int*[]>);
static_assert(!asl::is_ptr<int(&)[]>);
static_assert(asl::is_ptr<int(*)[]>);
static_assert(!asl::is_ptr<int[]>);
static_assert(!asl::is_ptr<Struct[4]>);
static_assert(!asl::is_ptr<Union[]>);
static_assert(!asl::is_ptr<Enum[]>);
static_assert(!asl::is_ptr<int()>);
static_assert(!asl::is_ptr<Struct>);
static_assert(!asl::is_ptr<const Struct>);
static_assert(!asl::is_ptr<Struct&>);
static_assert(asl::is_ptr<Struct*>);
static_assert(!asl::is_ptr<Union>);
static_assert(!asl::is_ptr<Enum>);
static_assert(!asl::is_ptr<EnumClass>);
static_assert(!asl::is_ref<float>);
static_assert(!asl::is_ref<void>);
static_assert(!asl::is_ref<asl::nullptr_t>);
static_assert(!asl::is_ref<int>);
static_assert(!asl::is_ref<decltype(Struct::b)>);
static_assert(!asl::is_ref<const int>);
static_assert(!asl::is_ref<bool>);
static_assert(!asl::is_ref<int*>);
static_assert(!asl::is_ref<const int*>);
static_assert(!asl::is_ref<int* const>);
static_assert(!asl::is_ref<int* const volatile>);
static_assert(!asl::is_ref<int const* volatile>);
static_assert(!asl::is_ref<int Struct::*>);
static_assert(asl::is_ref<int&>);
static_assert(asl::is_ref<const int&>);
static_assert(asl::is_ref<int&&>);
static_assert(!asl::is_ref<int[25]>);
static_assert(!asl::is_ref<int[]>);
static_assert(!asl::is_ref<int*[]>);
static_assert(asl::is_ref<int(&)[]>);
static_assert(!asl::is_ref<int(*)[]>);
static_assert(!asl::is_ref<int[]>);
static_assert(!asl::is_ref<Struct[4]>);
static_assert(!asl::is_ref<Union[]>);
static_assert(!asl::is_ref<Enum[]>);
static_assert(!asl::is_ref<int()>);
static_assert(!asl::is_ref<Struct>);
static_assert(!asl::is_ref<const Struct>);
static_assert(asl::is_ref<Struct&>);
static_assert(!asl::is_ref<Struct*>);
static_assert(!asl::is_ref<Union>);
static_assert(!asl::is_ref<Enum>);
static_assert(!asl::is_ref<EnumClass>);
static_assert(!asl::is_lref<float>);
static_assert(!asl::is_lref<void>);
static_assert(!asl::is_lref<asl::nullptr_t>);
static_assert(!asl::is_lref<int>);
static_assert(!asl::is_lref<decltype(Struct::b)>);
static_assert(!asl::is_lref<const int>);
static_assert(!asl::is_lref<bool>);
static_assert(!asl::is_lref<int*>);
static_assert(!asl::is_lref<const int*>);
static_assert(!asl::is_lref<int* const>);
static_assert(!asl::is_lref<int* const volatile>);
static_assert(!asl::is_lref<int const* volatile>);
static_assert(!asl::is_lref<int Struct::*>);
static_assert(asl::is_lref<int&>);
static_assert(asl::is_lref<const int&>);
static_assert(!asl::is_lref<int&&>);
static_assert(!asl::is_lref<int[25]>);
static_assert(!asl::is_lref<int[]>);
static_assert(!asl::is_lref<int*[]>);
static_assert(asl::is_lref<int(&)[]>);
static_assert(!asl::is_lref<int(*)[]>);
static_assert(!asl::is_lref<int[]>);
static_assert(!asl::is_lref<Struct[4]>);
static_assert(!asl::is_lref<Union[]>);
static_assert(!asl::is_lref<Enum[]>);
static_assert(!asl::is_lref<int()>);
static_assert(!asl::is_lref<Struct>);
static_assert(!asl::is_lref<const Struct>);
static_assert(asl::is_lref<Struct&>);
static_assert(!asl::is_lref<Struct*>);
static_assert(!asl::is_lref<Union>);
static_assert(!asl::is_lref<Enum>);
static_assert(!asl::is_lref<EnumClass>);
static_assert(!asl::is_rref<float>);
static_assert(!asl::is_rref<void>);
static_assert(!asl::is_rref<asl::nullptr_t>);
static_assert(!asl::is_rref<int>);
static_assert(!asl::is_rref<decltype(Struct::b)>);
static_assert(!asl::is_rref<const int>);
static_assert(!asl::is_rref<bool>);
static_assert(!asl::is_rref<int*>);
static_assert(!asl::is_rref<const int*>);
static_assert(!asl::is_rref<int* const>);
static_assert(!asl::is_rref<int* const volatile>);
static_assert(!asl::is_rref<int const* volatile>);
static_assert(!asl::is_rref<int Struct::*>);
static_assert(!asl::is_rref<int&>);
static_assert(!asl::is_rref<const int&>);
static_assert(asl::is_rref<int&&>);
static_assert(!asl::is_rref<int[25]>);
static_assert(!asl::is_rref<int[]>);
static_assert(!asl::is_rref<int*[]>);
static_assert(!asl::is_rref<int(&)[]>);
static_assert(!asl::is_rref<int(*)[]>);
static_assert(!asl::is_rref<int[]>);
static_assert(!asl::is_rref<Struct[4]>);
static_assert(!asl::is_rref<Union[]>);
static_assert(!asl::is_rref<Enum[]>);
static_assert(!asl::is_rref<int()>);
static_assert(!asl::is_rref<Struct>);
static_assert(!asl::is_rref<const Struct>);
static_assert(!asl::is_rref<Struct&>);
static_assert(!asl::is_rref<Struct*>);
static_assert(!asl::is_rref<Union>);
static_assert(!asl::is_rref<Enum>);
static_assert(!asl::is_rref<EnumClass>);
static_assert(!asl::is_member_ptr<float>);
static_assert(!asl::is_member_ptr<void>);
static_assert(!asl::is_member_ptr<asl::nullptr_t>);
static_assert(!asl::is_member_ptr<int>);
static_assert(!asl::is_member_ptr<decltype(Struct::b)>);
static_assert(!asl::is_member_ptr<const int>);
static_assert(!asl::is_member_ptr<bool>);
static_assert(!asl::is_member_ptr<int*>);
static_assert(!asl::is_member_ptr<const int*>);
static_assert(!asl::is_member_ptr<int* const>);
static_assert(!asl::is_member_ptr<int* const volatile>);
static_assert(!asl::is_member_ptr<int const* volatile>);
static_assert(asl::is_member_ptr<int Struct::*>);
static_assert(asl::is_member_ptr<int (Struct::*)()>);
static_assert(!asl::is_member_ptr<int&>);
static_assert(!asl::is_member_ptr<int&&>);
static_assert(!asl::is_member_ptr<int[25]>);
static_assert(!asl::is_member_ptr<int[]>);
static_assert(!asl::is_member_ptr<int*[]>);
static_assert(!asl::is_member_ptr<int(&)[]>);
static_assert(!asl::is_member_ptr<int(*)[]>);
static_assert(!asl::is_member_ptr<int[]>);
static_assert(!asl::is_member_ptr<Struct[4]>);
static_assert(!asl::is_member_ptr<Union[]>);
static_assert(!asl::is_member_ptr<Enum[]>);
static_assert(!asl::is_member_ptr<int()>);
static_assert(!asl::is_member_ptr<Struct>);
static_assert(!asl::is_member_ptr<const Struct>);
static_assert(!asl::is_member_ptr<Struct&>);
static_assert(!asl::is_member_ptr<Struct*>);
static_assert(!asl::is_member_ptr<Union>);
static_assert(!asl::is_member_ptr<Enum>);
static_assert(!asl::is_member_ptr<EnumClass>);
static_assert(!asl::is_member_object_ptr<float>);
static_assert(!asl::is_member_object_ptr<void>);
static_assert(!asl::is_member_object_ptr<asl::nullptr_t>);
static_assert(!asl::is_member_object_ptr<int>);
static_assert(!asl::is_member_object_ptr<decltype(Struct::b)>);
static_assert(!asl::is_member_object_ptr<const int>);
static_assert(!asl::is_member_object_ptr<bool>);
static_assert(!asl::is_member_object_ptr<int*>);
static_assert(!asl::is_member_object_ptr<const int*>);
static_assert(!asl::is_member_object_ptr<int* const>);
static_assert(!asl::is_member_object_ptr<int* const volatile>);
static_assert(!asl::is_member_object_ptr<int const* volatile>);
static_assert(asl::is_member_object_ptr<int Struct::*>);
static_assert(!asl::is_member_object_ptr<int (Struct::*)()>);
static_assert(!asl::is_member_object_ptr<int&>);
static_assert(!asl::is_member_object_ptr<int&&>);
static_assert(!asl::is_member_object_ptr<int[25]>);
static_assert(!asl::is_member_object_ptr<int[]>);
static_assert(!asl::is_member_object_ptr<int*[]>);
static_assert(!asl::is_member_object_ptr<int(&)[]>);
static_assert(!asl::is_member_object_ptr<int(*)[]>);
static_assert(!asl::is_member_object_ptr<int[]>);
static_assert(!asl::is_member_object_ptr<Struct[4]>);
static_assert(!asl::is_member_object_ptr<Union[]>);
static_assert(!asl::is_member_object_ptr<Enum[]>);
static_assert(!asl::is_member_object_ptr<int()>);
static_assert(!asl::is_member_object_ptr<Struct>);
static_assert(!asl::is_member_object_ptr<const Struct>);
static_assert(!asl::is_member_object_ptr<Struct&>);
static_assert(!asl::is_member_object_ptr<Struct*>);
static_assert(!asl::is_member_object_ptr<Union>);
static_assert(!asl::is_member_object_ptr<Enum>);
static_assert(!asl::is_member_object_ptr<EnumClass>);
static_assert(!asl::is_member_func_ptr<float>);
static_assert(!asl::is_member_func_ptr<void>);
static_assert(!asl::is_member_func_ptr<asl::nullptr_t>);
static_assert(!asl::is_member_func_ptr<int>);
static_assert(!asl::is_member_func_ptr<decltype(Struct::b)>);
static_assert(!asl::is_member_func_ptr<const int>);
static_assert(!asl::is_member_func_ptr<bool>);
static_assert(!asl::is_member_func_ptr<int*>);
static_assert(!asl::is_member_func_ptr<const int*>);
static_assert(!asl::is_member_func_ptr<int* const>);
static_assert(!asl::is_member_func_ptr<int* const volatile>);
static_assert(!asl::is_member_func_ptr<int const* volatile>);
static_assert(!asl::is_member_func_ptr<int Struct::*>);
static_assert(asl::is_member_func_ptr<int (Struct::*)()>);
static_assert(!asl::is_member_func_ptr<int&>);
static_assert(!asl::is_member_func_ptr<int&&>);
static_assert(!asl::is_member_func_ptr<int[25]>);
static_assert(!asl::is_member_func_ptr<int[]>);
static_assert(!asl::is_member_func_ptr<int*[]>);
static_assert(!asl::is_member_func_ptr<int(&)[]>);
static_assert(!asl::is_member_func_ptr<int(*)[]>);
static_assert(!asl::is_member_func_ptr<int[]>);
static_assert(!asl::is_member_func_ptr<Struct[4]>);
static_assert(!asl::is_member_func_ptr<Union[]>);
static_assert(!asl::is_member_func_ptr<Enum[]>);
static_assert(!asl::is_member_func_ptr<int()>);
static_assert(!asl::is_member_func_ptr<Struct>);
static_assert(!asl::is_member_func_ptr<const Struct>);
static_assert(!asl::is_member_func_ptr<Struct&>);
static_assert(!asl::is_member_func_ptr<Struct*>);
static_assert(!asl::is_member_func_ptr<Union>);
static_assert(!asl::is_member_func_ptr<Enum>);
static_assert(!asl::is_member_func_ptr<EnumClass>);
static_assert(!asl::is_compound<float>);
static_assert(!asl::is_compound<void>);
static_assert(!asl::is_compound<asl::nullptr_t>);
static_assert(!asl::is_compound<int>);
static_assert(!asl::is_compound<decltype(Struct::b)>);
static_assert(!asl::is_compound<const int>);
static_assert(!asl::is_compound<bool>);
static_assert(asl::is_compound<int*>);
static_assert(asl::is_compound<const int*>);
static_assert(asl::is_compound<int* const>);
static_assert(asl::is_compound<int* const volatile>);
static_assert(asl::is_compound<int const* volatile>);
static_assert(asl::is_compound<int Struct::*>);
static_assert(asl::is_compound<int (Struct::*)()>);
static_assert(asl::is_compound<int&>);
static_assert(asl::is_compound<int&&>);
static_assert(asl::is_compound<int[25]>);
static_assert(asl::is_compound<int[]>);
static_assert(asl::is_compound<int*[]>);
static_assert(asl::is_compound<int(&)[]>);
static_assert(asl::is_compound<int(*)[]>);
static_assert(asl::is_compound<int[]>);
static_assert(asl::is_compound<Struct[4]>);
static_assert(asl::is_compound<Union[]>);
static_assert(asl::is_compound<Enum[]>);
static_assert(asl::is_compound<int()>);
static_assert(asl::is_compound<Struct>);
static_assert(asl::is_compound<const Struct>);
static_assert(asl::is_compound<Struct&>);
static_assert(asl::is_compound<Struct*>);
static_assert(asl::is_compound<Union>);
static_assert(asl::is_compound<Enum>);
static_assert(asl::is_compound<EnumClass>);
static_assert(asl::is_scalar<float>);
static_assert(!asl::is_scalar<void>);
static_assert(asl::is_scalar<asl::nullptr_t>);
static_assert(asl::is_scalar<int>);
static_assert(asl::is_scalar<decltype(Struct::b)>);
static_assert(asl::is_scalar<const int>);
static_assert(asl::is_scalar<bool>);
static_assert(asl::is_scalar<int*>);
static_assert(asl::is_scalar<const int*>);
static_assert(asl::is_scalar<int* const>);
static_assert(asl::is_scalar<int* const volatile>);
static_assert(asl::is_scalar<int const* volatile>);
static_assert(asl::is_scalar<int Struct::*>);
static_assert(asl::is_scalar<int (Struct::*)()>);
static_assert(!asl::is_scalar<int&>);
static_assert(!asl::is_scalar<int&&>);
static_assert(!asl::is_scalar<int[25]>);
static_assert(!asl::is_scalar<int[]>);
static_assert(!asl::is_scalar<int*[]>);
static_assert(!asl::is_scalar<int(&)[]>);
static_assert(asl::is_scalar<int(*)[]>);
static_assert(!asl::is_scalar<int[]>);
static_assert(!asl::is_scalar<Struct[4]>);
static_assert(!asl::is_scalar<Union[]>);
static_assert(!asl::is_scalar<Enum[]>);
static_assert(!asl::is_scalar<int()>);
static_assert(!asl::is_scalar<Struct>);
static_assert(!asl::is_scalar<const Struct>);
static_assert(!asl::is_scalar<Struct&>);
static_assert(asl::is_scalar<Struct*>);
static_assert(!asl::is_scalar<Union>);
static_assert(asl::is_scalar<Enum>);
static_assert(asl::is_scalar<EnumClass>);
static_assert(asl::is_object<float>);
static_assert(!asl::is_object<void>);
static_assert(asl::is_object<asl::nullptr_t>);
static_assert(asl::is_object<int>);
static_assert(asl::is_object<decltype(Struct::b)>);
static_assert(asl::is_object<const int>);
static_assert(asl::is_object<bool>);
static_assert(asl::is_object<int*>);
static_assert(asl::is_object<const int*>);
static_assert(asl::is_object<int* const>);
static_assert(asl::is_object<int* const volatile>);
static_assert(asl::is_object<int const* volatile>);
static_assert(asl::is_object<int Struct::*>);
static_assert(asl::is_object<int (Struct::*)()>);
static_assert(!asl::is_object<int&>);
static_assert(!asl::is_object<int&&>);
static_assert(asl::is_object<int[25]>);
static_assert(asl::is_object<int[]>);
static_assert(asl::is_object<int*[]>);
static_assert(!asl::is_object<int(&)[]>);
static_assert(asl::is_object<int(*)[]>);
static_assert(asl::is_object<int[]>);
static_assert(asl::is_object<Struct[4]>);
static_assert(asl::is_object<Union[]>);
static_assert(asl::is_object<Enum[]>);
static_assert(!asl::is_object<int()>);
static_assert(asl::is_object<Struct>);
static_assert(asl::is_object<const Struct>);
static_assert(!asl::is_object<Struct&>);
static_assert(asl::is_object<Struct*>);
static_assert(asl::is_object<Union>);
static_assert(asl::is_object<Enum>);
static_assert(asl::is_object<EnumClass>);
int main() { return 0; }