diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-08-06 00:34:57 +0200 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-08-07 23:25:42 +0200 |
commit | 75b10758ba116eabed730d23e957f1d69a1e3cb8 (patch) | |
tree | 6fb656d6aa18e3b8fd67d0fed39b79234a23fc1d | |
parent | 4228e82740f62b841799cfca04861fa217fb93a5 (diff) |
Type traits
-rw-r--r-- | asl/BUILD.bazel | 18 | ||||
-rw-r--r-- | asl/base/BUILD.bazel | 18 | ||||
-rw-r--r-- | asl/integers.hpp (renamed from asl/base/integers.hpp) | 0 | ||||
-rw-r--r-- | asl/integers_tests.cpp (renamed from asl/base/integers_tests.cpp) | 2 | ||||
-rw-r--r-- | asl/memory/BUILD.bazel | 10 | ||||
-rw-r--r-- | asl/memory/layout.hpp | 6 | ||||
-rw-r--r-- | asl/meta.hpp | 89 | ||||
-rw-r--r-- | asl/meta/BUILD.bazel | 27 | ||||
-rw-r--r-- | asl/meta/empty.hpp | 11 | ||||
-rw-r--r-- | asl/meta/empty_tests.cpp | 17 | ||||
-rw-r--r-- | asl/meta/funcs.hpp | 11 | ||||
-rw-r--r-- | asl/meta/funcs_tests.cpp | 14 | ||||
-rw-r--r-- | asl/meta/internal/quals.hpp | 16 | ||||
-rw-r--r-- | asl/meta/internal/refs.hpp | 45 | ||||
-rw-r--r-- | asl/meta/internal/types.hpp | 9 | ||||
-rw-r--r-- | asl/meta/quals.hpp | 22 | ||||
-rw-r--r-- | asl/meta/quals_tests.cpp | 51 | ||||
-rw-r--r-- | asl/meta/refs.hpp | 21 | ||||
-rw-r--r-- | asl/meta/refs_tests.cpp | 33 | ||||
-rw-r--r-- | asl/meta/types.hpp | 13 | ||||
-rw-r--r-- | asl/meta/types_tests.cpp | 10 | ||||
-rw-r--r-- | asl/meta_tests.cpp | 572 |
22 files changed, 680 insertions, 335 deletions
diff --git a/asl/BUILD.bazel b/asl/BUILD.bazel new file mode 100644 index 0000000..dc0aef8 --- /dev/null +++ b/asl/BUILD.bazel @@ -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"]]
diff --git a/asl/base/BUILD.bazel b/asl/base/BUILD.bazel deleted file mode 100644 index 4ce905b..0000000 --- a/asl/base/BUILD.bazel +++ /dev/null @@ -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",
- ],
-)
-
diff --git a/asl/base/integers.hpp b/asl/integers.hpp index 07fa11e..07fa11e 100644 --- a/asl/base/integers.hpp +++ b/asl/integers.hpp diff --git a/asl/base/integers_tests.cpp b/asl/integers_tests.cpp index 587556d..0393a3c 100644 --- a/asl/base/integers_tests.cpp +++ b/asl/integers_tests.cpp @@ -1,4 +1,4 @@ -#include "asl/base/integers.hpp"
+#include "asl/integers.hpp"
static_assert(sizeof(int8_t) == 1);
static_assert(sizeof(int16_t) == 2);
diff --git a/asl/memory/BUILD.bazel b/asl/memory/BUILD.bazel deleted file mode 100644 index 7029496..0000000 --- a/asl/memory/BUILD.bazel +++ /dev/null @@ -1,10 +0,0 @@ -cc_library(
- name = "memory",
- hdrs = [
- "layout.hpp",
- ],
- deps = [
- "//asl/base",
- ],
- visibility = ["//visibility:public"],
-)
diff --git a/asl/memory/layout.hpp b/asl/memory/layout.hpp deleted file mode 100644 index 02ab518..0000000 --- a/asl/memory/layout.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once
-
-namespace asl {
-
-} // namespace asl
-
diff --git a/asl/meta.hpp b/asl/meta.hpp new file mode 100644 index 0000000..15f7790 --- /dev/null +++ b/asl/meta.hpp @@ -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
diff --git a/asl/meta/BUILD.bazel b/asl/meta/BUILD.bazel deleted file mode 100644 index e5b44a7..0000000 --- a/asl/meta/BUILD.bazel +++ /dev/null @@ -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"]]
-
diff --git a/asl/meta/empty.hpp b/asl/meta/empty.hpp deleted file mode 100644 index 9552fbd..0000000 --- a/asl/meta/empty.hpp +++ /dev/null @@ -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
- diff --git a/asl/meta/empty_tests.cpp b/asl/meta/empty_tests.cpp deleted file mode 100644 index c5bf519..0000000 --- a/asl/meta/empty_tests.cpp +++ /dev/null @@ -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; }
diff --git a/asl/meta/funcs.hpp b/asl/meta/funcs.hpp deleted file mode 100644 index f699dac..0000000 --- a/asl/meta/funcs.hpp +++ /dev/null @@ -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
- diff --git a/asl/meta/funcs_tests.cpp b/asl/meta/funcs_tests.cpp deleted file mode 100644 index f2f40a2..0000000 --- a/asl/meta/funcs_tests.cpp +++ /dev/null @@ -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; }
diff --git a/asl/meta/internal/quals.hpp b/asl/meta/internal/quals.hpp deleted file mode 100644 index 869cc89..0000000 --- a/asl/meta/internal/quals.hpp +++ /dev/null @@ -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
- diff --git a/asl/meta/internal/refs.hpp b/asl/meta/internal/refs.hpp deleted file mode 100644 index b21a0a1..0000000 --- a/asl/meta/internal/refs.hpp +++ /dev/null @@ -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
-
diff --git a/asl/meta/internal/types.hpp b/asl/meta/internal/types.hpp deleted file mode 100644 index f635de5..0000000 --- a/asl/meta/internal/types.hpp +++ /dev/null @@ -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
- diff --git a/asl/meta/quals.hpp b/asl/meta/quals.hpp deleted file mode 100644 index 9671043..0000000 --- a/asl/meta/quals.hpp +++ /dev/null @@ -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
- diff --git a/asl/meta/quals_tests.cpp b/asl/meta/quals_tests.cpp deleted file mode 100644 index 37ecc6c..0000000 --- a/asl/meta/quals_tests.cpp +++ /dev/null @@ -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; }
diff --git a/asl/meta/refs.hpp b/asl/meta/refs.hpp deleted file mode 100644 index b72458a..0000000 --- a/asl/meta/refs.hpp +++ /dev/null @@ -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
diff --git a/asl/meta/refs_tests.cpp b/asl/meta/refs_tests.cpp deleted file mode 100644 index 49d4f23..0000000 --- a/asl/meta/refs_tests.cpp +++ /dev/null @@ -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; }
diff --git a/asl/meta/types.hpp b/asl/meta/types.hpp deleted file mode 100644 index bfc2998..0000000 --- a/asl/meta/types.hpp +++ /dev/null @@ -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
- diff --git a/asl/meta/types_tests.cpp b/asl/meta/types_tests.cpp deleted file mode 100644 index 180ecda..0000000 --- a/asl/meta/types_tests.cpp +++ /dev/null @@ -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; }
diff --git a/asl/meta_tests.cpp b/asl/meta_tests.cpp new file mode 100644 index 0000000..f3d31f4 --- /dev/null +++ b/asl/meta_tests.cpp @@ -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<i |