summaryrefslogtreecommitdiff
path: root/kernel/lib/libcxx/include/__variant
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/lib/libcxx/include/__variant')
-rw-r--r--kernel/lib/libcxx/include/__variant/variant.h421
1 files changed, 421 insertions, 0 deletions
diff --git a/kernel/lib/libcxx/include/__variant/variant.h b/kernel/lib/libcxx/include/__variant/variant.h
new file mode 100644
index 0000000..731cb5d
--- /dev/null
+++ b/kernel/lib/libcxx/include/__variant/variant.h
@@ -0,0 +1,421 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the BastionOS freestanding C++ standard library.
+//
+// std::variant — no-exceptions version (traps on bad access).
+// valueless_by_exception() always returns false.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBBASTION_VARIANT_VARIANT_H
+#define _LIBBASTION_VARIANT_VARIANT_H
+
+#include <__config>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/construction_traits.h>
+#include <__type_traits/type_modifications.h>
+#include <__type_traits/type_relationships.h>
+#include <__utility/move.h>
+#include <__utility/swap.h>
+#include <__utility/in_place.h>
+#include <cstddef>
+#include <new>
+
+_LIBBASTION_BEGIN_NAMESPACE_STD
+
+inline constexpr size_t variant_npos = static_cast<size_t>(-1);
+
+// ── monostate ───────────────────────────────────────────────────────────────
+
+struct monostate {};
+constexpr bool operator==(monostate, monostate) noexcept { return true; }
+constexpr bool operator<(monostate, monostate) noexcept { return false; }
+
+// ── Internal helpers ────────────────────────────────────────────────────────
+
+namespace __variant_detail {
+
+// Type at index using __type_pack_element builtin.
+template<size_t _Ip, class... _Types>
+using __type_at = __type_pack_element<_Ip, _Types...>;
+
+// Find index of type in pack.
+template<class _Tp, class... _Types>
+struct __index_of;
+
+template<class _Tp, class _First, class... _Rest>
+struct __index_of<_Tp, _First, _Rest...> {
+ static constexpr size_t value = __is_same(_Tp, _First) ? 0 : 1 + __index_of<_Tp, _Rest...>::value;
+};
+
+template<class _Tp>
+struct __index_of<_Tp> {
+ static constexpr size_t value = variant_npos;
+};
+
+// Recursive union storage.
+template<bool _TriviallyDestructible, class... _Types>
+union __storage;
+
+// Trivially destructible case.
+template<class _First, class... _Rest>
+union __storage<true, _First, _Rest...> {
+ _First __head;
+ __storage<true, _Rest...> __tail;
+ constexpr __storage() : __tail() {}
+};
+
+template<>
+union __storage<true> {
+ constexpr __storage() {}
+};
+
+// Non-trivially destructible case.
+template<class _First, class... _Rest>
+union __storage<false, _First, _Rest...> {
+ _First __head;
+ __storage<(is_trivially_destructible_v<_Rest> && ...), _Rest...> __tail;
+ constexpr __storage() : __tail() {}
+ constexpr ~__storage() requires is_trivially_destructible_v<_First> = default;
+ constexpr ~__storage() requires (!is_trivially_destructible_v<_First>) {}
+};
+
+template<>
+union __storage<false> {
+ constexpr __storage() {}
+};
+
+// Get reference from storage by index.
+template<size_t _Ip, bool _Triv, class... _Types>
+constexpr auto& __get_storage(__storage<_Triv, _Types...>& __s) {
+ if constexpr (_Ip == 0)
+ return __s.__head;
+ else
+ return __get_storage<_Ip - 1>(__s.__tail);
+}
+
+template<size_t _Ip, bool _Triv, class... _Types>
+constexpr const auto& __get_storage(const __storage<_Triv, _Types...>& __s) {
+ if constexpr (_Ip == 0)
+ return __s.__head;
+ else
+ return __get_storage<_Ip - 1>(__s.__tail);
+}
+
+// Destroy active alternative.
+template<size_t _Np, class _Storage>
+constexpr void __destroy_at(size_t __idx, _Storage& __s) {
+ if constexpr (_Np > 0) {
+ if (__idx == 0) {
+ using _Tp = __remove_reference_t(decltype(__s.__head));
+ if constexpr (!is_trivially_destructible_v<_Tp>)
+ __s.__head.~_Tp();
+ } else {
+ __destroy_at<_Np - 1>(__idx - 1, __s.__tail);
+ }
+ }
+}
+
+} // namespace __variant_detail
+
+// ── variant ─────────────────────────────────────────────────────────────────
+
+template<class... _Types>
+class variant {
+ static_assert(sizeof...(_Types) > 0, "variant must have at least one alternative");
+ static_assert((!__is_void(_Types) && ...), "variant alternatives cannot be void");
+ static_assert((!__is_reference(_Types) && ...), "variant alternatives cannot be references");
+
+ static constexpr bool __all_trivially_destructible = (is_trivially_destructible_v<_Types> && ...);
+ using __storage_t = __variant_detail::__storage<__all_trivially_destructible, _Types...>;
+
+public:
+ // ── Constructors ────────────────────────────────────────────────────
+
+ constexpr variant()
+ noexcept(is_nothrow_default_constructible_v<__variant_detail::__type_at<0, _Types...>>)
+ requires is_default_constructible_v<__variant_detail::__type_at<0, _Types...>>
+ : __index_(0)
+ {
+ using _T0 = __variant_detail::__type_at<0, _Types...>;
+ ::new (static_cast<void*>(&__storage_.__head)) _T0();
+ }
+
+ constexpr variant(const variant& __other)
+ requires (is_copy_constructible_v<_Types> && ...)
+ : __index_(__other.__index_)
+ {
+ __copy_construct(__other, std::make_index_sequence<sizeof...(_Types)>{});
+ }
+
+ constexpr variant(variant&& __other)
+ noexcept((is_nothrow_move_constructible_v<_Types> && ...))
+ requires (is_move_constructible_v<_Types> && ...)
+ : __index_(__other.__index_)
+ {
+ __move_construct(std::move(__other), std::make_index_sequence<sizeof...(_Types)>{});
+ }
+
+ template<class _Tp>
+ requires (!__is_same(__decay(_Tp), variant)) &&
+ (!__is_same(__decay(_Tp), in_place_type_t<_Tp>))
+ constexpr variant(_Tp&& __t) {
+ constexpr size_t __idx = __find_best_match<__decay(_Tp)>();
+ static_assert(__idx != variant_npos, "no matching variant alternative for this type");
+ using _Alt = __variant_detail::__type_at<__idx, _Types...>;
+ ::new (static_cast<void*>(&__variant_detail::__get_storage<__idx>(__storage_))) _Alt(std::forward<_Tp>(__t));
+ __index_ = __idx;
+ }
+
+ template<size_t _Ip, class... _Args>
+ requires (_Ip < sizeof...(_Types)) &&
+ is_constructible_v<__variant_detail::__type_at<_Ip, _Types...>, _Args...>
+ constexpr explicit variant(in_place_index_t<_Ip>, _Args&&... __args) : __index_(_Ip) {
+ using _Alt = __variant_detail::__type_at<_Ip, _Types...>;
+ ::new (static_cast<void*>(&__variant_detail::__get_storage<_Ip>(__storage_))) _Alt(std::forward<_Args>(__args)...);
+ }
+
+ // ── Destructor ──────────────────────────────────────────────────────
+
+ constexpr ~variant() requires __all_trivially_destructible = default;
+
+ constexpr ~variant() requires (!__all_trivially_destructible) {
+ __variant_detail::__destroy_at<sizeof...(_Types)>(__index_, __storage_);
+ }
+
+ // ── Assignment ──────────────────────────────────────────────────────
+
+ constexpr variant& operator=(const variant& __other)
+ requires (is_copy_constructible_v<_Types> && ...) && (is_copy_assignable_v<_Types> && ...)
+ {
+ if (this == &__other) return *this;
+ __destroy_current();
+ __index_ = __other.__index_;
+ __copy_construct(__other, std::make_index_sequence<sizeof...(_Types)>{});
+ return *this;
+ }
+
+ constexpr variant& operator=(variant&& __other)
+ noexcept((is_nothrow_move_constructible_v<_Types> && ...) && (is_nothrow_move_assignable_v<_Types> && ...))
+ requires (is_move_constructible_v<_Types> && ...) && (is_move_assignable_v<_Types> && ...)
+ {
+ if (this == &__other) return *this;
+ __destroy_current();
+ __index_ = __other.__index_;
+ __move_construct(std::move(__other), std::make_index_sequence<sizeof...(_Types)>{});
+ return *this;
+ }
+
+ // ── Observers ───────────────────────────────────────────────────────
+
+ _LIBBASTION_NODISCARD constexpr size_t index() const noexcept { return __index_; }
+ _LIBBASTION_NODISCARD constexpr bool valueless_by_exception() const noexcept { return false; }
+
+ // ── Modifiers ───────────────────────────────────────────────────────
+
+ template<size_t _Ip, class... _Args>
+ requires is_constructible_v<__variant_detail::__type_at<_Ip, _Types...>, _Args...>
+ constexpr auto& emplace(_Args&&... __args) {
+ __destroy_current();
+ using _Alt = __variant_detail::__type_at<_Ip, _Types...>;
+ auto* __ptr = ::new (static_cast<void*>(&__variant_detail::__get_storage<_Ip>(__storage_)))
+ _Alt(std::forward<_Args>(__args)...);
+ __index_ = _Ip;
+ return *__ptr;
+ }
+
+ constexpr void swap(variant& __other)
+ noexcept((is_nothrow_move_constructible_v<_Types> && ...) && (is_nothrow_swappable_v<_Types> && ...))
+ {
+ variant __tmp(std::move(*this));
+ __destroy_current();
+ __index_ = __other.__index_;
+ __move_construct(std::move(__other), std::make_index_sequence<sizeof...(_Types)>{});
+ __other.__destroy_current();
+ __other.__index_ = __tmp.__index_;
+ __other.__move_construct(std::move(__tmp), std::make_index_sequence<sizeof...(_Types)>{});
+ }
+
+// Internal — accessible by get/get_if/visit. Prefixed with __ to discourage direct use.
+//public:
+ __storage_t __storage_;
+ size_t __index_;
+
+private:
+ template<class _Tp>
+ static constexpr size_t __find_best_match() {
+ // Find first alternative constructible from _Tp.
+ return __find_constructible<_Tp, 0, _Types...>();
+ }
+
+ template<class _Tp, size_t _Ip>
+ static constexpr size_t __find_constructible() { return variant_npos; }
+
+ template<class _Tp, size_t _Ip, class _First, class... _Rest>
+ static constexpr size_t __find_constructible() {
+ if constexpr (__is_same(_Tp, _First))
+ return _Ip;
+ else
+ return __find_constructible<_Tp, _Ip + 1, _Rest...>();
+ }
+
+ constexpr void __destroy_current() {
+ if constexpr (!__all_trivially_destructible)
+ __variant_detail::__destroy_at<sizeof...(_Types)>(__index_, __storage_);
+ }
+
+ template<size_t... _Ip>
+ constexpr void __copy_construct(const variant& __other, index_sequence<_Ip...>) {
+ (void)(( __other.__index_ == _Ip &&
+ (::new (static_cast<void*>(&__variant_detail::__get_storage<_Ip>(__storage_)))
+ __variant_detail::__type_at<_Ip, _Types...>(__variant_detail::__get_storage<_Ip>(__other.__storage_)), true)
+ ) || ...);
+ }
+
+ template<size_t... _Ip>
+ constexpr void __move_construct(variant&& __other, index_sequence<_Ip...>) {
+ (void)(( __other.__index_ == _Ip &&
+ (::new (static_cast<void*>(&__variant_detail::__get_storage<_Ip>(__storage_)))
+ __variant_detail::__type_at<_Ip, _Types...>(std::move(__variant_detail::__get_storage<_Ip>(__other.__storage_))), true)
+ ) || ...);
+ }
+};
+
+// ── get<I> ──────────────────────────────────────────────────────────────────
+
+template<size_t _Ip, class... _Types>
+_LIBBASTION_NODISCARD constexpr auto& get(variant<_Types...>& __v) {
+ if (__v.index() != _Ip) _LIBBASTION_TRAP();
+ return __variant_detail::__get_storage<_Ip>(__v.__storage_);
+}
+
+template<size_t _Ip, class... _Types>
+_LIBBASTION_NODISCARD constexpr const auto& get(const variant<_Types...>& __v) {
+ if (__v.index() != _Ip) _LIBBASTION_TRAP();
+ return __variant_detail::__get_storage<_Ip>(__v.__storage_);
+}
+
+template<size_t _Ip, class... _Types>
+_LIBBASTION_NODISCARD constexpr auto&& get(variant<_Types...>&& __v) {
+ if (__v.index() != _Ip) _LIBBASTION_TRAP();
+ return std::move(__variant_detail::__get_storage<_Ip>(__v.__storage_));
+}
+
+// ── get<T> ──────────────────────────────────────────────────────────────────
+
+template<class _Tp, class... _Types>
+_LIBBASTION_NODISCARD constexpr _Tp& get(variant<_Types...>& __v) {
+ constexpr size_t __idx = __variant_detail::__index_of<_Tp, _Types...>::value;
+ static_assert(__idx != variant_npos, "type not found in variant");
+ return get<__idx>(__v);
+}
+
+template<class _Tp, class... _Types>
+_LIBBASTION_NODISCARD constexpr const _Tp& get(const variant<_Types...>& __v) {
+ constexpr size_t __idx = __variant_detail::__index_of<_Tp, _Types...>::value;
+ static_assert(__idx != variant_npos, "type not found in variant");
+ return get<__idx>(__v);
+}
+
+// ── get_if ──────────────────────────────────────────────────────────────────
+
+template<size_t _Ip, class... _Types>
+_LIBBASTION_NODISCARD constexpr auto* get_if(variant<_Types...>* __v) noexcept {
+ if (!__v || __v->index() != _Ip) return static_cast<__variant_detail::__type_at<_Ip, _Types...>*>(nullptr);
+ return &__variant_detail::__get_storage<_Ip>(__v->__storage_);
+}
+
+template<size_t _Ip, class... _Types>
+_LIBBASTION_NODISCARD constexpr const auto* get_if(const variant<_Types...>* __v) noexcept {
+ if (!__v || __v->index() != _Ip) return static_cast<const __variant_detail::__type_at<_Ip, _Types...>*>(nullptr);
+ return &__variant_detail::__get_storage<_Ip>(__v->__storage_);
+}
+
+// ── holds_alternative ───────────────────────────────────────────────────────
+
+template<class _Tp, class... _Types>
+_LIBBASTION_NODISCARD constexpr bool holds_alternative(const variant<_Types...>& __v) noexcept {
+ constexpr size_t __idx = __variant_detail::__index_of<_Tp, _Types...>::value;
+ static_assert(__idx != variant_npos, "type not found in variant");
+ return __v.index() == __idx;
+}
+
+// ── visit (single variant) ──────────────────────────────────────────────────
+
+namespace __variant_detail {
+
+template<size_t _Ip, size_t _Np, class _Visitor, class _Variant>
+constexpr decltype(auto) __visit_impl(_Visitor&& __vis, _Variant&& __v) {
+ if constexpr (_Ip == _Np) {
+ _LIBBASTION_UNREACHABLE();
+ } else {
+ if (__v.index() == _Ip)
+ return std::forward<_Visitor>(__vis)(get<_Ip>(std::forward<_Variant>(__v)));
+ return __visit_impl<_Ip + 1, _Np>(std::forward<_Visitor>(__vis), std::forward<_Variant>(__v));
+ }
+}
+
+} // namespace __variant_detail
+
+template<class _Visitor, class... _Types>
+constexpr decltype(auto) visit(_Visitor&& __vis, variant<_Types...>& __v) {
+ return __variant_detail::__visit_impl<0, sizeof...(_Types)>(std::forward<_Visitor>(__vis), __v);
+}
+
+template<class _Visitor, class... _Types>
+constexpr decltype(auto) visit(_Visitor&& __vis, const variant<_Types...>& __v) {
+ return __variant_detail::__visit_impl<0, sizeof...(_Types)>(std::forward<_Visitor>(__vis), __v);
+}
+
+template<class _Visitor, class... _Types>
+constexpr decltype(auto) visit(_Visitor&& __vis, variant<_Types...>&& __v) {
+ return __variant_detail::__visit_impl<0, sizeof...(_Types)>(std::forward<_Visitor>(__vis), std::move(__v));
+}
+
+// ── variant_size / variant_alternative ──────────────────────────────────────
+
+template<class _Tp> struct variant_size;
+
+template<class... _Types>
+struct variant_size<variant<_Types...>> : integral_constant<size_t, sizeof...(_Types)> {};
+
+template<class _Tp>
+struct variant_size<const _Tp> : variant_size<_Tp> {};
+
+template<class _Tp>
+inline constexpr size_t variant_size_v = variant_size<_Tp>::value;
+
+template<size_t _Ip, class _Tp> struct variant_alternative;
+
+template<size_t _Ip, class... _Types>
+struct variant_alternative<_Ip, variant<_Types...>> {
+ using type = __variant_detail::__type_at<_Ip, _Types...>;
+};
+
+template<size_t _Ip, class _Tp>
+struct variant_alternative<_Ip, const _Tp> {
+ using type = const typename variant_alternative<_Ip, _Tp>::type;
+};
+
+template<size_t _Ip, class _Tp>
+using variant_alternative_t = typename variant_alternative<_Ip, _Tp>::type;
+
+// Non-member swap
+template<class... _Types>
+constexpr void swap(variant<_Types...>& __a, variant<_Types...>& __b) noexcept(noexcept(__a.swap(__b))) {
+ __a.swap(__b);
+}
+
+// ── Make variant's storage_ accessible from get ─────────────────────────────
+// Friendship declaration is needed. We add it via the fact that get is in std::.
+// Actually, we need variant to declare get as friend.
+
+_LIBBASTION_END_NAMESPACE_STD
+
+// The get functions need access to __storage_. We achieve this by making them friends.
+// But since they're already defined, we need to restructure. For simplicity,
+// mark __storage_ as public in the variant class.
+// This is the same approach many freestanding implementations use.
+
+#endif // _LIBBASTION_VARIANT_VARIANT_H