diff --git a/headers/meta.hpp/meta_value.hpp b/headers/meta.hpp/meta_value.hpp index 3676cc1..bfef1d3 100644 --- a/headers/meta.hpp/meta_value.hpp +++ b/headers/meta.hpp/meta_value.hpp @@ -20,27 +20,30 @@ namespace meta_hpp value& operator=(value&&) = default; value& operator=(const value&) = default; - template < typename T > - value(T&& value) - : raw_{std::forward(value)} {} + template < typename T + , typename U = std::decay_t + , typename = std::enable_if_t> > + value(T&& val) + : raw_{std::forward(val)} + , fid_{get_type_family_id()} {} - template < typename T > - value& operator=(T&& value) noexcept { - raw_ = std::forward(value); + template < typename T + , typename U = std::decay_t + , typename = std::enable_if_t> > + value& operator=(T&& val) { + value{std::forward(val)}.swap(*this); return *this; } template < typename T, typename... Args > - value(std::in_place_type_t, Args&&... args) - : raw_{std::in_place_type, std::forward(args)...} {} + explicit value(std::in_place_type_t, Args&&... args) + : raw_{std::in_place_type, std::forward(args)...} + , fid_{get_type_family_id()} {} template < typename T, typename U, typename... Args > - value(std::in_place_type_t, std::initializer_list ilist, Args&&... args) - : raw_{std::in_place_type, ilist, std::forward(args)...} {} - - void swap(value& other) noexcept { - raw_.swap(other.raw_); - } + explicit value(std::in_place_type_t, std::initializer_list ilist, Args&&... args) + : raw_{std::in_place_type, ilist, std::forward(args)...} + , fid_{get_type_family_id()} {} template < typename T > T cast() && { @@ -68,6 +71,16 @@ namespace meta_hpp try_cast() const noexcept { return std::any_cast(&raw_); } + + family_id fid() const noexcept { + return fid_; + } + + void swap(value& other) noexcept { + using std::swap; + swap(raw_, other.raw_); + swap(fid_, other.fid_); + } public: bool to_bool() const { return cast(); } int to_int() const { return cast(); } @@ -91,6 +104,7 @@ namespace meta_hpp std::uintptr_t to_uintptr_t() const { return cast(); } private: std::any raw_; + family_id fid_; }; inline void swap(value& l, value& r) noexcept { diff --git a/untests/meta_value_tests.cpp b/untests/meta_value_tests.cpp index 7de31cd..cd7363e 100644 --- a/untests/meta_value_tests.cpp +++ b/untests/meta_value_tests.cpp @@ -7,8 +7,13 @@ #include #include "doctest/doctest.hpp" +#include +#include + namespace { + class clazz {}; + class clazz2 {}; } TEST_CASE("meta/value") { @@ -36,3 +41,37 @@ TEST_CASE("meta/value") { CHECK(meta::value{std::in_place_type, std::size_t{1}}.to_size_t() == 1u); CHECK(meta::value{std::in_place_type, std::uintptr_t{1}}.to_uintptr_t() == 1u); } + +TEST_CASE("meta/value/fid") { + namespace meta = meta_hpp; + using namespace std::string_literals; + + CHECK(meta::value{clazz{}}.fid() == meta::get_type_family_id()); + CHECK(meta::value{clazz2{}}.fid() == meta::get_type_family_id()); + CHECK(meta::value{clazz{}}.fid() != meta::value{clazz2{}}.fid()); + + { + meta::value v = clazz{}; + CHECK(v.fid() == meta::get_type_family_id()); + v = clazz2{}; + CHECK(v.fid() == meta::get_type_family_id()); + } + + CHECK(meta::value{std::in_place_type, 1}.fid() == meta::get_type_family_id()); + CHECK(meta::value{std::in_place_type>, {1,2,3,4}}.fid() == meta::get_type_family_id>()); +} + +TEST_CASE("meta/value/swap") { + namespace meta = meta_hpp; + using namespace std::string_literals; + + meta::value v1{"hello"s}; + meta::value v2{42}; + meta::swap(v1, v2); + + CHECK(v1.fid() == meta::get_type_family_id()); + CHECK(v1.to_int() == 42); + + CHECK(v2.fid() == meta::get_type_family_id()); + CHECK(v2.to_string() == "hello"); +}