diff --git a/TODO.md b/TODO.md index c002f02..a7dfaf4 100644 --- a/TODO.md +++ b/TODO.md @@ -5,6 +5,8 @@ - add meta exception class; - add conversion of nullptr to any pointers; - add conversion of any pointers to void pointer ( identically cv-qualified ); +- void value? +- all string to hash? * argument names * argument defaults diff --git a/headers/meta.hpp/meta_base.hpp b/headers/meta.hpp/meta_base.hpp index 1ae7f8f..7c6f43c 100644 --- a/headers/meta.hpp/meta_base.hpp +++ b/headers/meta.hpp/meta_base.hpp @@ -182,3 +182,50 @@ namespace meta_hpp using scope_map = std::map>; using variable_map = std::map>; } + +namespace meta_hpp::detail::stdex +{ + template < typename T > + [[nodiscard]] constexpr std::underlying_type_t to_underlying(T v) noexcept { + return static_cast>(v); + } +} + +namespace meta_hpp::detail::stdex +{ + template < typename T, typename U > + concept same_as = + std::is_same_v && + std::is_same_v; + + template < typename Derived, typename Base > + concept derived_from = + std::is_base_of_v && + std::is_convertible_v; + + template < typename From, typename To > + concept convertible_to = + std::is_convertible_v && + requires { static_cast(std::declval()); }; + + template < typename T > + concept destructible = + std::is_nothrow_destructible_v; + + template < typename T, typename... Args > + concept constructible_from = + destructible && + std::is_constructible_v; + + template < typename T > + concept move_constructible = + constructible_from && + convertible_to; + + template + concept copy_constructible = + move_constructible && + constructible_from && convertible_to && + constructible_from && convertible_to && + constructible_from && convertible_to; +} diff --git a/headers/meta.hpp/meta_registry/class_bind.hpp b/headers/meta.hpp/meta_registry/class_bind.hpp index 36ba7cc..81dce45 100644 --- a/headers/meta.hpp/meta_registry/class_bind.hpp +++ b/headers/meta.hpp/meta_registry/class_bind.hpp @@ -23,7 +23,7 @@ namespace meta_hpp template < detail::class_kind Class > template < typename... Args > class_bind& class_bind::ctor_() { - static_assert(detail::constructible_from); + static_assert(detail::stdex::constructible_from); auto ctor_state = detail::ctor_state::make(); data_->ctors.emplace(ctor_state->index, std::move(ctor_state)); return *this; @@ -32,7 +32,7 @@ namespace meta_hpp template < detail::class_kind Class > template < detail::class_kind Base > class_bind& class_bind::base_() { - static_assert(detail::derived_from); + static_assert(detail::stdex::derived_from); data_->bases.emplace(resolve_type()); data_->bases_info.emplace(resolve_type(), detail::class_type_data::base_info{ .upcast = +[](void* derived) -> void* { diff --git a/headers/meta.hpp/meta_states/evalue.hpp b/headers/meta.hpp/meta_states/evalue.hpp index af2b6bd..df4328d 100644 --- a/headers/meta.hpp/meta_states/evalue.hpp +++ b/headers/meta.hpp/meta_states/evalue.hpp @@ -17,7 +17,7 @@ namespace meta_hpp::detail evalue_state::evalue_state(evalue_index index, Enum value) : index{std::move(index)} , enum_value{value} - , underlying_value{to_underlying(value)} {} + , underlying_value{stdex::to_underlying(value)} {} template < enum_kind Enum > evalue_state_ptr evalue_state::make(std::string name, Enum value) { diff --git a/headers/meta.hpp/meta_utilities.hpp b/headers/meta.hpp/meta_utilities.hpp index 8cf7683..8d4eac5 100644 --- a/headers/meta.hpp/meta_utilities.hpp +++ b/headers/meta.hpp/meta_utilities.hpp @@ -34,36 +34,6 @@ namespace meta_hpp::detail using copy_cvref_t = typename cvref_traits::template copy_to; } -namespace meta_hpp::detail -{ - template < typename T > - concept destructible = - std::is_nothrow_destructible_v; - - template < typename T, typename... Args > - concept constructible_from = - destructible && - std::is_constructible_v; - - template < typename Derived, typename Base > - concept derived_from = - std::is_base_of_v && - std::is_convertible_v; - - template < typename From, typename To > - concept convertible_to = - std::is_convertible_v && - requires { static_cast(std::declval()); }; -} - -namespace meta_hpp::detail -{ - template < typename T > - [[nodiscard]] constexpr std::underlying_type_t to_underlying(T v) noexcept { - return static_cast>(v); - } -} - namespace meta_hpp::detail { template < typename T > @@ -114,34 +84,6 @@ namespace meta_hpp::detail (std::is_rvalue_reference_v && std::is_class_v>); } -namespace meta_hpp::detail -{ - template < typename T > - concept has_deref_op_kind = requires(const T& v) { - { *v } -> convertible_to>; - }; - - template < typename T > - concept has_less_op_kind = requires(const T& v) { - { v < v } -> convertible_to; - }; - - template < typename T > - concept has_equals_op_kind = requires(const T& v) { - { v == v } -> convertible_to; - }; - - template < typename T > - concept has_istream_op_kind = requires(std::istream& is, T& v) { - { is >> v } -> convertible_to; - }; - - template < typename T > - concept has_ostream_op_kind = requires(std::ostream& os, const T& v) { - { os << v } -> convertible_to; - }; -} - namespace meta_hpp::detail { class noncopyable { @@ -187,9 +129,8 @@ namespace meta_hpp [[nodiscard]] const void* data() const noexcept; [[nodiscard]] const void* cdata() const noexcept; - [[nodiscard]] value deref(); - [[nodiscard]] value deref() const; - [[nodiscard]] value cderef() const; + [[nodiscard]] value operator*() const; + [[nodiscard]] value operator[](std::size_t index) const; template < typename T, typename Tp = std::decay_t > [[nodiscard]] Tp& cast() &; diff --git a/headers/meta.hpp/meta_utilities/value.hpp b/headers/meta.hpp/meta_utilities/value.hpp index 3e64be2..24c6e82 100644 --- a/headers/meta.hpp/meta_utilities/value.hpp +++ b/headers/meta.hpp/meta_utilities/value.hpp @@ -9,6 +9,13 @@ #include "../meta_base.hpp" #include "../meta_utilities.hpp" +#include "value_traits/deref_traits.hpp" +#include "value_traits/equals_traits.hpp" +#include "value_traits/index_traits.hpp" +#include "value_traits/istream_traits.hpp" +#include "value_traits/less_traits.hpp" +#include "value_traits/ostream_traits.hpp" + namespace meta_hpp { struct value::traits final { @@ -17,8 +24,8 @@ namespace meta_hpp void* (*const data)(value&) noexcept; const void* (*const cdata)(const value&) noexcept; - value (*const deref)(value&); - value (*const cderef)(const value&); + value (*const deref)(const value&); + value (*const index)(const value&, std::size_t); bool (*const less)(const value&, const value&); bool (*const equals)(const value&, const value&); @@ -48,35 +55,35 @@ namespace meta_hpp return v.try_cast(); }, - .deref = +[]([[maybe_unused]] value& v) -> value { - if constexpr ( detail::has_deref_op_kind ) { + .deref = +[]([[maybe_unused]] const value& v) -> value { + if constexpr ( detail::has_value_deref_traits ) { return value{*v.cast()}; } else { - throw std::logic_error("value type doesn't have deref operator"); + throw std::logic_error("value type doesn't have value deref traits"); } }, - .cderef = +[]([[maybe_unused]] const value& v) -> value { - if constexpr ( detail::has_deref_op_kind ) { - return value{*v.cast()}; + .index = +[]([[maybe_unused]] const value& v, [[maybe_unused]] std::size_t index) -> value { + if constexpr ( detail::has_value_index_traits ) { + return detail::value_index_traits{}(v.cast(), index); } else { - throw std::logic_error("value type doesn't have deref operator"); + throw std::logic_error("value type doesn't have value index traits"); } }, .less = +[]([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) -> bool { - if constexpr ( detail::has_less_op_kind ) { - return l.cast() < r.cast(); + if constexpr ( detail::has_value_less_traits ) { + return detail::value_less_traits{}(l.cast(), r.cast()); } else { - throw std::logic_error("value type doesn't have less operator"); + throw std::logic_error("value type doesn't have value less traits"); } }, .equals = +[]([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) -> bool { - if constexpr ( detail::has_equals_op_kind ) { - return l.cast() == r.cast(); + if constexpr ( detail::has_value_equals_traits ) { + return detail::value_equals_traits{}(l.cast(), r.cast()); } else { - throw std::logic_error("value type doesn't have equality operator"); + throw std::logic_error("value type doesn't have value equals traits"); } }, @@ -97,18 +104,18 @@ namespace meta_hpp }, .istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] value& v) -> std::istream& { - if constexpr ( detail::has_istream_op_kind ) { - return is >> v.cast(); + if constexpr ( detail::has_value_istream_traits ) { + return detail::value_istream_traits{}(is, v.cast()); } else { - throw std::logic_error("value type doesn't have istream operator"); + throw std::logic_error("value type doesn't have value istream traits"); } }, .ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const value& v) -> std::ostream& { - if constexpr ( detail::has_ostream_op_kind ) { - return os << v.cast(); + if constexpr ( detail::has_value_ostream_traits ) { + return detail::value_ostream_traits{}(os, v.cast()); } else { - throw std::logic_error("value type doesn't have ostream operator"); + throw std::logic_error("value type doesn't have value ostream traits"); } }, }; @@ -181,16 +188,12 @@ namespace meta_hpp return traits_->cdata(*this); } - inline value value::deref() { + inline value value::operator*() const { return traits_->deref(*this); } - inline value value::deref() const { - return traits_->cderef(*this); - } - - inline value value::cderef() const { - return traits_->cderef(*this); + inline value value::operator[](std::size_t index) const { + return traits_->index(*this, index); } template < typename T, typename Tp > diff --git a/headers/meta.hpp/meta_utilities/value_traits/deref_traits.hpp b/headers/meta.hpp/meta_utilities/value_traits/deref_traits.hpp new file mode 100644 index 0000000..6ac5ad0 --- /dev/null +++ b/headers/meta.hpp/meta_utilities/value_traits/deref_traits.hpp @@ -0,0 +1,52 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "../../meta_base.hpp" +#include "../../meta_utilities.hpp" + +namespace meta_hpp::detail +{ + template < typename T > + struct value_deref_traits; + + template < typename T > + concept has_value_deref_traits = requires(const T& v) { + { value_deref_traits{}(v) } -> stdex::convertible_to; + }; +} + +namespace meta_hpp::detail +{ + template < stdex::copy_constructible T > + struct value_deref_traits { + value operator()(T* v) const { + return value{*v}; + } + }; + + template < stdex::copy_constructible T > + struct value_deref_traits { + value operator()(const T* v) const { + return value{*v}; + } + }; + + template < stdex::copy_constructible T > + struct value_deref_traits> { + value operator()(const std::shared_ptr& v) const { + return value{*v}; + } + }; + + template < stdex::copy_constructible T > + struct value_deref_traits> { + value operator()(const std::unique_ptr& v) const { + return value{*v}; + } + }; +} diff --git a/headers/meta.hpp/meta_utilities/value_traits/equals_traits.hpp b/headers/meta.hpp/meta_utilities/value_traits/equals_traits.hpp new file mode 100644 index 0000000..6441c16 --- /dev/null +++ b/headers/meta.hpp/meta_utilities/value_traits/equals_traits.hpp @@ -0,0 +1,33 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "../../meta_base.hpp" + +namespace meta_hpp::detail +{ + template < typename T > + struct value_equals_traits; + + template < typename T > + concept has_value_equals_traits = requires(const T& v) { + { value_equals_traits{}(v, v) } -> stdex::convertible_to; + }; +} + +namespace meta_hpp::detail +{ + template < typename T > + requires requires(const T& v) { + { v == v } -> stdex::convertible_to; + } + struct value_equals_traits { + bool operator()(const T& l, const T& r) const { + return l == r; + } + }; +} diff --git a/headers/meta.hpp/meta_utilities/value_traits/index_traits.hpp b/headers/meta.hpp/meta_utilities/value_traits/index_traits.hpp new file mode 100644 index 0000000..2382f84 --- /dev/null +++ b/headers/meta.hpp/meta_utilities/value_traits/index_traits.hpp @@ -0,0 +1,66 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "../../meta_base.hpp" +#include "../../meta_utilities.hpp" + +namespace meta_hpp::detail +{ + template < typename T > + struct value_index_traits; + + template < typename T > + concept has_value_index_traits = requires(const T& v, std::size_t i) { + { value_index_traits{}(v, i) } -> stdex::convertible_to; + }; +} + +namespace meta_hpp::detail +{ + template < stdex::copy_constructible T > + struct value_index_traits { + value operator()(T* v, std::size_t i) const { + return value{*(v + i)}; + } + }; + + template < stdex::copy_constructible T > + struct value_index_traits { + value operator()(const T* v, std::size_t i) const { + return value{*(v + i)}; + } + }; + + template < stdex::copy_constructible T, std::size_t Size > + struct value_index_traits> { + value operator()(const std::array& v, std::size_t i) const { + return value{v[i]}; + } + }; + + template < stdex::copy_constructible T, std::size_t Extent > + struct value_index_traits> { + value operator()(const std::span& v, std::size_t i) const { + return value{v[i]}; + } + }; + + template < stdex::copy_constructible T, typename Traits, typename Allocator > + struct value_index_traits> { + value operator()(const std::basic_string& v, std::size_t i) const { + return value{v[i]}; + } + }; + + template < stdex::copy_constructible T, typename Allocator > + struct value_index_traits> { + value operator()(const std::vector& v, std::size_t i) { + return value{v[i]}; + } + }; +} diff --git a/headers/meta.hpp/meta_utilities/value_traits/istream_traits.hpp b/headers/meta.hpp/meta_utilities/value_traits/istream_traits.hpp new file mode 100644 index 0000000..8bb1fe9 --- /dev/null +++ b/headers/meta.hpp/meta_utilities/value_traits/istream_traits.hpp @@ -0,0 +1,33 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "../../meta_base.hpp" + +namespace meta_hpp::detail +{ + template < typename T > + struct value_istream_traits; + + template < typename T > + concept has_value_istream_traits = requires(std::istream& is, T& v) { + { value_istream_traits{}(is, v) } -> stdex::convertible_to; + }; +} + +namespace meta_hpp::detail +{ + template < typename T > + requires requires(std::istream& is, T& v) { + { is >> v } -> stdex::convertible_to; + } + struct value_istream_traits { + std::istream& operator()(std::istream& is, T& v) const { + return is >> v; + } + }; +} diff --git a/headers/meta.hpp/meta_utilities/value_traits/less_traits.hpp b/headers/meta.hpp/meta_utilities/value_traits/less_traits.hpp new file mode 100644 index 0000000..ca2498b --- /dev/null +++ b/headers/meta.hpp/meta_utilities/value_traits/less_traits.hpp @@ -0,0 +1,33 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "../../meta_base.hpp" + +namespace meta_hpp::detail +{ + template < typename T > + struct value_less_traits; + + template < typename T > + concept has_value_less_traits = requires(const T& v) { + { value_less_traits{}(v, v) } -> stdex::convertible_to; + }; +} + +namespace meta_hpp::detail +{ + template < typename T > + requires requires(const T& v) { + { v < v } -> stdex::convertible_to; + } + struct value_less_traits { + bool operator()(const T& l, const T& r) const { + return l < r; + } + }; +} diff --git a/headers/meta.hpp/meta_utilities/value_traits/ostream_traits.hpp b/headers/meta.hpp/meta_utilities/value_traits/ostream_traits.hpp new file mode 100644 index 0000000..e2f5ed9 --- /dev/null +++ b/headers/meta.hpp/meta_utilities/value_traits/ostream_traits.hpp @@ -0,0 +1,33 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "../../meta_base.hpp" + +namespace meta_hpp::detail +{ + template < typename T > + struct value_ostream_traits; + + template < typename T > + concept has_value_ostream_traits = requires(std::ostream& is, const T& v) { + { value_ostream_traits{}(is, v) } -> stdex::convertible_to; + }; +} + +namespace meta_hpp::detail +{ + template < typename T > + requires requires(std::ostream& os, const T& v) { + { os << v } -> stdex::convertible_to; + } + struct value_ostream_traits { + std::ostream& operator()(std::ostream& is, const T& v) const { + return is << v; + } + }; +} diff --git a/manuals/meta_examples/references_example.cpp b/manuals/meta_examples/references_example.cpp deleted file mode 100644 index 1fef687..0000000 --- a/manuals/meta_examples/references_example.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/meta.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include "../meta_manuals.hpp" - -namespace -{ -} - -TEST_CASE("meta/meta_examples/references") { - namespace meta = meta_hpp; -} diff --git a/manuals/meta_examples/pointers_example.cpp b/manuals/meta_examples/values_example.cpp similarity index 91% rename from manuals/meta_examples/pointers_example.cpp rename to manuals/meta_examples/values_example.cpp index 5729a42..c0940df 100644 --- a/manuals/meta_examples/pointers_example.cpp +++ b/manuals/meta_examples/values_example.cpp @@ -10,6 +10,6 @@ namespace { } -TEST_CASE("meta/meta_examples/pointers") { +TEST_CASE("meta/meta_examples/values") { namespace meta = meta_hpp; } diff --git a/untests/meta_states/evalue_tests.cpp b/untests/meta_states/evalue_tests.cpp index 93406af..ea3e1c6 100644 --- a/untests/meta_states/evalue_tests.cpp +++ b/untests/meta_states/evalue_tests.cpp @@ -56,7 +56,7 @@ TEST_CASE("meta/meta_states/evalue") { CHECK(evalue.get_value() == color::green); CHECK(evalue.get_value().get_type() == color_type); - CHECK(evalue.get_underlying_value() == meta::detail::to_underlying(color::green)); + CHECK(evalue.get_underlying_value() == meta::detail::stdex::to_underlying(color::green)); CHECK(evalue.get_underlying_value().get_type() == color_type.get_underlying_type()); } } diff --git a/untests/meta_types/enum_type_tests.cpp b/untests/meta_types/enum_type_tests.cpp index 139703f..b18cd0b 100644 --- a/untests/meta_types/enum_type_tests.cpp +++ b/untests/meta_types/enum_type_tests.cpp @@ -90,7 +90,7 @@ TEST_CASE("meta/meta_types/enum_type") { const meta::evalue green_value = color_type.get_evalue("green"); REQUIRE(green_value); CHECK(green_value.get_value() == color::green); - CHECK(green_value.get_underlying_value() == meta::detail::to_underlying(color::green)); + CHECK(green_value.get_underlying_value() == meta::detail::stdex::to_underlying(color::green)); } { @@ -107,7 +107,7 @@ TEST_CASE("meta/meta_types/enum_type") { const meta::evalue green_value = ecolor_type.get_evalue("green"); REQUIRE(green_value); CHECK(green_value.get_value() == ecolor_green); - CHECK(green_value.get_underlying_value() == meta::detail::to_underlying(ecolor_green)); + CHECK(green_value.get_underlying_value() == meta::detail::stdex::to_underlying(ecolor_green)); } { diff --git a/untests/meta_utilities/value_tests.cpp b/untests/meta_utilities/value_tests.cpp index 46838c3..7a3199b 100644 --- a/untests/meta_utilities/value_tests.cpp +++ b/untests/meta_utilities/value_tests.cpp @@ -354,20 +354,20 @@ TEST_CASE("meta/meta_utilities/value") { SUBCASE("deref") { { int i{42}; - const meta::value v{meta::value{&i}.deref()}; + const meta::value v{*meta::value{&i}}; CHECK(v.get_type() == meta::resolve_type()); CHECK(v.data() != &i); } { const char i{42}; - const meta::value v{meta::value{&i}.deref()}; + const meta::value v{*meta::value{&i}}; CHECK(v.get_type() == meta::resolve_type()); CHECK(v.data() != &i); } { const int i{42}; const int* const pi = &i; - const meta::value v{meta::value{&pi}.deref()}; + const meta::value v{*meta::value{&pi}}; CHECK(v.get_type() == meta::resolve_type() ); CHECK(v.cast() == pi); } @@ -379,10 +379,10 @@ TEST_CASE("meta/meta_utilities/value") { void* const& p3 = &i; const void* const& p4 = &i; - CHECK_THROWS(std::ignore = meta::value(p1).deref()); - CHECK_THROWS(std::ignore = meta::value(p2).deref()); - CHECK_THROWS(std::ignore = meta::value(p3).deref()); - CHECK_THROWS(std::ignore = meta::value(p4).deref()); + CHECK_THROWS(std::ignore = *meta::value(p1)); + CHECK_THROWS(std::ignore = *meta::value(p2)); + CHECK_THROWS(std::ignore = *meta::value(p3)); + CHECK_THROWS(std::ignore = *meta::value(p4)); } { ivec2 v{1,2}; @@ -390,18 +390,77 @@ TEST_CASE("meta/meta_utilities/value") { CHECK(ivec2::move_ctor_counter == 0); CHECK(ivec2::copy_ctor_counter == 0); - meta::value vv1{vp.deref()}; + meta::value vv1{*vp}; CHECK(ivec2::move_ctor_counter == 0); CHECK(ivec2::copy_ctor_counter == 1); - meta::value vv2{std::move(vp).deref()}; + meta::value vv2{*std::move(vp)}; CHECK(ivec2::move_ctor_counter == 0); CHECK(ivec2::copy_ctor_counter == 2); - meta::value vv3{vp.cderef()}; + meta::value vv3{*std::as_const(vp)}; CHECK(ivec2::move_ctor_counter == 0); CHECK(ivec2::copy_ctor_counter == 3); } + { + meta::value v{std::make_shared(42)}; + CHECK(*v == 42); + } + } +} + +TEST_CASE("meta/meta_utilities/value/arrays") { + namespace meta = meta_hpp; + + SUBCASE("int[3]") { + int arr[3]{1,2,3}; + meta::value v{arr}; + CHECK(v.get_type() == meta::resolve_type()); + CHECK(v[0] == 1); + CHECK(v[1] == 2); + CHECK(v[2] == 3); + } + + SUBCASE("const int[3]") { + const int arr[3]{1,2,3}; + meta::value v{arr}; + CHECK(v.get_type() == meta::resolve_type()); + CHECK(v[0] == 1); + CHECK(v[1] == 2); + CHECK(v[2] == 3); + } + + SUBCASE("std::array") { + meta::value v{std::array{1,2,3}}; + CHECK(v.get_type() == meta::resolve_type>()); + CHECK(v[0] == 1); + CHECK(v[1] == 2); + CHECK(v[2] == 3); + } + + SUBCASE("std::string") { + meta::value v{std::string{"hi!"}}; + CHECK(v.get_type() == meta::resolve_type()); + CHECK(v[0] == 'h'); + CHECK(v[1] == 'i'); + CHECK(v[2] == '!'); + } + + SUBCASE("std::span") { + std::vector arr{1,2,3}; + meta::value v{std::span{arr}}; + CHECK(v.get_type() == meta::resolve_type>()); + CHECK(v[0] == 1); + CHECK(v[1] == 2); + CHECK(v[2] == 3); + } + + SUBCASE("std::vector") { + const meta::value v{std::vector{1,2,3}}; + CHECK(v.get_type() == meta::resolve_type>()); + CHECK(v[0] == 1); + CHECK(v[1] == 2); + CHECK(v[2] == 3); } }