add family id to value

This commit is contained in:
BlackMATov
2021-07-05 21:17:27 +07:00
parent 548a2c680a
commit e9cdbd0c0a
2 changed files with 67 additions and 14 deletions

View File

@@ -20,27 +20,30 @@ namespace meta_hpp
value& operator=(value&&) = default; value& operator=(value&&) = default;
value& operator=(const value&) = default; value& operator=(const value&) = default;
template < typename T > template < typename T
value(T&& value) , typename U = std::decay_t<T>
: raw_{std::forward<T>(value)} {} , typename = std::enable_if_t<!std::is_same_v<U, value>> >
value(T&& val)
: raw_{std::forward<T>(val)}
, fid_{get_type_family_id<U>()} {}
template < typename T > template < typename T
value& operator=(T&& value) noexcept { , typename U = std::decay_t<T>
raw_ = std::forward<T>(value); , typename = std::enable_if_t<!std::is_same_v<U, value>> >
value& operator=(T&& val) {
value{std::forward<T>(val)}.swap(*this);
return *this; return *this;
} }
template < typename T, typename... Args > template < typename T, typename... Args >
value(std::in_place_type_t<T>, Args&&... args) explicit value(std::in_place_type_t<T>, Args&&... args)
: raw_{std::in_place_type<T>, std::forward<Args>(args)...} {} : raw_{std::in_place_type<T>, std::forward<Args>(args)...}
, fid_{get_type_family_id<T>()} {}
template < typename T, typename U, typename... Args > template < typename T, typename U, typename... Args >
value(std::in_place_type_t<T>, std::initializer_list<U> ilist, Args&&... args) explicit value(std::in_place_type_t<T>, std::initializer_list<U> ilist, Args&&... args)
: raw_{std::in_place_type<T>, ilist, std::forward<Args>(args)...} {} : raw_{std::in_place_type<T>, ilist, std::forward<Args>(args)...}
, fid_{get_type_family_id<T>()} {}
void swap(value& other) noexcept {
raw_.swap(other.raw_);
}
template < typename T > template < typename T >
T cast() && { T cast() && {
@@ -68,6 +71,16 @@ namespace meta_hpp
try_cast() const noexcept { try_cast() const noexcept {
return std::any_cast<T>(&raw_); return std::any_cast<T>(&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: public:
bool to_bool() const { return cast<bool>(); } bool to_bool() const { return cast<bool>(); }
int to_int() const { return cast<int>(); } int to_int() const { return cast<int>(); }
@@ -91,6 +104,7 @@ namespace meta_hpp
std::uintptr_t to_uintptr_t() const { return cast<std::uintptr_t>(); } std::uintptr_t to_uintptr_t() const { return cast<std::uintptr_t>(); }
private: private:
std::any raw_; std::any raw_;
family_id fid_;
}; };
inline void swap(value& l, value& r) noexcept { inline void swap(value& l, value& r) noexcept {

View File

@@ -7,8 +7,13 @@
#include <meta.hpp/meta_value.hpp> #include <meta.hpp/meta_value.hpp>
#include "doctest/doctest.hpp" #include "doctest/doctest.hpp"
#include <string>
#include <vector>
namespace namespace
{ {
class clazz {};
class clazz2 {};
} }
TEST_CASE("meta/value") { TEST_CASE("meta/value") {
@@ -36,3 +41,37 @@ TEST_CASE("meta/value") {
CHECK(meta::value{std::in_place_type<std::size_t>, std::size_t{1}}.to_size_t() == 1u); CHECK(meta::value{std::in_place_type<std::size_t>, std::size_t{1}}.to_size_t() == 1u);
CHECK(meta::value{std::in_place_type<std::uintptr_t>, std::uintptr_t{1}}.to_uintptr_t() == 1u); CHECK(meta::value{std::in_place_type<std::uintptr_t>, 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<clazz>());
CHECK(meta::value{clazz2{}}.fid() == meta::get_type_family_id<clazz2>());
CHECK(meta::value{clazz{}}.fid() != meta::value{clazz2{}}.fid());
{
meta::value v = clazz{};
CHECK(v.fid() == meta::get_type_family_id<clazz>());
v = clazz2{};
CHECK(v.fid() == meta::get_type_family_id<clazz2>());
}
CHECK(meta::value{std::in_place_type<int>, 1}.fid() == meta::get_type_family_id<int>());
CHECK(meta::value{std::in_place_type<std::vector<int>>, {1,2,3,4}}.fid() == meta::get_type_family_id<std::vector<int>>());
}
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<int>());
CHECK(v1.to_int() == 42);
CHECK(v2.fid() == meta::get_type_family_id<std::string>());
CHECK(v2.to_string() == "hello");
}