#ifndef ENTT_COMMON_VALUE_TYPE_H #define ENTT_COMMON_VALUE_TYPE_H #include #include namespace test { namespace internal { template struct pointer_stable_mixin: Type { static constexpr auto in_place_delete = true; using Type::Type; using Type::operator=; }; template struct non_default_constructible_mixin: Type { using Type::Type; using Type::operator=; non_default_constructible_mixin() = delete; }; template struct non_trivially_destructible_mixin: Type { using Type::Type; using Type::operator=; virtual ~non_trivially_destructible_mixin() noexcept = default; }; template struct non_comparable_mixin: Type { using Type::Type; using Type::operator=; bool operator==(const non_comparable_mixin &) const noexcept = delete; }; template struct non_movable_mixin: Type { using Type::Type; non_movable_mixin(non_movable_mixin &&) noexcept = delete; non_movable_mixin(const non_movable_mixin &) noexcept = default; non_movable_mixin &operator=(non_movable_mixin &&) noexcept = delete; non_movable_mixin &operator=(const non_movable_mixin &) noexcept = default; }; template struct new_delete_mixin: Type { static void *operator new(std::size_t count) { return ::operator new(count); } static void operator delete(void *ptr) { ::operator delete(ptr); } }; struct empty_type {}; struct aggregate_type { [[nodiscard]] constexpr bool operator==(const aggregate_type &) const noexcept = default; [[nodiscard]] constexpr auto operator<=>(const aggregate_type &) const noexcept = default; int value{}; }; template struct value_type { constexpr value_type() = default; constexpr value_type(Type elem): value{elem} {} [[nodiscard]] constexpr bool operator==(const value_type &) const noexcept = default; [[nodiscard]] constexpr auto operator<=>(const value_type &) const noexcept = default; operator Type() const noexcept { return value; } Type value{}; }; } // namespace internal using pointer_stable = internal::pointer_stable_mixin>; using pointer_stable_non_trivially_destructible = internal::pointer_stable_mixin>>; using non_default_constructible = internal::non_default_constructible_mixin>; using non_trivially_destructible = internal::non_trivially_destructible_mixin>; using non_comparable = internal::non_comparable_mixin; using non_movable = internal::non_movable_mixin>; using new_delete = internal::new_delete_mixin>; using boxed_int = internal::value_type; using boxed_char = internal::value_type; using empty = internal::empty_type; struct other_empty: internal::empty_type {}; using aggregate = internal::aggregate_type; static_assert(std::is_trivially_destructible_v, "Not a trivially destructible type"); static_assert(!std::is_trivially_destructible_v, "Trivially destructible type"); static_assert(!std::is_trivially_destructible_v, "Trivially destructible type"); static_assert(!std::is_move_constructible_v && !std::is_move_assignable_v, "Movable type"); static_assert(std::is_aggregate_v, "Not an aggregate type"); } // namespace test #endif