// Copyright 2025 Steven Le Rouzic // // SPDX-License-Identifier: BSD-3-Clause #include "asl/base/meta.hpp" #include "asl/tests/types.hpp" #include "asl/testing/testing.hpp" #include "asl/types/box.hpp" struct Struct {}; union Union {}; enum Enum : uint8_t { EnumVariant = 0, }; enum class EnumClass : uint8_t { Variant = 0, }; static_assert(!asl::same_as<long, short>); static_assert(asl::same_as<int, int>); static_assert(asl::same_as<asl::select_t<false, int, float>, float>); static_assert(asl::same_as<asl::select_t<true, int, float>, int>); static_assert(asl::default_constructible<int>); static_assert(asl::default_constructible<TrivialType>); static_assert(asl::default_constructible<TrivialTypeDefaultValue>); static_assert(asl::trivially_default_constructible<int>); static_assert(asl::trivially_default_constructible<TrivialType>); static_assert(!asl::trivially_default_constructible<TrivialTypeDefaultValue>); static_assert(asl::copy_constructible<int>); static_assert(asl::copy_constructible<TrivialType>); static_assert(asl::copy_constructible<Copyable>); static_assert(!asl::copy_constructible<MoveableOnly>); static_assert(!asl::copy_constructible<Pinned>); static_assert(asl::trivially_copy_constructible<int>); static_assert(asl::trivially_copy_constructible<TrivialType>); static_assert(asl::trivially_copy_constructible<TrivialTypeDefaultValue>); static_assert(!asl::trivially_copy_constructible<WithDestructor>); static_assert(!asl::trivially_copy_constructible<Copyable>); static_assert(!asl::trivially_copy_constructible<MoveableOnly>); static_assert(!asl::trivially_copy_constructible<Pinned>); static_assert(asl::move_constructible<int>); static_assert(asl::move_constructible<TrivialType>); static_assert(asl::move_constructible<Copyable>); static_assert(asl::move_constructible<MoveableOnly>); static_assert(!asl::move_constructible<Pinned>); static_assert(asl::trivially_move_constructible<int>); static_assert(asl::trivially_move_constructible<TrivialType>); static_assert(asl::trivially_move_constructible<TrivialTypeDefaultValue>); static_assert(!asl::trivially_move_constructible<WithDestructor>); static_assert(!asl::trivially_move_constructible<Copyable>); static_assert(!asl::trivially_move_constructible<MoveableOnly>); static_assert(!asl::trivially_move_constructible<Pinned>); static_assert(asl::copy_assignable<int>); static_assert(asl::copy_assignable<TrivialType>); static_assert(asl::copy_assignable<Copyable>); static_assert(!asl::copy_assignable<MoveableOnly>); static_assert(!asl::copy_assignable<Pinned>); static_assert(asl::trivially_copy_assignable<int>); static_assert(asl::trivially_copy_assignable<TrivialType>); static_assert(asl::trivially_copy_assignable<TrivialTypeDefaultValue>); static_assert(asl::trivially_copy_assignable<WithDestructor>); static_assert(!asl::trivially_copy_assignable<Copyable>); static_assert(!asl::trivially_copy_assignable<MoveableOnly>); static_assert(!asl::trivially_copy_assignable<Pinned>); static_assert(asl::copyable<int>); static_assert(asl::copyable<TrivialType>); static_assert(asl::copyable<Copyable>); static_assert(!asl::copyable<MoveableOnly>); static_assert(!asl::copyable<Pinned>); static_assert(asl::moveable<int>); static_assert(asl::moveable<TrivialType>); static_assert(asl::moveable<Copyable>); static_assert(asl::moveable<MoveableOnly>); static_assert(!asl::moveable<Pinned>); static_assert(asl::move_assignable<int>); static_assert(asl::move_assignable<TrivialType>); static_assert(asl::move_assignable<Copyable>); static_assert(asl::move_assignable<MoveableOnly>); static_assert(!asl::move_assignable<Pinned>); static_assert(asl::trivially_move_assignable<int>); static_assert(asl::trivially_move_assignable<TrivialType>); static_assert(asl::trivially_move_assignable<TrivialTypeDefaultValue>); static_assert(asl::trivially_move_assignable<WithDestructor>); static_assert(!asl::trivially_move_assignable<Copyable>); static_assert(!asl::trivially_move_assignable<MoveableOnly>); static_assert(!asl::trivially_move_assignable<Pinned>); static_assert(asl::trivially_destructible<int>); static_assert(asl::trivially_destructible<TrivialType>); static_assert(asl::trivially_destructible<TrivialTypeDefaultValue>); static_assert(!asl::trivially_destructible<WithDestructor>); static_assert(asl::trivially_destructible<Copyable>); static_assert(asl::trivially_destructible<MoveableOnly>); static_assert(asl::trivially_destructible<Pinned>); static_assert(asl::same_as<int, asl::un_const_t<int>>); static_assert(asl::same_as<int, asl::un_const_t<const int>>); static_assert(asl::same_as<const int&, asl::un_const_t<const int&>>); static_assert(asl::same_as<int, asl::un_volatile_t<int>>); static_assert(asl::same_as<int, asl::un_volatile_t<volatile int>>); static_assert(asl::same_as<volatile int&, asl::un_volatile_t<volatile int&>>); static_assert(asl::same_as<int, asl::un_cv_t<int>>); static_assert(asl::same_as<int, asl::un_cv_t<const int>>); static_assert(asl::same_as<int, asl::un_cv_t<const volatile int>>); static_assert(asl::same_as<int, asl::un_cv_t<volatile int>>); static_assert(asl::is_void<void>); static_assert(asl::is_void<const void>); static_assert(asl::is_void<const volatile void>); static_assert(asl::is_void<volatile void>); static_assert(!asl::is_void<int>); static_assert(!asl::is_void<Struct>); static_assert(!asl::is_void<int&>); static_assert(!asl::is_void<int&&>); static_assert(!asl::is_void<void()>); static_assert(!asl::is_void<void() const &&>); static_assert(asl::is_ref<int&>); static_assert(asl::is_ref<const int&>); static_assert(asl::is_ref<const volatile int&>); static_assert(asl::is_ref<int&&>); static_assert(!asl::is_ref<int>); static_assert(!asl::is_ref<void>); static_assert(!asl::is_ref<void()>); static_assert(!asl::is_ref<void() const &&>); struct MyClass { int data; int fn(int x) { return x; } // NOLINT }; static_assert(asl::is_ptr<int*>); static_assert(asl::is_ptr<const int* const>); static_assert(asl::is_ptr<const volatile int*>); static_assert(!asl::is_ptr<int>); static_assert(!asl::is_ptr<void>); static_assert(!asl::is_ptr<void()>); static_assert(!asl::is_ptr<void() const &&>); static_assert(!asl::is_ptr<int MyClass::*>); static_assert(!asl::is_ptr<int (MyClass::*)(int)>); static_assert(!asl::is_member_ptr<int*>); static_assert(!asl::is_member_ptr<void()>); static_assert(!asl::is_member_ptr<void() const &&>); static_assert(asl::is_member_ptr<int MyClass::*>); static_assert(asl::is_member_ptr<int (MyClass::*)(int)>); static_assert(!asl::is_member_data_ptr<int*>); static_assert(!asl::is_member_data_ptr<void()>); static_assert(!asl::is_member_data_ptr<void() const &&>); static_assert(asl::is_member_data_ptr<int MyClass::*>); static_assert(!asl::is_member_data_ptr<int (MyClass::*)(int)>); static_assert(!asl::is_member_func_ptr<int*>); static_assert(!asl::is_member_func_ptr<void()>); static_assert(!asl::is_member_func_ptr<void() const &&>); static_assert(!asl::is_member_func_ptr<int MyClass::*>); static_assert(asl::is_member_func_ptr<int (MyClass::*)(int)>); static_assert(asl::is_member_func_ptr<int (MyClass::*)(int) const>); static_assert(asl::is_member_func_ptr<int (MyClass::*)(int) volatile &&>); static_assert(asl::same_as<int, asl::tame_t<int>>); static_assert(asl::same_as<int(), asl::tame_t<int()>>); static_assert(asl::same_as<int(float), asl::tame_t<int(float)>>); static_assert(asl::same_as<int(float), asl::tame_t<int(float) &>>); static_assert(asl::same_as<int(float), asl::tame_t<int(float) const &&>>); static_assert(asl::same_as<int(float), asl::tame_t<int(float) volatile noexcept>>); static_assert(asl::same_as<int(float), asl::tame_t<int(float) && noexcept>>); static_assert(asl::same_as<int(float), asl::tame_t<int(float) const>>); static_assert(asl::is_func<void()>); static_assert(asl::is_func<void(int)>); static_assert(asl::is_func<void(int, float)>); static_assert(asl::is_func<void() &>); static_assert(asl::is_func<void() const &&>); static_assert(asl::is_func<void() volatile noexcept>); static_assert(!asl::is_func<void(*)()>); static_assert(!asl::is_func<int>); static_assert(!asl::is_func<int&>); static_assert(!asl::is_func<void>); static_assert(asl::is_object<Struct>); static_assert(asl::is_object<int>); static_assert(asl::is_object<int*>); static_assert(asl::is_object<int Struct::*>); static_assert(asl::is_object<int (Struct::*)(float)>); static_assert(asl::is_object<int[]>); static_assert(asl::is_object<int[45]>); static_assert(asl::is_object<Enum>); static_assert(!asl::is_object<int&>); static_assert(!asl::is_object<void>); static_assert(!asl::is_object<void(int)>); static_assert(!asl::is_object<int(float) const && noexcept>); static_assert(!asl::is_array<Struct>); static_assert(!asl::is_array<int>); static_assert(!asl::is_array<int*>); static_assert(!asl::is_array<int Struct::*>); static_assert(!asl::is_array<int (Struct::*)(float)>); static_assert(asl::is_array<int[]>); static_assert(asl::is_array<int[45]>); static_assert(!asl::is_array<Enum>); static_assert(!asl::is_array<int&>); static_assert(!asl::is_array<void>); static_assert(!asl::is_array<void(int)>); static_assert(!asl::is_array<int(float) const && noexcept>); static_assert(asl::same_as<int, asl::remove_extent_t<int>>); static_assert(asl::same_as<int, asl::remove_extent_t<int[]>>); static_assert(asl::same_as<int, asl::remove_extent_t<int[67]>>); static_assert(asl::same_as<int, asl::un_ref_t<int>>); static_assert(asl::same_as<int, asl::un_ref_t<int&>>); static_assert(asl::same_as<int, asl::un_ref_t<int&&>>); static_assert(asl::same_as<int() &, asl::un_ref_t<int() &>>); static_assert(asl::types_count<int, float> == 2); static_assert(asl::types_count<int, int> == 2); static_assert(asl::types_count<int> == 1); static_assert(asl::types_count<> == 0); class Base {}; class Derived : public Base {}; class C {}; class D { public: operator C() { return c; } C c; }; // NOLINT class E { public: template<class T> E(T&&) {} }; // NOLINT static_assert(asl::convertible_to<Derived*, Base*>); static_assert(!asl::convertible_to<Base*, Derived*>); static_assert(asl::convertible_to<D, C>); static_assert(!asl::convertible_to<Derived*, C*>); static_assert(asl::convertible_to<Base, E>); static_assert(!asl::convertible_to<int32_t(&)[], int16_t(&)[]>); static_assert(asl::convertible_to<int16_t(&)[], const int16_t(&)[]>); static_assert(asl::convertible_to<const int16_t(&)[], const int16_t(&)[]>); static_assert(asl::convertible_to<int16_t(&)[], int16_t(&)[]>); static_assert(!asl::convertible_to<int16_t(&)[], int32_t(&)[]>); static_assert(!asl::convertible_to<const int16_t(&)[], int16_t(&)[]>); static_assert(!asl::convertible_to<D(&)[], C(&)[]>); static_assert(asl::derived_from<Derived, Base>); static_assert(asl::derived_from<Derived, Derived>); static_assert(asl::derived_from<Base, Base>); static_assert(!asl::derived_from<Base, Derived>); static_assert(!asl::derived_from<D, C>); static_assert(!asl::derived_from<C, D>); static_assert(!asl::derived_from<uint8_t, uint16_t>); static_assert(!asl::derived_from<uint16_t, uint8_t>); static_assert(!asl::derived_from<int, int>); static_assert(asl::same_or_derived_from<Derived, Base>); static_assert(asl::same_or_derived_from<Derived, Derived>); static_assert(asl::same_or_derived_from<Base, Base>); static_assert(!asl::same_or_derived_from<Base, Derived>); static_assert(!asl::same_or_derived_from<D, C>); static_assert(!asl::same_or_derived_from<C, D>); static_assert(!asl::same_or_derived_from<uint8_t, uint16_t>); static_assert(!asl::same_or_derived_from<uint16_t, uint8_t>); static_assert(asl::same_or_derived_from<int, int>); static_assert(!asl::is_const<int>); static_assert(asl::is_const<const int>); 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_floating_point<float>); static_assert(asl::is_floating_point<const float>); static_assert(asl::is_floating_point<volatile double>); static_assert(!asl::is_floating_point<const float&>); static_assert(!asl::is_floating_point<int>); static_assert(!asl::is_floating_point<C>); static_assert(asl::uniquely_represented<int>); static_assert(asl::uniquely_represented<uint128_t>); static_assert(!asl::uniquely_represented<bool>); enum Enum1 {}; enum class Enum2 {}; static_assert(asl::uniquely_represented<Enum1>); static_assert(asl::uniquely_represented<Enum2>); static_assert(!asl::is_enum<int>); static_assert(asl::is_enum<Enum1>); static_assert(asl::is_enum<Enum2>); static_assert(asl::derefs_as<int, int>); static_assert(asl::derefs_as<int*, int>); static_assert(!asl::derefs_as<const int*, int>); static_assert(asl::derefs_as<int&, int>); static_assert(!asl::derefs_as<const int&, int>); static_assert(asl::derefs_as<asl::box<int>, int>); static_assert(asl::derefs_as<Derived, Base>); static_assert(!asl::derefs_as<Base, Derived>); static_assert(asl::derefs_as<Derived*, Base>); static_assert(asl::derefs_as<Derived&, Base>); static_assert(!asl::derefs_as<Base&, Derived>); static_assert(asl::derefs_as<asl::box<Derived>, Base>); static_assert(asl::derefs_as<asl::box<Derived>, Derived>); static_assert(asl::derefs_as<asl::box<Base>, Base>); static void wants_int(int) {} static void wants_base(const Base&) {} static void wants_base_ptr(Base*) {} ASL_TEST(deref) { int a = 4; auto b = asl::make_box<int>(5); wants_int(asl::deref<int>(5)); wants_int(asl::deref<int>(a)); wants_int(asl::deref<int>(&a)); wants_int(asl::deref<int>(b)); Derived c{}; auto d = asl::make_box<Derived>(); wants_base(asl::deref<Base>(Derived{})); wants_base(asl::deref<Base>(c)); wants_base(asl::deref<Base>(&c)); wants_base(asl::deref<Base>(d)); wants_base_ptr(&asl::deref<Base>(c)); wants_base_ptr(&asl::deref<Base>(&c)); wants_base_ptr(&asl::deref<Base>(d)); wants_base(asl::deref<Base>(std::move(d))); } static_assert(asl::same_as<asl::copy_cref_t<int, float>, float>); static_assert(asl::same_as<asl::copy_cref_t<int, const float>, float>); static_assert(asl::same_as<asl::copy_cref_t<int, float&&>, float>); static_assert(asl::same_as<asl::copy_cref_t<int, const float&>, float>); static_assert(asl::same_as<asl::copy_cref_t<int&&, float>, float&&>); static_assert(asl::same_as<asl::copy_cref_t<int&&, const float>, float&&>); static_assert(asl::same_as<asl::copy_cref_t<int&&, float&&>, float&&>); static_assert(asl::same_as<asl::copy_cref_t<int&&, const float&>, float&&>); static_assert(asl::same_as<asl::copy_cref_t<const int, float>, const float>); static_assert(asl::same_as<asl::copy_cref_t<const int, const float>, const float>); static_assert(asl::same_as<asl::copy_cref_t<const int, float&&>, const float>); static_assert(asl::same_as<asl::copy_cref_t<const int, const float&>, const float>); static_assert(asl::same_as<asl::copy_cref_t<const int&, float>, const float&>); static_assert(asl::same_as<asl::copy_cref_t<const int&, const float>, const float&>); static_assert(asl::same_as<asl::copy_cref_t<const int&, float&&>, const float&>); static_assert(asl::same_as<asl::copy_cref_t<const int&, const float&>, const float&>); static_assert(asl::same_as<asl::copy_const_t<int, float>, float>); static_assert(asl::same_as<asl::copy_const_t<int, const float>, float>); static_assert(asl::same_as<asl::copy_const_t<const int, float>, const float>); static_assert(asl::same_as<asl::copy_const_t<const int, const float>, const float>); static_assert(asl::same_as<asl::copy_const_t<const int*, float>, float>); static_assert(asl::same_as<asl::copy_const_t<int* const, float>, const float>); static_assert(asl::same_as<asl::decay_t<int>, int>); static_assert(!asl::same_as<asl::decay_t<int>, float>); static_assert(asl::same_as<asl::decay_t<int&>, int>); static_assert(asl::same_as<asl::decay_t<int&&>, int>); static_assert(asl::same_as<asl::decay_t<const int&>, int>); static_assert(asl::same_as<asl::decay_t<int[2]>, int*>); static_assert(!asl::same_as<asl::decay_t<int[4][2]>, int*>); static_assert(!asl::same_as<asl::decay_t<int[4][2]>, int**>); static_assert(asl::same_as<asl::decay_t<int[4][2]>, int(*)[2]>); static_assert(asl::same_as<asl::decay_t<int(int)>, int(*)(int)>); enum EnumU8 : uint8_t {}; enum EnumI64 : int64_t {}; static_assert(asl::same_as<asl::underlying_t<EnumU8>, uint8_t>); static_assert(asl::same_as<asl::underlying_t<EnumI64>, int64_t>);