mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-13 19:18:01 +07:00
uvalue doesn't require copyable type now
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
64
develop/untests/meta_features/move_only_tests.cpp
Normal file
64
develop/untests/meta_features/move_only_tests.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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>());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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*>());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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}};
|
||||
|
||||
@@ -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{};
|
||||
}
|
||||
}
|
||||
|
||||
33
headers/meta.hpp/meta_detail/value_traits/copy_traits.hpp
Normal file
33
headers/meta.hpp/meta_detail/value_traits/copy_traits.hpp
Normal 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};
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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>> {
|
||||
|
||||
@@ -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>> {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)...);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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 //
|
||||
|
||||
@@ -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 //
|
||||
|
||||
@@ -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 //
|
||||
|
||||
@@ -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 //
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 //
|
||||
|
||||
Reference in New Issue
Block a user