From 2bac310e55df06a3e378c932afa2a4c2bc2123e7 Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Sat, 19 Apr 2025 17:57:53 -0400 Subject: [PATCH] silly variant --- CMakeLists.txt | 2 +- include/blt/std/variant.h | 287 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 include/blt/std/variant.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 98bc98e..4c4cd13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 5.3.7) +set(BLT_VERSION 5.3.8) set(BLT_TARGET BLT) diff --git a/include/blt/std/variant.h b/include/blt/std/variant.h new file mode 100644 index 0000000..4676c35 --- /dev/null +++ b/include/blt/std/variant.h @@ -0,0 +1,287 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_STD_VARIANT_H +#define BLT_STD_VARIANT_H + +#include +#include +#include + +namespace blt +{ + template + class variant_t + { + public: + using value_type = std::variant; + size_t variant_size = sizeof...(Types); + + constexpr variant_t(): m_variant() + { + } + + constexpr variant_t(const variant_t& variant) noexcept(std::is_nothrow_copy_constructible_v): m_variant(variant.m_variant) + { + } + + constexpr variant_t(variant_t&& variant) noexcept(std::is_nothrow_move_constructible_v): m_variant(std::move(variant.m_variant)) + { + } + + explicit constexpr variant_t(const value_type& variant) noexcept(std::is_nothrow_copy_constructible_v): m_variant(variant) + { + } + + explicit constexpr variant_t(value_type&& variant) noexcept(std::is_nothrow_move_constructible_v): m_variant(std::move(variant)) + { + } + + explicit constexpr variant_t(Types&&... args) noexcept(std::is_nothrow_constructible_v): m_variant( + std::forward(args)...) + { + } + + template + explicit constexpr variant_t(std::in_place_type_t, C_Args&&... args): m_variant(std::in_place_type, std::forward(args)...) + { + } + + template + constexpr explicit variant_t(std::in_place_type_t, std::initializer_list il, C_Args&&... args): m_variant( + std::in_place_type, il, std::forward(args)...) + { + } + + template + explicit constexpr variant_t(std::in_place_index_t, C_Args&&... args): m_variant(std::in_place_index, std::forward(args)...) + { + } + + template + constexpr explicit variant_t(std::in_place_index_t, std::initializer_list il, C_Args&&... args): m_variant( + std::in_place_index, il, std::forward(args)...) + { + } + + template + T& emplace(Args&&... args) + { + return m_variant.template emplace(std::forward(args)...); + } + + template + T& emplace(std::initializer_list il, Args&&... args) + { + return m_variant.template emplace(il, std::forward(args)...); + } + + template + std::variant_alternative_t& emplace(Args&&... args) + { + return m_variant.template emplace(std::forward(args)...); + } + + template + std::variant_alternative_t& emplace(std::initializer_list il, Args&&... args) + { + return m_variant.template emplace(il, std::forward(args)...); + } + + [[nodiscard]] constexpr std::size_t index() const noexcept + { + return m_variant.index(); + } + + [[nodiscard]] constexpr bool valueless_by_exception() const noexcept + { + return m_variant.valueless_by_exception(); + } + + template + constexpr auto visit(T&& visitor) -> decltype(auto) + { + return std::visit(std::forward(visitor), m_variant); + } + + template + [[nodiscard]] constexpr bool has_index() const noexcept + { + return m_variant.index() == I; + } + + template + [[nodiscard]] constexpr bool has_type() const noexcept + { + return std::holds_alternative(m_variant); + } + + template + [[nodiscard]] constexpr auto get() -> decltype(auto) + { + return std::get(m_variant); + } + + template + [[nodiscard]] constexpr auto get() const -> decltype(auto) + { + return std::get(m_variant); + } + + template + [[nodiscard]] constexpr auto get() -> decltype(auto) + { + return std::get(m_variant); + } + + template + [[nodiscard]] constexpr auto get() const -> decltype(auto) + { + return std::get(m_variant); + } + + template + constexpr std::add_pointer_t> get_if() noexcept + { + return std::get_if(m_variant); + } + + template + constexpr std::add_pointer_t> get_if() noexcept + { + return std::get_if(m_variant); + } + + template + constexpr std::add_pointer_t get_if() noexcept + { + return std::get_if(m_variant); + } + + template + constexpr std::add_pointer_t get_if() noexcept + { + return std::get_if(m_variant); + } + + template + constexpr T value_or(T&& t) const + { + if (has_type()) + return get(); + return std::forward(t); + } + + template + constexpr std::variant_alternative_t value_or(const std::variant_alternative_t& t) const + { + if (has_type>()) + return get(); + return t; + } + + template + constexpr std::variant_alternative_t value_or(std::variant_alternative_t&& t) const + { + if (has_type>()) + return get(); + return t; + } + + template + constexpr const value_type& variant() const + { + return m_variant; + } + + constexpr value_type& variant() + { + return m_variant; + } + + [[nodiscard]] constexpr size_t size() const + { + return variant_size; + } + + friend bool operator==(const variant_t& lhs, const variant_t& rhs) + { + return lhs.m_variant == rhs.m_variant; + } + + friend bool operator!=(const variant_t& lhs, const variant_t& rhs) + { + return lhs.m_variant != rhs.m_variant; + } + + friend bool operator<(const variant_t& lhs, const variant_t& rhs) + { + return lhs.m_variant < rhs.m_variant; + } + + friend bool operator>(const variant_t& lhs, const variant_t& rhs) + { + return lhs.m_variant > rhs.m_variant; + } + + friend bool operator<=(const variant_t& lhs, const variant_t& rhs) + { + return lhs.m_variant <= rhs.m_variant; + } + + friend bool operator>=(const variant_t& lhs, const variant_t& rhs) + { + return lhs.m_variant >= rhs.m_variant; + } + + private: + value_type m_variant; + }; + + namespace detail + { + template + class variant_is_base_of + {}; + + template + class variant_is_base_of> + { + public: + template + static constexpr bool value = std::conjunction_v...>; + }; + + template + class variant_is_base_of> + { + public: + template + static constexpr bool value = std::conjunction_v...>; + }; + + template + static constexpr bool variant_is_base_of_v = variant_is_base_of::value; + } + + template + class variant_wrapper_t : public Subclasses... + {}; +} + +#endif //BLT_STD_VARIANT_H