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

@@ -33,29 +33,31 @@ TEST_CASE("meta/meta_manuals/metadata") {
// key: std::string
// value: meta::uvalue
meta::class_<ivec3>({
{"tooltip", "3D Vector"s} // for class type
})
meta::class_<ivec3>(meta::metadata_() // for class type
("tooltip", "3D Vector"s)
)
.member_("x", &ivec3::x, {
.metadata { {"tooltip", "X-Coordinate"s} } // for class members
.metadata = meta::metadata_() // for class members
("tooltip", "X-Coordinate"s)
})
.member_("y", &ivec3::y, {
.metadata { {"tooltip", "Y-Coordinate"s} }
.metadata = meta::metadata_()
("tooltip", "Y-Coordinate"s)
})
.member_("z", &ivec3::z, {
.metadata { {"tooltip", "Z-Coordinate"s} }
.metadata = meta::metadata_()
("tooltip", "Z-Coordinate"s)
});
const meta::scope math_scope = meta::local_scope_("math")
.typedef_<ivec3>("ivec3")
.function_("cross", &cross, {
.arguments {{
.name = "first vector",
.metadata {} // even function arguments can have metadata
},{
.name = "second vector"
}},
.metadata { {"tooltip", "Cross product of vectors"s} } // for functions in a scope
.arguments = meta::arguments_()
("first vector")
("second vector", meta::metadata_() // even function arguments can have metadata
("tooltip", "The second cross product argument"s)),
.metadata = meta::metadata_() // for functions in a scope
("tooltip", "Cross product of vectors"s),
});
// after binding, you can use it as you wish

View File

@@ -61,7 +61,7 @@ TEST_CASE("meta/meta_manuals/uvalue") {
TEST_CASE("meta/meta_manuals/uvalue/usage") {
namespace meta = meta_hpp;
// the 'uvalue' class allows to store any copyable value inside
// the 'uvalue' class allows to store any typed value inside
// it's widely used as return value types and as containers for storing metadata
meta::uvalue val{42};

View File

@@ -1674,15 +1674,18 @@ namespace meta_hpp
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, //
@@ -1690,35 +1693,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;
@@ -1739,6 +1738,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;
@@ -2761,7 +2763,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> {
@@ -3307,10 +3309,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;
@@ -3324,35 +3326,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;
@@ -3475,9 +3473,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
@@ -3533,34 +3534,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
@@ -4475,7 +4477,7 @@ namespace meta_hpp
};
struct method_opts final {
argument_opts_list arguments;
argument_opts_list arguments{};
metadata_map metadata{};
};
@@ -4818,6 +4820,98 @@ namespace meta_hpp
}
}
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{};
}
}
namespace meta_hpp
{
template < detail::array_kind Array >
@@ -6267,8 +6361,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 //
@@ -6725,7 +6819,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 //
@@ -7090,8 +7184,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 //
@@ -7634,9 +7728,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>;
@@ -7644,7 +7737,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 //
@@ -7668,6 +7764,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)...);
}
});
}
@@ -8078,12 +8178,11 @@ 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;
}
}
@@ -8156,7 +8255,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 //
@@ -9246,6 +9345,29 @@ namespace meta_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};
}
};
}
namespace meta_hpp::detail
{
template < typename T >
@@ -9268,14 +9390,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>> {
@@ -9316,15 +9430,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>> {
@@ -9409,9 +9514,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);
@@ -9496,24 +9601,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);
@@ -9580,21 +9667,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);
@@ -9610,6 +9682,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 {
@@ -9648,6 +9730,8 @@ namespace meta_hpp
namespace meta_hpp
{
inline const uvalue uvalue::empty_value;
inline uvalue::~uvalue() noexcept {
reset();
}
@@ -9656,10 +9740,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);
@@ -9667,13 +9747,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));
@@ -9686,30 +9759,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)...);
@@ -9811,6 +9880,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 //
@@ -10024,20 +10105,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;
@@ -10045,8 +10123,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

@@ -0,0 +1,64 @@
/*******************************************************************************
* 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)
******************************************************************************/
#include <meta.hpp/meta_all.hpp>
#include <doctest/doctest.h>
namespace
{
struct move_only_clazz {
int v{};
move_only_clazz(int nv) : v{nv} {}
move_only_clazz(move_only_clazz&&) = default;
move_only_clazz(const move_only_clazz&) = delete;
move_only_clazz& operator=(move_only_clazz&&) = default;
move_only_clazz& operator=(const move_only_clazz&) = delete;
static move_only_clazz static_ctor(int nv) {
return move_only_clazz{nv};
}
move_only_clazz clone() {
return move_only_clazz{v};
}
};
}
TEST_CASE("meta/meta_features/move_only/_") {
namespace meta = meta_hpp;
meta::class_<move_only_clazz>()
.constructor_<int>()
.function_("static_ctor", &move_only_clazz::static_ctor)
.method_("clone", &move_only_clazz::clone);
}
TEST_CASE("meta/meta_features/move_only") {
namespace meta = meta_hpp;
const meta::class_type move_only_clazz_type = meta::resolve_type<move_only_clazz>();
SUBCASE("constructor") {
meta::uvalue v = move_only_clazz_type.create(42);
REQUIRE(v.get_type() == move_only_clazz_type);
CHECK(v.as<move_only_clazz>().v == 42);
}
SUBCASE("function") {
meta::uvalue v = move_only_clazz_type.get_function("static_ctor").invoke(42);
REQUIRE(v.get_type() == move_only_clazz_type);
CHECK(v.as<move_only_clazz>().v == 42);
}
SUBCASE("method") {
meta::uvalue v = move_only_clazz_type.get_method("clone").invoke(move_only_clazz{42});
REQUIRE(v.get_type() == move_only_clazz_type);
CHECK(v.as<move_only_clazz>().v == 42);
}
}

View File

@@ -50,7 +50,7 @@ TEST_CASE("meta/meta_issues/random/4") {
SUBCASE("3") {
meta::uvalue v2{std::in_place_type<throw_on_copy>};
CHECK_THROWS(v = v2);
CHECK_THROWS(v = v2.copy());
CHECK(v.get_type() == meta::resolve_type<int>());
CHECK_NOTHROW(v = std::move(v2));
CHECK(v.get_type() == meta::resolve_type<throw_on_copy>());
@@ -58,7 +58,7 @@ TEST_CASE("meta/meta_issues/random/4") {
SUBCASE("4") {
meta::uvalue v2{std::in_place_type<throw_on_move>};
CHECK_THROWS(v = v2);
CHECK_THROWS(v = v2.copy());
CHECK(v.get_type() == meta::resolve_type<int>());
CHECK_NOTHROW(v = std::move(v2));
CHECK(v.get_type() == meta::resolve_type<throw_on_move>());

View File

@@ -443,3 +443,78 @@ TEST_CASE("meta/meta_states/ctor/as_shared_pointer") {
CHECK(clazz_t::copy_constructor_counter == 1);
}
}
TEST_CASE("meta/meta_states/ctor/as_unique_pointer") {
namespace meta = meta_hpp;
using clazz_t = clazz<meta::constructor_policy::as_unique_pointer_t>;
meta::class_<clazz_t>()
.constructor_<int>(meta::constructor_policy::as_unique_pointer)
.constructor_<clazz_t&&>(meta::constructor_policy::as_unique_pointer)
.constructor_<const clazz_t&>(meta::constructor_policy::as_unique_pointer);
clazz_t::constructor_counter = 0;
clazz_t::destructor_counter = 0;
clazz_t::move_constructor_counter = 0;
clazz_t::copy_constructor_counter = 0;
const meta::class_type clazz_type = meta::resolve_type<clazz_t>();
REQUIRE(clazz_type);
SUBCASE("int") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<int>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, int>());
}
{
const meta::uvalue v = clazz_type.create(42);
CHECK(v.get_type() == meta::resolve_type<std::unique_ptr<clazz_t>>());
CHECK(v.as<std::unique_ptr<clazz_t>>()->i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 1);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("clazz_t&&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<clazz_t&&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, clazz_t&&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::move(o));
CHECK(v.get_type() == meta::resolve_type<std::unique_ptr<clazz_t>>());
CHECK(v.as<std::unique_ptr<clazz_t>>()->i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 1);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("const clazz_t&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<const clazz_t&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, const clazz_t&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::as_const(o));
CHECK(v.get_type() == meta::resolve_type<std::unique_ptr<clazz_t>>());
CHECK(v.as<std::unique_ptr<clazz_t>>()->i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 1);
}
}

View File

@@ -38,9 +38,8 @@ TEST_CASE("meta/meta_states/dtor") {
meta::class_<clazz_dtor_metadata>()
.destructor_({
.metadata{
{"desc", "virtual dtor"s}
}
.metadata = meta::metadata_()
("desc", "virtual dtor"s)
});
SUBCASE("closed_dtor") {

View File

@@ -38,32 +38,29 @@ TEST_CASE("meta/meta_states/metadata/enum") {
namespace meta = meta_hpp;
using namespace std::string_literals;
meta::enum_<color>({
{"desc1", "enum-desc1"s},
{"desc2", "enum-desc2"s},
})
meta::enum_<color>(meta::metadata_()
("desc1", "enum-desc1"s)
("desc2", "enum-desc2"s))
.evalue_("red", color::red, {
.metadata{{"desc1", "red-color"s}}
.metadata{meta::metadata_()("desc1", "red-color"s)}
})
.evalue_("green", color::green, {
.metadata{{"desc1", "green-color"s}}
.metadata{meta::metadata_()("desc1", "green-color"s)}
})
.evalue_("blue", color::blue, {
.metadata{{"desc1", "blue-color"s}}
.metadata{meta::metadata_()("desc1", "blue-color"s)}
});
// metadata override
meta::enum_<color>({
{"desc2", "new-enum-desc2"s},
{"desc3", "new-enum-desc3"s},
});
meta::enum_<color>(meta::metadata_()
("desc2", "new-enum-desc2"s)
("desc3", "new-enum-desc3"s));
meta::enum_<color>()
.evalue_("red", color::red, {
.metadata{
{"desc2", "new-red-color"s},
}
.metadata = meta::metadata_()
("desc2", "new-red-color"s)
});
//
@@ -89,57 +86,45 @@ TEST_CASE("meta/meta_states/metadata/class") {
namespace meta = meta_hpp;
using namespace std::string_literals;
meta::class_<ivec2>({
{"desc1", "class-desc1"s},
{"desc2", "class-desc2"s},
})
meta::class_<ivec2>(meta::metadata_()
("desc1", "class-desc1"s)
("desc2", "class-desc2"s))
.constructor_<int>({
.arguments{{
.name{"v"},
.metadata{{"desc", "the ctor arg"s}},
}},
.metadata{{"desc", "one arg 2d vector ctor"s}},
.arguments{meta::arguments_()
("v", meta::metadata_()("desc", "the ctor arg"s))},
.metadata{meta::metadata_()("desc", "one arg 2d vector ctor"s)},
})
.constructor_<int, int>({
.arguments{{
.name{"x"},
.metadata{{"desc", "the 1st ctor arg"s}},
},{
.name{"y"},
.metadata{{"desc", "the 2nd ctor arg"s}},
}},
.metadata{{"desc", "two args 2d vector ctor"s}}
.arguments{meta::arguments_()
("x", meta::metadata_()("desc", "the 1st ctor arg"s))
("y", meta::metadata_()("desc", "the 2nd ctor arg"s))
},
.metadata{meta::metadata_()("desc", "two args 2d vector ctor"s)}
})
.member_("x", &ivec2::x, {
.metadata{{"desc", "x-member"s}}
.metadata{meta::metadata_()("desc", "x-member"s)}
})
.member_("y", &ivec2::y, {
.metadata{{"desc", "y-member"s}}
.metadata{meta::metadata_()("desc", "y-member"s)}
})
.method_("add", &ivec2::add, {
.arguments{{
.name{"other"},
.metadata{{"desc", "other-arg"s}}
}},
.metadata{{"desc", "add-method"s}}
.arguments{meta::arguments_()
("other", meta::metadata_()("desc", "other-arg"s))},
.metadata{meta::metadata_()("desc", "add-method"s)}
})
.function_("iadd", &ivec2::iadd, {
.arguments{{
.name{"l"},
.metadata{{"desc", "l-arg"s}}
},{
.name{"r"},
.metadata{{"desc", "r-arg"s}}
}},
.metadata{{"desc", "iadd-function"s}}
.arguments{meta::arguments_()
("l", meta::metadata_()("desc", "l-arg"s))
("r", meta::metadata_()("desc", "r-arg"s))
},
.metadata{meta::metadata_()("desc", "iadd-function"s)}
});
// metadata override
meta::class_<ivec2>({
{"desc2", "new-class-desc2"s},
{"desc3", "new-class-desc3"s},
});
meta::class_<ivec2>(meta::metadata_()
("desc2", "new-class-desc2"s)
("desc3", "new-class-desc3"s));
//
@@ -243,16 +228,14 @@ TEST_CASE("meta/meta_states/metadata/scope") {
using namespace std::string_literals;
SUBCASE("local_scope") {
const meta::scope lscope = meta::local_scope_("local-scope", {
{"desc", "scope-desc"s}
});
const meta::scope lscope = meta::local_scope_("local-scope", meta::metadata_()
("desc", "scope-desc"s));
CHECK(lscope.get_metadata().at("desc").as<std::string>() == "scope-desc"s);
}
SUBCASE("static_scope") {
meta::static_scope_("meta/meta_states/metadata/scope/static-scope", {
{"desc", "scope-desc"s}
});
meta::static_scope_("meta/meta_states/metadata/scope/static-scope", meta::metadata_()
("desc", "scope-desc"s));
CHECK(meta::resolve_scope("meta/meta_states/metadata/scope/static-scope").get_metadata().at("desc").as<std::string>() == "scope-desc"s);
}
}
@@ -262,65 +245,56 @@ TEST_CASE("meta/meta_states/metadata/other") {
using namespace std::string_literals;
SUBCASE("array") {
meta::array_<int[]>({
{"desc", "int[]-type"s}
});
meta::array_<int[]>(meta::metadata_()
("desc", "int[]-type"s));
CHECK(meta::resolve_type<int[]>().get_metadata().at("desc").as<std::string>() == "int[]-type"s);
}
SUBCASE("function") {
meta::function_<int(int)>({
{"desc", "int->int"s}
});
meta::function_<int(int)>(meta::metadata_()
("desc", "int->int"s));
CHECK(meta::resolve_type<int(int)>().get_metadata().at("desc").as<std::string>() == "int->int"s);
}
SUBCASE("member") {
meta::member_<int ivec2::*>({
{"desc", "ivec2::int"s}
});
meta::member_<int ivec2::*>(meta::metadata_()
("desc", "ivec2::int"s));
CHECK(meta::resolve_type<int ivec2::*>().get_metadata().at("desc").as<std::string>() == "ivec2::int"s);
}
SUBCASE("method") {
meta::method_<int (ivec2::*)(int)>({
{"desc", "ivec2(int -> int)"s}
});
meta::method_<int (ivec2::*)(int)>(meta::metadata_()
("desc", "ivec2(int -> int)"s));
CHECK(meta::resolve_type<int (ivec2::*)(int)>().get_metadata().at("desc").as<std::string>() == "ivec2(int -> int)"s);
}
SUBCASE("nullptr") {
meta::nullptr_<std::nullptr_t>({
{"desc", "nullptr_t"s}
});
meta::nullptr_<std::nullptr_t>(meta::metadata_()
("desc", "nullptr_t"s));
CHECK(meta::resolve_type<std::nullptr_t>().get_metadata().at("desc").as<std::string>() == "nullptr_t"s);
}
SUBCASE("number") {
meta::number_<int>({
{"desc", "int-type"s}
});
meta::number_<int>(meta::metadata_()
("desc", "int-type"s));
CHECK(meta::resolve_type<int>().get_metadata().at("desc").as<std::string>() == "int-type"s);
}
SUBCASE("pointer") {
meta::pointer_<int*>({
{"desc", "int*-type"s}
});
meta::pointer_<int*>(meta::metadata_()
("desc", "int*-type"s));
CHECK(meta::resolve_type<int*>().get_metadata().at("desc").as<std::string>() == "int*-type"s);
}
SUBCASE("reference") {
meta::reference_<int&>({
{"desc", "int&-type"s}
});
meta::reference_<int&>(meta::metadata_()
("desc", "int&-type"s));
CHECK(meta::resolve_type<int&>().get_metadata().at("desc").as<std::string>() == "int&-type"s);
}
SUBCASE("void") {
meta::void_<void>({
{"desc", "void-type"s}
});
meta::void_<void>(meta::metadata_()
("desc", "void-type"s));
CHECK(meta::resolve_type<void>().get_metadata().at("desc").as<std::string>() == "void-type"s);
}
}

View File

@@ -1342,8 +1342,8 @@ TEST_CASE("meta/meta_utilities/arg/ptr_values") {
}
{
auto PRV_PTR = []() -> meta::uvalue { static clazz v; static clazz* p{&v}; static meta::uvalue vv{p}; return vv; };
auto PRV2_PTR = []() -> meta::uvalue { static dclazz v; static dclazz* p{&v}; static meta::uvalue vv{p}; return vv; };
auto PRV_PTR = []() -> meta::uvalue { static clazz v; static clazz* p{&v}; static meta::uvalue vv{p}; return vv.copy(); };
auto PRV2_PTR = []() -> meta::uvalue { static dclazz v; static dclazz* p{&v}; static meta::uvalue vv{p}; return vv.copy(); };
uarg a{r, PRV_PTR()};
CHECK(a.get_raw_type() == meta::resolve_type<clazz*>());
@@ -1379,8 +1379,8 @@ TEST_CASE("meta/meta_utilities/arg/ptr_values") {
}
{
auto PRV_CPTR = []() -> meta::uvalue { static clazz v; static const clazz* p{&v}; static meta::uvalue vv{p}; return vv; };
auto PRV2_CPTR = []() -> meta::uvalue { static dclazz v; static const dclazz* p{&v}; static meta::uvalue vv{p}; return vv; };
auto PRV_CPTR = []() -> meta::uvalue { static clazz v; static const clazz* p{&v}; static meta::uvalue vv{p}; return vv.copy(); };
auto PRV2_CPTR = []() -> meta::uvalue { static dclazz v; static const dclazz* p{&v}; static meta::uvalue vv{p}; return vv.copy(); };
uarg a{r, PRV_CPTR()};
CHECK(a.get_raw_type() == meta::resolve_type<const clazz*>());
@@ -1416,8 +1416,8 @@ TEST_CASE("meta/meta_utilities/arg/ptr_values") {
}
{
auto CPRV_PTR = []() -> const meta::uvalue { static clazz v; static clazz* p{&v}; static meta::uvalue vv{p}; return vv; };
auto CPRV2_PTR = []() -> const meta::uvalue { static dclazz v; static dclazz* p{&v}; static meta::uvalue vv{p}; return vv; };
auto CPRV_PTR = []() -> const meta::uvalue { static clazz v; static clazz* p{&v}; static meta::uvalue vv{p}; return vv.copy(); };
auto CPRV2_PTR = []() -> const meta::uvalue { static dclazz v; static dclazz* p{&v}; static meta::uvalue vv{p}; return vv.copy(); };
uarg a{r, CPRV_PTR()};
CHECK(a.get_raw_type() == meta::resolve_type<clazz*>());
@@ -1453,8 +1453,8 @@ TEST_CASE("meta/meta_utilities/arg/ptr_values") {
}
{
auto CPRV_CPTR = []() -> const meta::uvalue { static clazz v; static const clazz* p{&v}; static meta::uvalue vv{p}; return vv; };
auto CPRV2_CPTR = []() -> const meta::uvalue { static dclazz v; static const dclazz* p{&v}; static meta::uvalue vv{p}; return vv; };
auto CPRV_CPTR = []() -> const meta::uvalue { static clazz v; static const clazz* p{&v}; static meta::uvalue vv{p}; return vv.copy(); };
auto CPRV2_CPTR = []() -> const meta::uvalue { static dclazz v; static const dclazz* p{&v}; static meta::uvalue vv{p}; return vv.copy(); };
uarg a{r, CPRV_CPTR()};
CHECK(a.get_raw_type() == meta::resolve_type<const clazz*>());

View File

@@ -161,7 +161,7 @@ TEST_CASE("meta/meta_utilities/value2/counters/small") {
SUBCASE("copy ctor") {
{
meta::uvalue v1{ivec2{1,2}};
meta::uvalue v2{std::as_const(v1)};
meta::uvalue v2{std::as_const(v1).copy()};
CHECK(v1.as<ivec2>().x == 1);
CHECK(v2.as<ivec2>().y == 2);
@@ -248,7 +248,7 @@ TEST_CASE("meta/meta_utilities/value2/counters/big") {
SUBCASE("copy ctor") {
{
meta::uvalue v1{ivec2_big{1,2}};
meta::uvalue v2{std::as_const(v1)};
meta::uvalue v2{std::as_const(v1).copy()};
CHECK(v1.as<ivec2_big>().x == 1);
CHECK(v2.as<ivec2_big>().y == 2);

View File

@@ -202,11 +202,11 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(std::as_const(val).as<ivec2>() == ivec2{1,2});
{
meta::uvalue val_copy{val};
meta::uvalue val_copy{val.copy()};
CHECK(std::move(val_copy).as<ivec2>() == ivec2{1,2});
}
{
meta::uvalue val_copy{val};
meta::uvalue val_copy{val.copy()};
CHECK(std::move(std::as_const(val_copy)).as<ivec2>() == ivec2{1,2});
}
@@ -242,11 +242,11 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(std::as_const(val).as<ivec2>() == ivec2{1,2});
{
meta::uvalue val_copy{val};
meta::uvalue val_copy{val.copy()};
CHECK(std::move(val_copy).as<ivec2>() == ivec2{1,2});
}
{
meta::uvalue val_copy{val};
meta::uvalue val_copy{val.copy()};
CHECK(std::move(std::as_const(val_copy)).as<ivec2>() == ivec2{1,2});
}
@@ -276,11 +276,11 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(std::as_const(val).as<ivec2>() == ivec2{1,2});
{
meta::uvalue val_copy{val};
meta::uvalue val_copy{val.copy()};
CHECK(std::move(val_copy).as<ivec2>() == ivec2{1,2});
}
{
meta::uvalue val_copy{val};
meta::uvalue val_copy{val.copy()};
CHECK(std::move(std::as_const(val_copy)).as<ivec2>() == ivec2{1,2});
}
@@ -310,11 +310,11 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(std::as_const(val).as<ivec2>() == ivec2{1,2});
{
meta::uvalue val_copy{val};
meta::uvalue val_copy{val.copy()};
CHECK(std::move(val_copy).as<ivec2>() == ivec2{1,2});
}
{
meta::uvalue val_copy{val};
meta::uvalue val_copy{val.copy()};
CHECK(std::move(std::as_const(val_copy)).as<ivec2>() == ivec2{1,2});
}
@@ -341,21 +341,6 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(ivec2::copy_constructor_counter == 0);
}
SUBCASE("value(const meta::value&)") {
const ivec2 v{1,2};
meta::uvalue val_src{v};
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 1);
meta::uvalue val_dst{val_src};
CHECK(val_dst.as<ivec2>() == ivec2{1,2});
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 2);
CHECK(val_src.as<ivec2>() == ivec2{1,2});
CHECK(val_src.get_data() != val_dst.get_data());
}
SUBCASE("value& operator=(T&&)") {
meta::uvalue val{10};
@@ -385,28 +370,6 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(ivec2::copy_constructor_counter == 0);
}
SUBCASE("value& operator=(const meta::value&)") {
meta::uvalue val_src1{"world"s};
meta::uvalue val_src2{ivec2{1,2}};
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
meta::uvalue val_dst{"hello"s};
val_dst = val_src1;
CHECK(val_dst.as<std::string>() == "world"s);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
val_dst = val_src2;
CHECK(val_dst.as<ivec2>() == ivec2{1,2});
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 1);
CHECK(val_src2.as<ivec2>() == ivec2{1,2});
CHECK(val_src2.get_data() != val_dst.get_data());
}
SUBCASE("swap/0") {
meta::uvalue val1{"world"s};
meta::uvalue val2{ivec2{1,2}};

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 //