uvalue doesn't require copyable type now

This commit is contained in:
BlackMATov
2023-08-08 10:48:44 +07:00
parent caa5df52b1
commit ca57a44c64
27 changed files with 693 additions and 451 deletions

View File

@@ -70,7 +70,7 @@ namespace meta_hpp
};
struct method_opts final {
argument_opts_list arguments;
argument_opts_list arguments{};
metadata_map metadata{};
};
@@ -412,3 +412,95 @@ namespace meta_hpp
return scope_bind{scope, std::move(metadata)};
}
}
namespace meta_hpp
{
class arguments_bind final {
public:
arguments_bind() = default;
~arguments_bind() = default;
arguments_bind(arguments_bind&&) = default;
arguments_bind(const arguments_bind&) = delete;
arguments_bind& operator=(arguments_bind&&) = default;
arguments_bind& operator=(const arguments_bind&) = delete;
arguments_bind& operator()(std::string name) & {
arguments_.push_back(argument_opts{
.name = std::move(name),
});
return *this;
}
arguments_bind operator()(std::string name) && {
arguments_.push_back(argument_opts{
.name = std::move(name),
});
return std::move(*this);
}
arguments_bind& operator()(std::string name, metadata_map metadata) & {
arguments_.push_back(argument_opts{
.name = std::move(name),
.metadata = std::move(metadata),
});
return *this;
}
arguments_bind operator()(std::string name, metadata_map metadata) && {
arguments_.push_back(argument_opts{
.name = std::move(name),
.metadata = std::move(metadata),
});
return std::move(*this);
}
operator argument_opts_list() && {
return std::move(arguments_);
}
private:
argument_opts_list arguments_;
};
inline arguments_bind arguments_() {
return arguments_bind{};
}
}
namespace meta_hpp
{
class metadata_bind final {
public:
metadata_bind() = default;
~metadata_bind() = default;
metadata_bind(metadata_bind&&) = default;
metadata_bind(const metadata_bind&) = delete;
metadata_bind& operator=(metadata_bind&&) = default;
metadata_bind& operator=(const metadata_bind&) = delete;
metadata_bind& operator()(std::string name, uvalue value) & {
metadata_.insert_or_assign(std::move(name), std::move(value));
return *this;
}
metadata_bind operator()(std::string name, uvalue value) && {
metadata_.insert_or_assign(std::move(name), std::move(value));
return std::move(*this);
}
operator metadata_map() && {
return std::move(metadata_);
}
private:
metadata_map metadata_;
};
inline metadata_bind metadata_() {
return metadata_bind{};
}
}

View File

@@ -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-2023, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#pragma once
#include "../../meta_base.hpp"
#include "../../meta_uvalue.hpp"
namespace meta_hpp::detail
{
template < typename T >
struct copy_traits;
template < typename T >
concept has_copy_traits //
= requires(const T& v) {
{ copy_traits<T>{}(v) } -> std::convertible_to<uvalue>;
};
}
namespace meta_hpp::detail
{
template < typename T >
requires std::is_copy_constructible_v<T>
struct copy_traits<T> {
uvalue operator()(const T& v) const {
return uvalue{v};
}
};
}

View File

@@ -31,14 +31,6 @@ namespace meta_hpp::detail
}
};
template < typename T >
requires std::is_copy_constructible_v<T>
struct deref_traits<const T*> {
uvalue operator()(const T* v) const {
return v != nullptr ? uvalue{*v} : uvalue{};
}
};
template < typename T >
requires std::is_copy_constructible_v<T>
struct deref_traits<std::shared_ptr<T>> {

View File

@@ -32,15 +32,6 @@ namespace meta_hpp::detail
}
};
template < typename T >
requires std::is_copy_constructible_v<T>
struct index_traits<const T*> {
uvalue operator()(const T* v, std::size_t i) const {
// NOLINTNEXTLINE(*-pointer-arithmetic)
return v != nullptr ? uvalue{v[i]} : uvalue{};
}
};
template < typename T, std::size_t Size >
requires std::is_copy_constructible_v<T>
struct index_traits<std::array<T, Size>> {

View File

@@ -24,9 +24,12 @@ namespace meta_hpp
struct as_shared_pointer_t final {};
struct as_unique_pointer_t final {};
inline constexpr as_object_t as_object{};
inline constexpr as_raw_pointer_t as_raw_pointer{};
inline constexpr as_shared_pointer_t as_shared_pointer{};
inline constexpr as_unique_pointer_t as_unique_pointer{};
}
namespace function_policy
@@ -82,34 +85,35 @@ namespace meta_hpp
}
template < typename Policy >
concept constructor_policy_family //
= std::is_same_v<Policy, constructor_policy::as_object_t> //
|| std::is_same_v<Policy, constructor_policy::as_raw_pointer_t> //
|| std::is_same_v<Policy, constructor_policy::as_shared_pointer_t>;
concept constructor_policy_family //
= std::is_same_v<Policy, constructor_policy::as_object_t> //
|| std::is_same_v<Policy, constructor_policy::as_raw_pointer_t> //
|| std::is_same_v<Policy, constructor_policy::as_shared_pointer_t> //
|| std::is_same_v<Policy, constructor_policy::as_unique_pointer_t>; //
template < typename Policy >
concept function_policy_family //
= std::is_same_v<Policy, function_policy::as_copy_t> //
|| std::is_same_v<Policy, function_policy::discard_return_t> //
|| std::is_same_v<Policy, function_policy::return_reference_as_pointer_t>;
concept function_policy_family //
= std::is_same_v<Policy, function_policy::as_copy_t> //
|| std::is_same_v<Policy, function_policy::discard_return_t> //
|| std::is_same_v<Policy, function_policy::return_reference_as_pointer_t>; //
template < typename Policy >
concept member_policy_family //
= std::is_same_v<Policy, member_policy::as_copy_t> //
|| std::is_same_v<Policy, member_policy::as_pointer_t> //
|| std::is_same_v<Policy, member_policy::as_reference_wrapper_t>;
concept member_policy_family //
= std::is_same_v<Policy, member_policy::as_copy_t> //
|| std::is_same_v<Policy, member_policy::as_pointer_t> //
|| std::is_same_v<Policy, member_policy::as_reference_wrapper_t>; //
template < typename Policy >
concept method_policy_family //
= std::is_same_v<Policy, method_policy::as_copy_t> //
|| std::is_same_v<Policy, method_policy::discard_return_t> //
|| std::is_same_v<Policy, method_policy::return_reference_as_pointer_t>;
concept method_policy_family //
= std::is_same_v<Policy, method_policy::as_copy_t> //
|| std::is_same_v<Policy, method_policy::discard_return_t> //
|| std::is_same_v<Policy, method_policy::return_reference_as_pointer_t>; //
template < typename Policy >
concept variable_policy_family //
= std::is_same_v<Policy, variable_policy::as_copy_t> //
|| std::is_same_v<Policy, variable_policy::as_pointer_t> //
|| std::is_same_v<Policy, variable_policy::as_reference_wrapper_t>;
concept variable_policy_family //
= std::is_same_v<Policy, variable_policy::as_copy_t> //
|| std::is_same_v<Policy, variable_policy::as_pointer_t> //
|| std::is_same_v<Policy, variable_policy::as_reference_wrapper_t>; //
}
namespace meta_hpp

View File

@@ -21,9 +21,8 @@ namespace meta_hpp::detail
using class_type = typename ct::class_type;
using argument_types = typename ct::argument_types;
constexpr bool as_object //
= std::is_copy_constructible_v<class_type> //
&& std::is_same_v<Policy, constructor_policy::as_object_t>;
constexpr bool as_object //
= std::is_same_v<Policy, constructor_policy::as_object_t>;
constexpr bool as_raw_ptr //
= std::is_same_v<Policy, constructor_policy::as_raw_pointer_t>;
@@ -31,7 +30,10 @@ namespace meta_hpp::detail
constexpr bool as_shared_ptr //
= std::is_same_v<Policy, constructor_policy::as_shared_pointer_t>;
static_assert(as_object || as_raw_ptr || as_shared_ptr);
constexpr bool as_unique_ptr //
= std::is_same_v<Policy, constructor_policy::as_unique_pointer_t>;
static_assert(as_object || as_raw_ptr || as_shared_ptr || as_unique_ptr);
META_HPP_ASSERT( //
args.size() == ct::arity //
@@ -55,6 +57,10 @@ namespace meta_hpp::detail
if constexpr ( as_shared_ptr ) {
return std::make_shared<class_type>(META_HPP_FWD(all_args)...);
}
if constexpr ( as_unique_ptr ) {
return std::make_unique<class_type>(META_HPP_FWD(all_args)...);
}
});
}

View File

@@ -21,8 +21,8 @@ namespace meta_hpp::detail
using return_type = typename ft::return_type;
using argument_types = typename ft::argument_types;
constexpr bool as_copy //
= std::is_copy_constructible_v<return_type> //
constexpr bool as_copy //
= std::is_constructible_v<uvalue, return_type> //
&& std::is_same_v<Policy, function_policy::as_copy_t>;
constexpr bool as_void //

View File

@@ -23,7 +23,7 @@ namespace meta_hpp::detail
using value_type = typename mt::value_type;
constexpr bool as_copy //
= std::is_copy_constructible_v<value_type> //
= std::is_constructible_v<uvalue, value_type> //
&& std::is_same_v<Policy, member_policy::as_copy_t>; //
constexpr bool as_ptr //

View File

@@ -23,8 +23,8 @@ namespace meta_hpp::detail
using qualified_type = typename mt::qualified_type;
using argument_types = typename mt::argument_types;
constexpr bool as_copy //
= std::is_copy_constructible_v<return_type> //
constexpr bool as_copy //
= std::is_constructible_v<uvalue, return_type> //
&& std::is_same_v<Policy, method_policy::as_copy_t>;
constexpr bool as_void //

View File

@@ -21,7 +21,7 @@ namespace meta_hpp::detail
using data_type = typename pt::data_type;
constexpr bool as_copy //
= std::is_copy_constructible_v<data_type> //
= std::is_constructible_v<uvalue, data_type> //
&& std::is_same_v<Policy, variable_policy::as_copy_t>; //
constexpr bool as_ptr //

View File

@@ -350,7 +350,7 @@ namespace meta_hpp
template < detail::enum_kind Enum >
[[nodiscard]] std::string_view value_to_name(Enum value) const noexcept;
[[nodiscard]] uvalue name_to_value(std::string_view name) const noexcept;
[[nodiscard]] const uvalue& name_to_value(std::string_view name) const noexcept;
};
class function_type final : public type_base<function_type> {

View File

@@ -62,11 +62,10 @@ namespace meta_hpp
return std::string_view{};
}
inline uvalue enum_type::name_to_value(std::string_view name) const noexcept {
inline const uvalue& enum_type::name_to_value(std::string_view name) const noexcept {
if ( const evalue& value = get_evalue(name) ) {
return value.get_value();
}
return uvalue{};
return uvalue::empty_value;
}
}

View File

@@ -68,10 +68,10 @@ namespace meta_hpp
~uresult() = default;
uresult(uresult&&) noexcept = default;
uresult(const uresult&) = default;
uresult(const uresult&) = delete;
uresult& operator=(uresult&&) noexcept = default;
uresult& operator=(const uresult&) = default;
uresult& operator=(const uresult&) = delete;
explicit(false) uresult(uerror error) noexcept;
explicit(false) uresult(uvalue value) noexcept;
@@ -85,35 +85,31 @@ namespace meta_hpp
typename = std::enable_if_t< //
!uvalue_family<Tp> && //
!detail::is_in_place_type_v<Tp> && //
std::is_copy_constructible_v<Tp>>> //
std::is_constructible_v<Tp, T>>> //
uresult(T&& val);
template < //
typename T, //
typename Tp = std::decay_t<T>, //
typename = std::enable_if_t< //
!uvalue_family<Tp> && //
std::is_copy_constructible_v<Tp>>> //
template < //
typename T, //
typename Tp = std::decay_t<T>, //
typename = std::enable_if_t< //
!uvalue_family<Tp> && //
std::is_constructible_v<Tp, T>>> //
uresult& operator=(T&& val);
template < typename T, typename... Args, typename Tp = std::decay_t<T> >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, Args...> //
requires std::is_constructible_v<Tp, Args...> //
explicit uresult(std::in_place_type_t<T>, Args&&... args);
template < typename T, typename U, typename... Args, typename Tp = std::decay_t<T> >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
requires std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
explicit uresult(std::in_place_type_t<T>, std::initializer_list<U> ilist, Args&&... args);
template < typename T, typename... Args, typename Tp = std::decay_t<T> >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, Args...> //
requires std::is_constructible_v<Tp, Args...> //
Tp& emplace(Args&&... args);
template < typename T, typename U, typename... Args, typename Tp = std::decay_t<T> >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
requires std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
Tp& emplace(std::initializer_list<U> ilist, Args&&... args);
[[nodiscard]] bool has_error() const noexcept;

View File

@@ -83,20 +83,17 @@ namespace meta_hpp
}
template < typename T, typename... Args, typename Tp >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, Args...> //
requires std::is_constructible_v<Tp, Args...> //
uresult::uresult(std::in_place_type_t<T>, Args&&... args)
: value_{std::in_place_type<T>, std::forward<Args>(args)...} {}
template < typename T, typename U, typename... Args, typename Tp >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
requires std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
uresult::uresult(std::in_place_type_t<T>, std::initializer_list<U> ilist, Args&&... args)
: value_{std::in_place_type<T>, ilist, std::forward<Args>(args)...} {}
template < typename T, typename... Args, typename Tp >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, Args...> //
requires std::is_constructible_v<Tp, Args...> //
Tp& uresult::emplace(Args&&... args) {
Tp& val{value_.emplace<Tp>(std::forward<Args>(args)...)};
error_ = error_code::no_error;
@@ -104,8 +101,7 @@ namespace meta_hpp
}
template < typename T, typename U, typename... Args, typename Tp >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
requires std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
Tp& uresult::emplace(std::initializer_list<U> ilist, Args&&... args) {
Tp& val{value_.emplace<Tp>(ilist, std::forward<Args>(args)...)};
error_ = error_code::no_error;

View File

@@ -11,15 +11,18 @@
namespace meta_hpp
{
class uvalue final {
public:
static const uvalue empty_value;
public:
uvalue() = default;
~uvalue() noexcept;
uvalue(uvalue&& other) noexcept;
uvalue(const uvalue& other);
uvalue(const uvalue& other) = delete;
uvalue& operator=(uvalue&& other) noexcept;
uvalue& operator=(const uvalue& other);
uvalue& operator=(const uvalue& other) = delete;
template < //
typename T, //
@@ -27,35 +30,31 @@ namespace meta_hpp
typename = std::enable_if_t< //
!uvalue_family<Tp> && //
!detail::is_in_place_type_v<Tp> && //
std::is_copy_constructible_v<Tp>>> //
std::is_constructible_v<Tp, T>>> //
uvalue(T&& val);
template < //
typename T, //
typename Tp = std::decay_t<T>, //
typename = std::enable_if_t< //
!uvalue_family<Tp> && //
std::is_copy_constructible_v<Tp>>> //
template < //
typename T, //
typename Tp = std::decay_t<T>, //
typename = std::enable_if_t< //
!uvalue_family<Tp> && //
std::is_constructible_v<Tp, T>>> //
uvalue& operator=(T&& val);
template < typename T, typename... Args, typename Tp = std::decay_t<T> >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, Args...> //
requires std::is_constructible_v<Tp, Args...> //
explicit uvalue(std::in_place_type_t<T>, Args&&... args);
template < typename T, typename U, typename... Args, typename Tp = std::decay_t<T> >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
requires std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
explicit uvalue(std::in_place_type_t<T>, std::initializer_list<U> ilist, Args&&... args);
template < typename T, typename... Args, typename Tp = std::decay_t<T> >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, Args...> //
requires std::is_constructible_v<Tp, Args...> //
Tp& emplace(Args&&... args);
template < typename T, typename U, typename... Args, typename Tp = std::decay_t<T> >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
requires std::is_constructible_v<Tp, std::initializer_list<U>&, Args...> //
Tp& emplace(std::initializer_list<U> ilist, Args&&... args);
[[nodiscard]] bool has_value() const noexcept;
@@ -76,6 +75,9 @@ namespace meta_hpp
[[nodiscard]] uvalue operator[](std::size_t index) const;
[[nodiscard]] bool has_index_op() const noexcept;
[[nodiscard]] uvalue copy() const;
[[nodiscard]] bool has_copy_op() const noexcept;
[[nodiscard]] uvalue unmap() const;
[[nodiscard]] bool has_unmap_op() const noexcept;

View File

@@ -10,6 +10,7 @@
#include "../meta_registry.hpp"
#include "../meta_uvalue.hpp"
#include "../meta_detail/value_traits/copy_traits.hpp"
#include "../meta_detail/value_traits/deref_traits.hpp"
#include "../meta_detail/value_traits/index_traits.hpp"
#include "../meta_detail/value_traits/unmap_traits.hpp"
@@ -24,9 +25,9 @@ namespace meta_hpp
const any_type type;
void (*const move)(uvalue&& self, uvalue& to) noexcept;
void (*const copy)(const uvalue& self, uvalue& to);
void (*const reset)(uvalue& self) noexcept;
uvalue (*const copy)(const storage_u& self);
uvalue (*const deref)(const storage_u& self);
uvalue (*const index)(const storage_u& self, std::size_t i);
uvalue (*const unmap)(const storage_u& self);
@@ -111,24 +112,6 @@ namespace meta_hpp
}
}
static void do_copy(const uvalue& self, uvalue& to) {
META_HPP_DEV_ASSERT(!to);
auto&& [tag, vtable] = unpack_vtag(self);
switch ( tag ) {
case storage_e::nothing:
break;
case storage_e::trivial:
to.storage_ = self.storage_;
break;
case storage_e::internal:
case storage_e::external:
vtable->copy(self, to);
break;
}
}
static void do_reset(uvalue& self) noexcept {
auto&& [tag, vtable] = unpack_vtag(self);
@@ -195,21 +178,6 @@ namespace meta_hpp
}
}},
.copy{[](const uvalue& self, uvalue& to) {
META_HPP_DEV_ASSERT(!to);
META_HPP_DEV_ASSERT(self);
const Tp* src = storage_cast<Tp>(self.storage_);
if constexpr ( in_internal_v<Tp> ) {
do_ctor<Tp>(to, *src);
} else {
// NOLINTNEXTLINE(*-union-access, *-owning-memory)
to.storage_.external.ptr = new Tp(*src);
to.storage_.vtag = self.storage_.vtag;
}
}},
.reset{[](uvalue& self) noexcept {
META_HPP_DEV_ASSERT(self);
@@ -225,6 +193,16 @@ namespace meta_hpp
self.storage_.vtag = 0;
}},
.copy{[]() {
if constexpr ( detail::has_copy_traits<Tp> ) {
return +[](const storage_u& self) -> uvalue {
return detail::copy_traits<Tp>{}(*storage_cast<Tp>(self));
};
} else {
return nullptr;
}
}()},
.deref{[]() {
if constexpr ( detail::has_deref_traits<Tp> ) {
return +[](const storage_u& self) -> uvalue {
@@ -263,6 +241,8 @@ namespace meta_hpp
namespace meta_hpp
{
inline const uvalue uvalue::empty_value;
inline uvalue::~uvalue() noexcept {
reset();
}
@@ -271,10 +251,6 @@ namespace meta_hpp
vtable_t::do_move(std::move(other), *this);
}
inline uvalue::uvalue(const uvalue& other) {
vtable_t::do_copy(other, *this);
}
inline uvalue& uvalue::operator=(uvalue&& other) noexcept {
if ( this != &other ) {
uvalue{std::move(other)}.swap(*this);
@@ -282,13 +258,6 @@ namespace meta_hpp
return *this;
}
inline uvalue& uvalue::operator=(const uvalue& other) {
if ( this != &other ) {
uvalue{other}.swap(*this);
}
return *this;
}
template < typename T, typename Tp, typename >
uvalue::uvalue(T&& val) {
vtable_t::do_ctor<T>(*this, std::forward<T>(val));
@@ -301,30 +270,26 @@ namespace meta_hpp
}
template < typename T, typename... Args, typename Tp >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, Args...>
requires std::is_constructible_v<Tp, Args...>
uvalue::uvalue(std::in_place_type_t<T>, Args&&... args) {
vtable_t::do_ctor<T>(*this, std::forward<Args>(args)...);
}
template < typename T, typename U, typename... Args, typename Tp >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, std::initializer_list<U>&, Args...>
requires std::is_constructible_v<Tp, std::initializer_list<U>&, Args...>
uvalue::uvalue(std::in_place_type_t<T>, std::initializer_list<U> ilist, Args&&... args) {
vtable_t::do_ctor<T>(*this, ilist, std::forward<Args>(args)...);
}
template < typename T, typename... Args, typename Tp >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, Args...>
requires std::is_constructible_v<Tp, Args...>
Tp& uvalue::emplace(Args&&... args) {
vtable_t::do_reset(*this);
return vtable_t::do_ctor<T>(*this, std::forward<Args>(args)...);
}
template < typename T, typename U, typename... Args, typename Tp >
requires std::is_copy_constructible_v<Tp> //
&& std::is_constructible_v<Tp, std::initializer_list<U>&, Args...>
requires std::is_constructible_v<Tp, std::initializer_list<U>&, Args...>
Tp& uvalue::emplace(std::initializer_list<U> ilist, Args&&... args) {
vtable_t::do_reset(*this);
return vtable_t::do_ctor<T>(*this, ilist, std::forward<Args>(args)...);
@@ -426,6 +391,18 @@ namespace meta_hpp
return tag != storage_e::nothing && vtable->index != nullptr;
}
inline uvalue uvalue::copy() const {
auto&& [tag, vtable] = vtable_t::unpack_vtag(*this);
return tag != storage_e::nothing && vtable->copy != nullptr //
? vtable->copy(storage_)
: uvalue{};
}
inline bool uvalue::has_copy_op() const noexcept {
auto&& [tag, vtable] = vtable_t::unpack_vtag(*this);
return tag != storage_e::nothing && vtable->copy != nullptr;
}
inline uvalue uvalue::unmap() const {
auto&& [tag, vtable] = vtable_t::unpack_vtag(*this);
return tag != storage_e::nothing && vtable->unmap != nullptr //