any/meta:
* added alias constructor to any * added alias constructor to meta_any * added alias constructor to poly * added support for const containers, const deref operator and const views to meta_any
This commit is contained in:
@@ -267,15 +267,22 @@ A particularly interesting feature of this class is that it can also be used as
|
||||
an opaque container for const and non-const references:
|
||||
|
||||
```cpp
|
||||
int value;
|
||||
int value = 42;
|
||||
|
||||
// reference construction
|
||||
entt::any any{std::ref(value)};
|
||||
entt::any cany{std::cref(value)};
|
||||
|
||||
// alias construction
|
||||
int value = 42;
|
||||
entt::any in_place{std::in_place_type<int &>, &value};
|
||||
```
|
||||
|
||||
In other words, whenever `any` intercepts a `reference_wrapper`, it acts as a
|
||||
pointer to the original instance rather than making a copy of it or moving it
|
||||
internally. The _contained_ object is never destroyed and users must ensure that
|
||||
its lifetime exceeds that of the container.<br/>
|
||||
In other words, whenever `any` intercepts a `reference_wrapper` or is explicitly
|
||||
told that users want to construct an alias, it acts as a pointer to the original
|
||||
instance rather than making a copy of it or moving it internally. The contained
|
||||
object is never destroyed and users must ensure that its lifetime exceeds that
|
||||
of the container.<br/>
|
||||
Similarly, it's possible to create non-owning copies of `any` from an existing
|
||||
object:
|
||||
|
||||
|
||||
@@ -128,8 +128,7 @@ class any {
|
||||
public:
|
||||
/*! @brief Default constructor. */
|
||||
any() ENTT_NOEXCEPT
|
||||
: vtable{&basic_vtable<void>},
|
||||
instance{}
|
||||
: any{std::in_place_type<void>}
|
||||
{}
|
||||
|
||||
/**
|
||||
@@ -144,7 +143,11 @@ public:
|
||||
instance{}
|
||||
{
|
||||
if constexpr(!std::is_void_v<Type>) {
|
||||
if constexpr(in_situ<Type>) {
|
||||
if constexpr(std::is_lvalue_reference_v<Type>) {
|
||||
static_assert(sizeof...(Args) == 1u && (std::is_pointer_v<std::remove_reference_t<Args>> && ...));
|
||||
ENTT_ASSERT(((args != nullptr) && ...));
|
||||
instance = (args, ...);
|
||||
} else if constexpr(in_situ<Type>) {
|
||||
new (&storage) Type{std::forward<Args>(args)...};
|
||||
} else {
|
||||
instance = new Type{std::forward<Args>(args)...};
|
||||
@@ -159,8 +162,7 @@ public:
|
||||
*/
|
||||
template<typename Type>
|
||||
any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
|
||||
: vtable{&basic_vtable<Type &>},
|
||||
instance{&value.get()}
|
||||
: any{std::in_place_type<Type &>, &value.get()}
|
||||
{}
|
||||
|
||||
/**
|
||||
@@ -316,7 +318,7 @@ private:
|
||||
*/
|
||||
template<typename Type>
|
||||
Type any_cast(const any &data) ENTT_NOEXCEPT {
|
||||
auto * const instance = any_cast<std::remove_reference_t<Type>>(&data);
|
||||
const auto * const instance = any_cast<std::remove_reference_t<Type>>(&data);
|
||||
ENTT_ASSERT(instance);
|
||||
return static_cast<Type>(*instance);
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "../config/config.h"
|
||||
#include "../core/type_traits.hpp"
|
||||
#include "type_traits.hpp"
|
||||
|
||||
|
||||
@@ -22,7 +24,7 @@ namespace entt {
|
||||
* @tparam Trait Traits associated with the underlying container.
|
||||
*/
|
||||
template<typename Container, template<typename> class... Trait>
|
||||
struct container_traits: public Trait<Container>... {};
|
||||
struct meta_container_traits: public Trait<Container>... {};
|
||||
|
||||
|
||||
/**
|
||||
@@ -32,7 +34,7 @@ struct container_traits: public Trait<Container>... {};
|
||||
template<typename Container>
|
||||
struct basic_container {
|
||||
/*! @brief Iterator type of the container. */
|
||||
using iterator = typename Container::iterator;
|
||||
using iterator = std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator>;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = typename Container::size_type;
|
||||
/*! @brief Value type of the container. */
|
||||
@@ -77,13 +79,13 @@ struct basic_associative_container {
|
||||
using key_type = typename Container::key_type;
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the element with key equivalent to the given
|
||||
* one, if any.
|
||||
* @brief Returns an iterator to the element with key equivalent to the
|
||||
* given one, if any.
|
||||
* @param cont The container in which to search for the element.
|
||||
* @param key The key of the element to search.
|
||||
* @return An iterator to the element with the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] static typename Container::iterator find(Container &cont, const key_type &key) {
|
||||
[[nodiscard]] static std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator> find(Container &cont, const key_type &key) {
|
||||
return cont.find(key);
|
||||
}
|
||||
};
|
||||
@@ -100,8 +102,12 @@ struct basic_dynamic_container {
|
||||
* @param cont The container for which to clear the content.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] static bool clear(Container &cont) {
|
||||
return cont.clear(), true;
|
||||
[[nodiscard]] static bool clear([[maybe_unused]] Container &cont) {
|
||||
if constexpr(std::is_const_v<Container>) {
|
||||
return false;
|
||||
} else {
|
||||
return cont.clear(), true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -118,9 +124,13 @@ struct basic_dynamic_associative_container {
|
||||
* @param key The element to remove.
|
||||
* @return A bool denoting whether the removal took place.
|
||||
*/
|
||||
[[nodiscard]] static bool erase(Container &cont, const typename Container::key_type &key) {
|
||||
const auto sz = cont.size();
|
||||
return cont.erase(key) != sz;
|
||||
[[nodiscard]] static bool erase([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) {
|
||||
if constexpr(std::is_const_v<Container>) {
|
||||
return false;
|
||||
} else {
|
||||
const auto sz = cont.size();
|
||||
return cont.erase(key) != sz;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -132,13 +142,13 @@ struct basic_dynamic_associative_container {
|
||||
template<typename Container>
|
||||
struct basic_sequence_container {
|
||||
/**
|
||||
* @brief Returns a reference to the element at the specified location of the
|
||||
* given container (no bounds checking is performed).
|
||||
* @brief Returns a reference to the element at the specified location of
|
||||
* the given container (no bounds checking is performed).
|
||||
* @param cont The container from which to get the element.
|
||||
* @param pos The position of the element to return.
|
||||
* @return A reference to the requested element.
|
||||
*/
|
||||
[[nodiscard]] static typename Container::value_type & get(Container &cont, typename Container::size_type pos) {
|
||||
[[nodiscard]] static constness_as_t<typename Container::value_type, Container> & get(Container &cont, typename Container::size_type pos) {
|
||||
return cont[pos];
|
||||
}
|
||||
};
|
||||
@@ -156,8 +166,12 @@ struct dynamic_associative_key_only_container {
|
||||
* @param key The element to insert.
|
||||
* @return A bool denoting whether the insertion took place.
|
||||
*/
|
||||
[[nodiscard]] static bool insert(Container &cont, const typename Container::key_type &key) {
|
||||
return cont.insert(key).second;
|
||||
[[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) {
|
||||
if constexpr(std::is_const_v<Container>) {
|
||||
return false;
|
||||
} else {
|
||||
return cont.insert(key).second;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -175,8 +189,12 @@ struct dynamic_associative_key_value_container {
|
||||
* @param value The value of the element to insert.
|
||||
* @return A bool denoting whether the insertion took place.
|
||||
*/
|
||||
[[nodiscard]] static bool insert(Container &cont, const typename Container::key_type &key, const typename Container::mapped_type &value) {
|
||||
return cont.insert(std::make_pair(key, value)).second;
|
||||
[[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key, [[maybe_unused]] const typename Container::mapped_type &value) {
|
||||
if constexpr(std::is_const_v<Container>) {
|
||||
return false;
|
||||
} else {
|
||||
return cont.insert(std::make_pair(key, value)).second;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -188,37 +206,54 @@ struct dynamic_associative_key_value_container {
|
||||
template<typename Container>
|
||||
struct dynamic_sequence_container {
|
||||
/**
|
||||
* @brief Resizes the given container to contain the given number of elements.
|
||||
* @brief Resizes the given container to contain the given number of
|
||||
* elements.
|
||||
* @param cont The container to resize.
|
||||
* @param sz The new size of the container.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] static bool resize(Container &cont, typename Container::size_type sz) {
|
||||
return (cont.resize(sz), true);
|
||||
[[nodiscard]] static bool resize([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::size_type sz) {
|
||||
if constexpr(std::is_const_v<Container>) {
|
||||
return false;
|
||||
} else {
|
||||
return cont.resize(sz), true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts an element at the specified location of the given container.
|
||||
* @brief Inserts an element at the specified location of the given
|
||||
* container.
|
||||
* @param cont The container into which to insert the element.
|
||||
* @param it Iterator before which the element will be inserted.
|
||||
* @param value Element value to insert.
|
||||
* @return A pair consisting of an iterator to the inserted element (in case
|
||||
* of success) and a bool denoting whether the insertion took place.
|
||||
*/
|
||||
[[nodiscard]] static std::pair<typename Container::iterator, bool> insert(Container &cont, typename Container::iterator it, const typename Container::value_type &value) {
|
||||
return { cont.insert(it, value), true };
|
||||
[[nodiscard]] static std::pair<std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator>, bool>
|
||||
insert([[maybe_unused]] Container &cont, [[maybe_unused]] std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator> it, [[maybe_unused]] const typename Container::value_type &value) {
|
||||
if constexpr(std::is_const_v<Container>) {
|
||||
return { {}, false };
|
||||
} else {
|
||||
return { cont.insert(it, value), true };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the element at the specified location from the given container.
|
||||
* @brief Removes the element at the specified location from the given
|
||||
* container.
|
||||
* @param cont The container from which to remove the element.
|
||||
* @param it Iterator to the element to remove.
|
||||
* @return A pair consisting of an iterator following the last removed
|
||||
* element (in case of success) and a bool denoting whether the insertion
|
||||
* took place.
|
||||
*/
|
||||
[[nodiscard]] static std::pair<typename Container::iterator, bool> erase(Container &cont, typename Container::iterator it) {
|
||||
return { cont.erase(it), true };
|
||||
[[nodiscard]] static std::pair<std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator>, bool>
|
||||
erase([[maybe_unused]] Container &cont, [[maybe_unused]] std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator> it) {
|
||||
if constexpr(std::is_const_v<Container>) {
|
||||
return { {}, false };
|
||||
} else {
|
||||
return { cont.erase(it), true };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -250,7 +285,8 @@ struct fixed_sequence_container {
|
||||
* @return A pair consisting of an invalid iterator and a false value to
|
||||
* indicate failure in all cases.
|
||||
*/
|
||||
[[nodiscard]] static std::pair<typename Container::iterator, bool> insert(const Container &, typename Container::iterator, const typename Container::value_type &) {
|
||||
[[nodiscard]] static std::pair<std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator>, bool>
|
||||
insert(const Container &, std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator>, const typename Container::value_type &) {
|
||||
return { {}, false };
|
||||
}
|
||||
|
||||
@@ -259,7 +295,8 @@ struct fixed_sequence_container {
|
||||
* @return A pair consisting of an invalid iterator and a false value to
|
||||
* indicate failure in all cases.
|
||||
*/
|
||||
[[nodiscard]] static std::pair<typename Container::iterator, bool> erase(const Container &, typename Container::iterator) {
|
||||
[[nodiscard]] static std::pair<std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator>, bool>
|
||||
erase(const Container &, std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator>) {
|
||||
return { {}, false };
|
||||
}
|
||||
};
|
||||
@@ -272,7 +309,7 @@ struct fixed_sequence_container {
|
||||
*/
|
||||
template<typename Type, typename... Args>
|
||||
struct meta_sequence_container_traits<std::vector<Type, Args...>>
|
||||
: container_traits<
|
||||
: meta_container_traits<
|
||||
std::vector<Type, Args...>,
|
||||
basic_container,
|
||||
basic_dynamic_container,
|
||||
@@ -282,6 +319,23 @@ struct meta_sequence_container_traits<std::vector<Type, Args...>>
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta sequence container traits for const `std::vector`s of any type.
|
||||
* @tparam Type The type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Type, typename... Args>
|
||||
struct meta_sequence_container_traits<const std::vector<Type, Args...>>
|
||||
: meta_container_traits<
|
||||
const std::vector<Type, Args...>,
|
||||
basic_container,
|
||||
basic_dynamic_container,
|
||||
basic_sequence_container,
|
||||
dynamic_sequence_container
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta sequence container traits for `std::array`s of any type.
|
||||
* @tparam Type The type of elements.
|
||||
@@ -289,7 +343,7 @@ struct meta_sequence_container_traits<std::vector<Type, Args...>>
|
||||
*/
|
||||
template<typename Type, auto N>
|
||||
struct meta_sequence_container_traits<std::array<Type, N>>
|
||||
: container_traits<
|
||||
: meta_container_traits<
|
||||
std::array<Type, N>,
|
||||
basic_container,
|
||||
basic_sequence_container,
|
||||
@@ -298,6 +352,22 @@ struct meta_sequence_container_traits<std::array<Type, N>>
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta sequence container traits for const `std::array`s of any type.
|
||||
* @tparam Type The type of elements.
|
||||
* @tparam N The number of elements.
|
||||
*/
|
||||
template<typename Type, auto N>
|
||||
struct meta_sequence_container_traits<const std::array<Type, N>>
|
||||
: meta_container_traits<
|
||||
const std::array<Type, N>,
|
||||
basic_container,
|
||||
basic_sequence_container,
|
||||
fixed_sequence_container
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for `std::map`s of any type.
|
||||
* @tparam Key The key type of elements.
|
||||
@@ -306,7 +376,7 @@ struct meta_sequence_container_traits<std::array<Type, N>>
|
||||
*/
|
||||
template<typename Key, typename Value, typename... Args>
|
||||
struct meta_associative_container_traits<std::map<Key, Value, Args...>>
|
||||
: container_traits<
|
||||
: meta_container_traits<
|
||||
std::map<Key, Value, Args...>,
|
||||
basic_container,
|
||||
basic_associative_container,
|
||||
@@ -320,6 +390,28 @@ struct meta_associative_container_traits<std::map<Key, Value, Args...>>
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for const `std::map`s of any type.
|
||||
* @tparam Key The key type of elements.
|
||||
* @tparam Value The value type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Key, typename Value, typename... Args>
|
||||
struct meta_associative_container_traits<const std::map<Key, Value, Args...>>
|
||||
: meta_container_traits<
|
||||
const std::map<Key, Value, Args...>,
|
||||
basic_container,
|
||||
basic_associative_container,
|
||||
basic_dynamic_container,
|
||||
basic_dynamic_associative_container,
|
||||
dynamic_associative_key_value_container
|
||||
>
|
||||
{
|
||||
/*! @brief Mapped type of the sequence container. */
|
||||
using mapped_type = typename std::map<Key, Value, Args...>::mapped_type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for `std::unordered_map`s of any
|
||||
* type.
|
||||
@@ -329,7 +421,7 @@ struct meta_associative_container_traits<std::map<Key, Value, Args...>>
|
||||
*/
|
||||
template<typename Key, typename Value, typename... Args>
|
||||
struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
|
||||
: container_traits<
|
||||
: meta_container_traits<
|
||||
std::unordered_map<Key, Value, Args...>,
|
||||
basic_container,
|
||||
basic_associative_container,
|
||||
@@ -343,6 +435,29 @@ struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for const `std::unordered_map`s of
|
||||
* any type.
|
||||
* @tparam Key The key type of elements.
|
||||
* @tparam Value The value type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Key, typename Value, typename... Args>
|
||||
struct meta_associative_container_traits<const std::unordered_map<Key, Value, Args...>>
|
||||
: meta_container_traits<
|
||||
const std::unordered_map<Key, Value, Args...>,
|
||||
basic_container,
|
||||
basic_associative_container,
|
||||
basic_dynamic_container,
|
||||
basic_dynamic_associative_container,
|
||||
dynamic_associative_key_value_container
|
||||
>
|
||||
{
|
||||
/*! @brief Mapped type of the sequence container. */
|
||||
using mapped_type = typename std::unordered_map<Key, Value, Args...>::mapped_type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for `std::set`s of any type.
|
||||
* @tparam Key The type of elements.
|
||||
@@ -350,7 +465,7 @@ struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>
|
||||
*/
|
||||
template<typename Key, typename... Args>
|
||||
struct meta_associative_container_traits<std::set<Key, Args...>>
|
||||
: container_traits<
|
||||
: meta_container_traits<
|
||||
std::set<Key, Args...>,
|
||||
basic_container,
|
||||
basic_associative_container,
|
||||
@@ -361,6 +476,24 @@ struct meta_associative_container_traits<std::set<Key, Args...>>
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for const `std::set`s of any type.
|
||||
* @tparam Key The type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Key, typename... Args>
|
||||
struct meta_associative_container_traits<const std::set<Key, Args...>>
|
||||
: meta_container_traits<
|
||||
const std::set<Key, Args...>,
|
||||
basic_container,
|
||||
basic_associative_container,
|
||||
basic_dynamic_container,
|
||||
basic_dynamic_associative_container,
|
||||
dynamic_associative_key_only_container
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for `std::unordered_set`s of any
|
||||
* type.
|
||||
@@ -369,7 +502,7 @@ struct meta_associative_container_traits<std::set<Key, Args...>>
|
||||
*/
|
||||
template<typename Key, typename... Args>
|
||||
struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
|
||||
: container_traits<
|
||||
: meta_container_traits<
|
||||
std::unordered_set<Key, Args...>,
|
||||
basic_container,
|
||||
basic_associative_container,
|
||||
@@ -380,6 +513,25 @@ struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Meta associative container traits for const `std::unordered_set`s of
|
||||
* any type.
|
||||
* @tparam Key The type of elements.
|
||||
* @tparam Args Other arguments.
|
||||
*/
|
||||
template<typename Key, typename... Args>
|
||||
struct meta_associative_container_traits<const std::unordered_set<Key, Args...>>
|
||||
: meta_container_traits<
|
||||
const std::unordered_set<Key, Args...>,
|
||||
basic_container,
|
||||
basic_associative_container,
|
||||
basic_dynamic_container,
|
||||
basic_dynamic_associative_container,
|
||||
dynamic_associative_key_only_container
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -118,7 +118,6 @@ struct meta_type_node {
|
||||
const bool is_associative_container;
|
||||
const size_type rank;
|
||||
size_type(* const extent)(size_type);
|
||||
bool(* const compare)(const void *, const void *);
|
||||
meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
|
||||
meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
|
||||
meta_base_node *base{nullptr};
|
||||
@@ -219,14 +218,6 @@ template<typename Type>
|
||||
class ENTT_API meta_node {
|
||||
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
|
||||
|
||||
[[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
|
||||
if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
|
||||
return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
|
||||
} else {
|
||||
return lhs == rhs;
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t... Index>
|
||||
[[nodiscard]] static auto extent(meta_type_node::size_type dim, std::index_sequence<Index...>) {
|
||||
meta_type_node::size_type ext{};
|
||||
@@ -260,7 +251,6 @@ public:
|
||||
[](meta_type_node::size_type dim) {
|
||||
return extent(dim, std::make_index_sequence<std::rank_v<Type>>{});
|
||||
},
|
||||
&compare, // workaround for an issue with VS2017
|
||||
&meta_node<std::remove_cv_t<std::remove_pointer_t<Type>>>::resolve,
|
||||
&meta_node<std::remove_cv_t<std::remove_extent_t<Type>>>::resolve
|
||||
};
|
||||
|
||||
@@ -41,17 +41,15 @@ public:
|
||||
using iterator = meta_iterator;
|
||||
|
||||
/*! @brief Default constructor. */
|
||||
meta_sequence_container() ENTT_NOEXCEPT
|
||||
: instance{nullptr}
|
||||
{}
|
||||
meta_sequence_container() ENTT_NOEXCEPT = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a proxy object for sequence containers.
|
||||
* @tparam Type Type of container to wrap.
|
||||
* @param container The container to wrap.
|
||||
* @param instance The container to wrap.
|
||||
*/
|
||||
template<typename Type>
|
||||
meta_sequence_container(Type *container) ENTT_NOEXCEPT
|
||||
meta_sequence_container(Type &instance) ENTT_NOEXCEPT
|
||||
: value_type_fn{&meta_sequence_container_proxy<Type>::value_type},
|
||||
size_fn{&meta_sequence_container_proxy<Type>::size},
|
||||
resize_fn{&meta_sequence_container_proxy<Type>::resize},
|
||||
@@ -61,12 +59,12 @@ public:
|
||||
insert_fn{&meta_sequence_container_proxy<Type>::insert},
|
||||
erase_fn{&meta_sequence_container_proxy<Type>::erase},
|
||||
get_fn{&meta_sequence_container_proxy<Type>::get},
|
||||
instance{container}
|
||||
storage{std::reference_wrapper{instance}}
|
||||
{}
|
||||
|
||||
[[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT;
|
||||
[[nodiscard]] inline size_type size() const ENTT_NOEXCEPT;
|
||||
inline bool resize(size_type) const;
|
||||
inline bool resize(size_type);
|
||||
inline bool clear();
|
||||
[[nodiscard]] inline iterator begin();
|
||||
[[nodiscard]] inline iterator end();
|
||||
@@ -77,15 +75,15 @@ public:
|
||||
|
||||
private:
|
||||
meta_type(* value_type_fn)() ENTT_NOEXCEPT = nullptr;
|
||||
size_type(* size_fn)(const void *) ENTT_NOEXCEPT = nullptr;
|
||||
bool(* resize_fn)(void *, size_type) = nullptr;
|
||||
bool(* clear_fn)(void *) = nullptr;
|
||||
iterator(* begin_fn)(void *) = nullptr;
|
||||
iterator(* end_fn)(void *) = nullptr;
|
||||
std::pair<iterator, bool>(* insert_fn)(void *, iterator, meta_any) = nullptr;
|
||||
std::pair<iterator, bool>(* erase_fn)(void *, iterator) = nullptr;
|
||||
meta_any(* get_fn)(void *, size_type) = nullptr;
|
||||
void *instance{};
|
||||
size_type(* size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
|
||||
bool(* resize_fn)(any &, size_type) = nullptr;
|
||||
bool(* clear_fn)(any &) = nullptr;
|
||||
iterator(* begin_fn)(any &) = nullptr;
|
||||
iterator(* end_fn)(any &) = nullptr;
|
||||
std::pair<iterator, bool>(* insert_fn)(any &, iterator, meta_any &) = nullptr;
|
||||
std::pair<iterator, bool>(* erase_fn)(any &, iterator) = nullptr;
|
||||
meta_any(* get_fn)(any &, size_type) = nullptr;
|
||||
any storage{};
|
||||
};
|
||||
|
||||
|
||||
@@ -103,17 +101,15 @@ public:
|
||||
using iterator = meta_iterator;
|
||||
|
||||
/*! @brief Default constructor. */
|
||||
meta_associative_container() ENTT_NOEXCEPT
|
||||
: instance{nullptr}
|
||||
{}
|
||||
meta_associative_container() ENTT_NOEXCEPT = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a proxy object for associative containers.
|
||||
* @tparam Type Type of container to wrap.
|
||||
* @param container The container to wrap.
|
||||
* @param instance The container to wrap.
|
||||
*/
|
||||
template<typename Type>
|
||||
meta_associative_container(Type *container) ENTT_NOEXCEPT
|
||||
meta_associative_container(Type &instance) ENTT_NOEXCEPT
|
||||
: key_only_container{is_key_only_meta_associative_container_v<Type>},
|
||||
key_type_fn{&meta_associative_container_proxy<Type>::key_type},
|
||||
mapped_type_fn{&meta_associative_container_proxy<Type>::mapped_type},
|
||||
@@ -125,7 +121,7 @@ public:
|
||||
insert_fn{&meta_associative_container_proxy<Type>::insert},
|
||||
erase_fn{&meta_associative_container_proxy<Type>::erase},
|
||||
find_fn{&meta_associative_container_proxy<Type>::find},
|
||||
instance{container}
|
||||
storage{std::reference_wrapper{instance}}
|
||||
{}
|
||||
|
||||
[[nodiscard]] inline bool key_only() const ENTT_NOEXCEPT;
|
||||
@@ -146,41 +142,58 @@ private:
|
||||
meta_type(* key_type_fn)() ENTT_NOEXCEPT = nullptr;
|
||||
meta_type(* mapped_type_fn)() ENTT_NOEXCEPT = nullptr;
|
||||
meta_type(* value_type_fn)() ENTT_NOEXCEPT = nullptr;
|
||||
size_type(* size_fn)(const void *) ENTT_NOEXCEPT = nullptr;
|
||||
bool(* clear_fn)(void *) = nullptr;
|
||||
iterator(* begin_fn)(void *) = nullptr;
|
||||
iterator(* end_fn)(void *) = nullptr;
|
||||
bool(* insert_fn)(void *, meta_any, meta_any) = nullptr;
|
||||
bool(* erase_fn)(void *, meta_any) = nullptr;
|
||||
iterator(* find_fn)(void *, meta_any) = nullptr;
|
||||
void *instance{};
|
||||
size_type(* size_fn)(const any &) ENTT_NOEXCEPT = nullptr;
|
||||
bool(* clear_fn)(any &) = nullptr;
|
||||
iterator(* begin_fn)(any &) = nullptr;
|
||||
iterator(* end_fn)(any &) = nullptr;
|
||||
bool(* insert_fn)(any &, meta_any &, meta_any &) = nullptr;
|
||||
bool(* erase_fn)(any &, meta_any &) = nullptr;
|
||||
iterator(* find_fn)(any &, meta_any &) = nullptr;
|
||||
any storage{};
|
||||
};
|
||||
|
||||
|
||||
/*! @brief Opaque wrapper for values of any type. */
|
||||
class meta_any {
|
||||
enum class operation { DEREF, SEQ, ASSOC };
|
||||
enum class operation { DEREF, CDEREF, SEQ, CSEQ, ASSOC, CASSOC };
|
||||
|
||||
using vtable_type = void(const operation, meta_any &, void *);
|
||||
using vtable_type = void(const operation, const any &, void *);
|
||||
|
||||
template<typename Type>
|
||||
static void basic_vtable(const operation op, [[maybe_unused]] meta_any &from, [[maybe_unused]] void *to) {
|
||||
static void basic_vtable(const operation op, [[maybe_unused]] const any &from, [[maybe_unused]] void *to) {
|
||||
switch(op) {
|
||||
case operation::DEREF:
|
||||
if constexpr(is_meta_pointer_like_v<Type>) {
|
||||
if(auto ptr = from.cast<Type>(); ptr) {
|
||||
*static_cast<meta_any *>(to) = std::reference_wrapper{*ptr};
|
||||
}
|
||||
*static_cast<meta_any *>(to) = std::ref(*any_cast<const Type>(from));
|
||||
}
|
||||
break;
|
||||
case operation::CDEREF:
|
||||
if constexpr(is_meta_pointer_like_v<Type>) {
|
||||
*static_cast<meta_any *>(to) = std::cref(*any_cast<const Type>(from));
|
||||
}
|
||||
break;
|
||||
case operation::SEQ:
|
||||
if constexpr(has_meta_sequence_container_traits_v<Type>) {
|
||||
*static_cast<meta_sequence_container *>(to) = static_cast<Type *>(from.data());
|
||||
if(auto *instance = any_cast<Type>(&const_cast<any &>(from)); instance) {
|
||||
return *static_cast<meta_sequence_container *>(to) = *instance, void();
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
case operation::CSEQ:
|
||||
if constexpr(has_meta_sequence_container_traits_v<Type>) {
|
||||
*static_cast<meta_sequence_container *>(to) = any_cast<const Type &>(from);
|
||||
}
|
||||
break;
|
||||
case operation::ASSOC:
|
||||
if constexpr(has_meta_associative_container_traits_v<Type>) {
|
||||
*static_cast<meta_associative_container *>(to) = static_cast<Type *>(from.data());
|
||||
if(auto *instance = any_cast<Type>(&const_cast<any &>(from)); instance) {
|
||||
return *static_cast<meta_associative_container *>(to) = *instance, void();
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
case operation::CASSOC:
|
||||
if constexpr(has_meta_associative_container_traits_v<Type>) {
|
||||
*static_cast<meta_associative_container *>(to) = any_cast<const Type &>(from);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -203,8 +216,8 @@ public:
|
||||
template<typename Type, typename... Args>
|
||||
explicit meta_any(std::in_place_type_t<Type>, Args &&... args)
|
||||
: storage(std::in_place_type<Type>, std::forward<Args>(args)...),
|
||||
vtable{&basic_vtable<Type>},
|
||||
node{internal::meta_info<Type>::resolve()}
|
||||
vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>},
|
||||
node{internal::meta_info<std::remove_const_t<std::remove_reference_t<Type>>>::resolve()}
|
||||
{}
|
||||
|
||||
/**
|
||||
@@ -214,9 +227,7 @@ public:
|
||||
*/
|
||||
template<typename Type>
|
||||
meta_any(std::reference_wrapper<Type> value)
|
||||
: storage{value},
|
||||
vtable{&basic_vtable<Type>},
|
||||
node{internal::meta_info<Type>::resolve()}
|
||||
: meta_any{std::in_place_type<Type &>, &value.get()}
|
||||
{}
|
||||
|
||||
/**
|
||||
@@ -443,7 +454,14 @@ public:
|
||||
*/
|
||||
[[nodiscard]] meta_sequence_container as_sequence_container() ENTT_NOEXCEPT {
|
||||
meta_sequence_container proxy;
|
||||
vtable(operation::SEQ, *this, &proxy);
|
||||
vtable(operation::SEQ, storage, &proxy);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/*! @copydoc as_sequence_container */
|
||||
[[nodiscard]] meta_sequence_container as_sequence_container() const ENTT_NOEXCEPT {
|
||||
meta_sequence_container proxy;
|
||||
vtable(operation::CSEQ, storage, &proxy);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
@@ -453,7 +471,14 @@ public:
|
||||
*/
|
||||
[[nodiscard]] meta_associative_container as_associative_container() ENTT_NOEXCEPT {
|
||||
meta_associative_container proxy;
|
||||
vtable(operation::ASSOC, *this, &proxy);
|
||||
vtable(operation::ASSOC, storage, &proxy);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/*! @copydoc as_associative_container */
|
||||
[[nodiscard]] meta_associative_container as_associative_container() const ENTT_NOEXCEPT {
|
||||
meta_associative_container proxy;
|
||||
vtable(operation::CASSOC, storage, &proxy);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
@@ -464,7 +489,14 @@ public:
|
||||
*/
|
||||
[[nodiscard]] meta_any operator*() ENTT_NOEXCEPT {
|
||||
meta_any any{};
|
||||
vtable(operation::DEREF, *this, &any);
|
||||
vtable(operation::DEREF, storage, &any);
|
||||
return any;
|
||||
}
|
||||
|
||||
/*! @copydoc operator* */
|
||||
[[nodiscard]] meta_any operator*() const ENTT_NOEXCEPT {
|
||||
meta_any any{};
|
||||
vtable(operation::CDEREF, storage, &any);
|
||||
return any;
|
||||
}
|
||||
|
||||
@@ -482,7 +514,7 @@ public:
|
||||
* @return False if the two objects differ in their content, true otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool operator==(const meta_any &other) const {
|
||||
return (!node && !other.node) || (node && other.node && node->info == other.node->info && node->compare(storage.data(), other.storage.data()));
|
||||
return (node == other.node) && (storage == other.storage);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1671,13 +1703,13 @@ class meta_sequence_container::meta_iterator {
|
||||
friend class meta_sequence_container;
|
||||
|
||||
template<typename It>
|
||||
static void incr(meta_any any) {
|
||||
++any.cast<It &>();
|
||||
static void incr(any &ref) {
|
||||
++any_cast<It &>(ref);
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
[[nodiscard]] static meta_any deref(meta_any any) {
|
||||
return std::reference_wrapper{*any.cast<const It &>()};
|
||||
[[nodiscard]] static meta_any deref(const any &ref) {
|
||||
return std::reference_wrapper{*any_cast<const It &>(ref)};
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1709,7 +1741,7 @@ public:
|
||||
|
||||
/*! @brief Pre-increment operator. @return This iterator. */
|
||||
meta_iterator & operator++() ENTT_NOEXCEPT {
|
||||
return next_fn(as_ref(handle)), *this;
|
||||
return next_fn(handle), *this;
|
||||
}
|
||||
|
||||
/*! @brief Post-increment operator. @return This iterator. */
|
||||
@@ -1743,7 +1775,7 @@ public:
|
||||
* @return The element to which the meta pointer points.
|
||||
*/
|
||||
[[nodiscard]] reference operator*() const {
|
||||
return get_fn(as_ref(handle));
|
||||
return get_fn(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1755,9 +1787,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void(* next_fn)(meta_any);
|
||||
meta_any(* get_fn)(meta_any);
|
||||
meta_any handle;
|
||||
void(* next_fn)(any &);
|
||||
meta_any(* get_fn)(const any &);
|
||||
any handle;
|
||||
};
|
||||
|
||||
|
||||
@@ -1769,42 +1801,42 @@ struct meta_sequence_container::meta_sequence_container_proxy {
|
||||
return internal::meta_info<typename traits_type::value_type>::resolve();
|
||||
}
|
||||
|
||||
[[nodiscard]] static size_type size(const void *container) ENTT_NOEXCEPT {
|
||||
return traits_type::size(*static_cast<const Type *>(container));
|
||||
[[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
|
||||
return traits_type::size(any_cast<const Type &>(container));
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool resize(void *container, size_type sz) {
|
||||
return traits_type::resize(*static_cast<Type *>(container), sz);
|
||||
[[nodiscard]] static bool resize(any &container, size_type sz) {
|
||||
return traits_type::resize(any_cast<Type &>(container), sz);
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool clear(void *container) {
|
||||
return traits_type::clear(*static_cast<Type *>(container));
|
||||
[[nodiscard]] static bool clear(any &container) {
|
||||
return traits_type::clear(any_cast<Type &>(container));
|
||||
}
|
||||
|
||||
[[nodiscard]] static iterator begin(void *container) {
|
||||
return iterator{traits_type::begin(*static_cast<Type *>(container))};
|
||||
[[nodiscard]] static iterator begin(any &container) {
|
||||
return iterator{traits_type::begin(any_cast<Type &>(container))};
|
||||
}
|
||||
|
||||
[[nodiscard]] static iterator end(void *container) {
|
||||
return iterator{traits_type::end(*static_cast<Type *>(container))};
|
||||
[[nodiscard]] static iterator end(any &container) {
|
||||
return iterator{traits_type::end(any_cast<Type &>(container))};
|
||||
}
|
||||
|
||||
[[nodiscard]] static std::pair<iterator, bool> insert(void *container, iterator it, meta_any value) {
|
||||
[[nodiscard]] static std::pair<iterator, bool> insert(any &container, iterator it, meta_any &value) {
|
||||
if(value.allow_cast<const typename traits_type::value_type &>()) {
|
||||
auto ret = traits_type::insert(*static_cast<Type *>(container), it.handle.cast<const typename traits_type::iterator &>(), value.cast<const typename traits_type::value_type &>());
|
||||
auto ret = traits_type::insert(any_cast<Type &>(container), any_cast<const typename traits_type::iterator &>(it.handle), value.cast<const typename traits_type::value_type &>());
|
||||
return { iterator{std::move(ret.first)}, ret.second };
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] static std::pair<iterator, bool> erase(void *container, iterator it) {
|
||||
auto ret = traits_type::erase(*static_cast<Type *>(container), it.handle.cast<const typename traits_type::iterator &>());
|
||||
[[nodiscard]] static std::pair<iterator, bool> erase(any &container, iterator it) {
|
||||
auto ret = traits_type::erase(any_cast<Type &>(container), any_cast<const typename traits_type::iterator &>(it.handle));
|
||||
return { iterator{std::move(ret.first)}, ret.second };
|
||||
}
|
||||
|
||||
[[nodiscard]] static meta_any get(void *container, size_type pos) {
|
||||
return std::reference_wrapper{traits_type::get(*static_cast<Type *>(container), pos)};
|
||||
[[nodiscard]] static meta_any get(any &container, size_type pos) {
|
||||
return std::reference_wrapper{traits_type::get(any_cast<Type &>(container), pos)};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1823,7 +1855,7 @@ struct meta_sequence_container::meta_sequence_container_proxy {
|
||||
* @return The size of the wrapped container.
|
||||
*/
|
||||
[[nodiscard]] inline meta_sequence_container::size_type meta_sequence_container::size() const ENTT_NOEXCEPT {
|
||||
return size_fn(instance);
|
||||
return size_fn(storage);
|
||||
}
|
||||
|
||||
|
||||
@@ -1832,8 +1864,8 @@ struct meta_sequence_container::meta_sequence_container_proxy {
|
||||
* @param sz The new size of the container.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
inline bool meta_sequence_container::resize(size_type sz) const {
|
||||
return resize_fn(instance, sz);
|
||||
inline bool meta_sequence_container::resize(size_type sz) {
|
||||
return resize_fn(storage, sz);
|
||||
}
|
||||
|
||||
|
||||
@@ -1842,7 +1874,7 @@ inline bool meta_sequence_container::resize(size_type sz) const {
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
inline bool meta_sequence_container::clear() {
|
||||
return clear_fn(instance);
|
||||
return clear_fn(storage);
|
||||
}
|
||||
|
||||
|
||||
@@ -1851,7 +1883,7 @@ inline bool meta_sequence_container::clear() {
|
||||
* @return A meta iterator to the first element of the wrapped container.
|
||||
*/
|
||||
[[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::begin() {
|
||||
return begin_fn(instance);
|
||||
return begin_fn(storage);
|
||||
}
|
||||
|
||||
|
||||
@@ -1862,7 +1894,7 @@ inline bool meta_sequence_container::clear() {
|
||||
* container.
|
||||
*/
|
||||
[[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::end() {
|
||||
return end_fn(instance);
|
||||
return end_fn(storage);
|
||||
}
|
||||
|
||||
|
||||
@@ -1874,7 +1906,7 @@ inline bool meta_sequence_container::clear() {
|
||||
* case of success) and a bool denoting whether the insertion took place.
|
||||
*/
|
||||
inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_container::insert(iterator it, meta_any value) {
|
||||
return insert_fn(instance, it, as_ref(value));
|
||||
return insert_fn(storage, it, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -1886,7 +1918,7 @@ inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_containe
|
||||
* took place.
|
||||
*/
|
||||
inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_container::erase(iterator it) {
|
||||
return erase_fn(instance, it);
|
||||
return erase_fn(storage, it);
|
||||
}
|
||||
|
||||
|
||||
@@ -1897,7 +1929,7 @@ inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_containe
|
||||
* @return A reference to the requested element properly wrapped.
|
||||
*/
|
||||
[[nodiscard]] inline meta_any meta_sequence_container::operator[](size_type pos) {
|
||||
return get_fn(instance, pos);
|
||||
return get_fn(storage, pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -1906,32 +1938,32 @@ inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_containe
|
||||
* @return False if the proxy is invalid, true otherwise.
|
||||
*/
|
||||
[[nodiscard]] inline meta_sequence_container::operator bool() const ENTT_NOEXCEPT {
|
||||
return (instance != nullptr);
|
||||
return static_cast<bool>(storage);
|
||||
}
|
||||
|
||||
|
||||
/*! @brief Opaque iterator for meta associative containers. */
|
||||
class meta_associative_container::meta_iterator {
|
||||
template<typename It>
|
||||
static void incr(meta_any any) {
|
||||
++any.cast<It &>();
|
||||
static void incr(any &any) {
|
||||
++any_cast<It &>(any);
|
||||
}
|
||||
|
||||
template<bool KeyOnly, typename It>
|
||||
[[nodiscard]] static meta_any key(meta_any any) {
|
||||
[[nodiscard]] static meta_any key(const any &ref) {
|
||||
if constexpr(KeyOnly) {
|
||||
return *any.cast<const It &>();
|
||||
return *any_cast<const It &>(ref);
|
||||
} else {
|
||||
return any.cast<const It &>()->first;
|
||||
return any_cast<const It &>(ref)->first;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool KeyOnly, typename It>
|
||||
[[nodiscard]] static meta_any value([[maybe_unused]] meta_any any) {
|
||||
[[nodiscard]] static meta_any value([[maybe_unused]] const any &ref) {
|
||||
if constexpr(KeyOnly) {
|
||||
return meta_any{};
|
||||
} else {
|
||||
return std::reference_wrapper{any.cast<const It &>()->second};
|
||||
return std::reference_wrapper{any_cast<const It &>(ref)->second};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1967,7 +1999,7 @@ public:
|
||||
|
||||
/*! @brief Pre-increment operator. @return This iterator. */
|
||||
meta_iterator & operator++() ENTT_NOEXCEPT {
|
||||
return next_fn(as_ref(handle)), *this;
|
||||
return next_fn(handle), *this;
|
||||
}
|
||||
|
||||
/*! @brief Post-increment operator. @return This iterator. */
|
||||
@@ -2001,7 +2033,7 @@ public:
|
||||
* @return The element to which the meta pointer points.
|
||||
*/
|
||||
[[nodiscard]] reference operator*() const {
|
||||
return { key_fn(as_ref(handle)), value_fn(as_ref(handle)) };
|
||||
return { key_fn(handle), value_fn(handle) };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2013,10 +2045,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void(* next_fn)(meta_any);
|
||||
meta_any(* key_fn)(meta_any);
|
||||
meta_any(* value_fn)(meta_any);
|
||||
meta_any handle;
|
||||
void(* next_fn)(any &);
|
||||
meta_any(* key_fn)(const any &);
|
||||
meta_any(* value_fn)(const any &);
|
||||
any handle;
|
||||
};
|
||||
|
||||
|
||||
@@ -2040,29 +2072,29 @@ struct meta_associative_container::meta_associative_container_proxy {
|
||||
return internal::meta_info<typename traits_type::value_type>::resolve();
|
||||
}
|
||||
|
||||
[[nodiscard]] static size_type size(const void *container) ENTT_NOEXCEPT {
|
||||
return traits_type::size(*static_cast<const Type *>(container));
|
||||
[[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
|
||||
return traits_type::size(any_cast<const Type &>(container));
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool clear(void *container) {
|
||||
return traits_type::clear(*static_cast<Type *>(container));
|
||||
[[nodiscard]] static bool clear(any &container) {
|
||||
return traits_type::clear(any_cast<Type &>(container));
|
||||
}
|
||||
|
||||
[[nodiscard]] static iterator begin(void *container) {
|
||||
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::begin(*static_cast<Type *>(container))};
|
||||
[[nodiscard]] static iterator begin(any &container) {
|
||||
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::begin(any_cast<Type &>(container))};
|
||||
}
|
||||
|
||||
[[nodiscard]] static iterator end(void *container) {
|
||||
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::end(*static_cast<Type *>(container))};
|
||||
[[nodiscard]] static iterator end(any &container) {
|
||||
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::end(any_cast<Type &>(container))};
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool insert(void *container, meta_any key, meta_any value) {
|
||||
[[nodiscard]] static bool insert(any &container, meta_any &key, meta_any &value) {
|
||||
if(key.allow_cast<const typename traits_type::key_type &>()) {
|
||||
if constexpr(is_key_only_meta_associative_container_v<Type>) {
|
||||
return traits_type::insert(*static_cast<Type *>(container), key.cast<const typename traits_type::key_type &>());
|
||||
return traits_type::insert(any_cast<Type &>(container), key.cast<const typename traits_type::key_type &>());
|
||||
} else {
|
||||
if(value.allow_cast<const typename traits_type::mapped_type &>()) {
|
||||
return traits_type::insert(*static_cast<Type *>(container), key.cast<const typename traits_type::key_type &>(), value.cast<const typename traits_type::mapped_type &>());
|
||||
return traits_type::insert(any_cast<Type &>(container), key.cast<const typename traits_type::key_type &>(), value.cast<const typename traits_type::mapped_type &>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2070,17 +2102,17 @@ struct meta_associative_container::meta_associative_container_proxy {
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool erase(void *container, meta_any key) {
|
||||
[[nodiscard]] static bool erase(any &container, meta_any &key) {
|
||||
if(key.allow_cast<const typename traits_type::key_type &>()) {
|
||||
return traits_type::erase(*static_cast<Type *>(container), key.cast<const typename traits_type::key_type &>());
|
||||
return traits_type::erase(any_cast<Type &>(container), key.cast<const typename traits_type::key_type &>());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] static iterator find(void *container, meta_any key) {
|
||||
[[nodiscard]] static iterator find(any &container, meta_any &key) {
|
||||
if(key.allow_cast<const typename traits_type::key_type &>()) {
|
||||
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::find(*static_cast<Type *>(container), key.cast<const typename traits_type::key_type &>())};
|
||||
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::find(any_cast<Type &>(container), key.cast<const typename traits_type::key_type &>())};
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -2124,25 +2156,25 @@ struct meta_associative_container::meta_associative_container_proxy {
|
||||
|
||||
/*! @copydoc meta_sequence_container::size */
|
||||
[[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const ENTT_NOEXCEPT {
|
||||
return size_fn(instance);
|
||||
return size_fn(storage);
|
||||
}
|
||||
|
||||
|
||||
/*! @copydoc meta_sequence_container::clear */
|
||||
inline bool meta_associative_container::clear() {
|
||||
return clear_fn(instance);
|
||||
return clear_fn(storage);
|
||||
}
|
||||
|
||||
|
||||
/*! @copydoc meta_sequence_container::begin */
|
||||
[[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() {
|
||||
return begin_fn(instance);
|
||||
return begin_fn(storage);
|
||||
}
|
||||
|
||||
|
||||
/*! @copydoc meta_sequence_container::end */
|
||||
[[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
|
||||
return end_fn(instance);
|
||||
return end_fn(storage);
|
||||
}
|
||||
|
||||
|
||||
@@ -2153,7 +2185,7 @@ inline bool meta_associative_container::clear() {
|
||||
* @return A bool denoting whether the insertion took place.
|
||||
*/
|
||||
inline bool meta_associative_container::insert(meta_any key, meta_any value = {}) {
|
||||
return insert_fn(instance, as_ref(key), as_ref(value));
|
||||
return insert_fn(storage, key, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -2163,7 +2195,7 @@ inline bool meta_associative_container::insert(meta_any key, meta_any value = {}
|
||||
* @return A bool denoting whether the removal took place.
|
||||
*/
|
||||
inline bool meta_associative_container::erase(meta_any key) {
|
||||
return erase_fn(instance, as_ref(key));
|
||||
return erase_fn(storage, key);
|
||||
}
|
||||
|
||||
|
||||
@@ -2174,7 +2206,7 @@ inline bool meta_associative_container::erase(meta_any key) {
|
||||
* @return An iterator to the element with the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] inline meta_associative_container::iterator meta_associative_container::find(meta_any key) {
|
||||
return find_fn(instance, as_ref(key));
|
||||
return find_fn(storage, key);
|
||||
}
|
||||
|
||||
|
||||
@@ -2183,7 +2215,7 @@ inline bool meta_associative_container::erase(meta_any key) {
|
||||
* @return False if the proxy is invalid, true otherwise.
|
||||
*/
|
||||
[[nodiscard]] inline meta_associative_container::operator bool() const ENTT_NOEXCEPT {
|
||||
return (instance != nullptr);
|
||||
return static_cast<bool>(storage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,16 @@ template<typename Type, typename = void>
|
||||
struct has_meta_sequence_container_traits: std::false_type {};
|
||||
|
||||
|
||||
/**
|
||||
* @brief TODO
|
||||
* @tparam Type TODO
|
||||
*/
|
||||
template<typename Type>
|
||||
struct has_meta_sequence_container_traits<const Type>
|
||||
: has_meta_sequence_container_traits<Type>
|
||||
{};
|
||||
|
||||
|
||||
/*! @copydoc has_meta_sequence_container_traits */
|
||||
template<typename Type>
|
||||
struct has_meta_sequence_container_traits<Type, std::void_t<typename meta_sequence_container_traits<Type>::value_type>>
|
||||
@@ -57,6 +67,16 @@ template<typename, typename = void>
|
||||
struct has_meta_associative_container_traits: std::false_type {};
|
||||
|
||||
|
||||
/**
|
||||
* @brief TODO
|
||||
* @tparam Type TODO
|
||||
*/
|
||||
template<typename Type>
|
||||
struct has_meta_associative_container_traits<const Type>
|
||||
: has_meta_associative_container_traits<Type>
|
||||
{};
|
||||
|
||||
|
||||
/*! @copydoc has_meta_associative_container_traits */
|
||||
template<typename Type>
|
||||
struct has_meta_associative_container_traits<Type, std::void_t<typename meta_associative_container_traits<Type>::key_type>>
|
||||
@@ -81,6 +101,16 @@ template<typename, typename = void>
|
||||
struct is_key_only_meta_associative_container: std::true_type {};
|
||||
|
||||
|
||||
/**
|
||||
* @brief TODO
|
||||
* @tparam Type TODO
|
||||
*/
|
||||
template<typename Type>
|
||||
struct is_key_only_meta_associative_container<const Type>
|
||||
: is_key_only_meta_associative_container<Type>
|
||||
{};
|
||||
|
||||
|
||||
/*! @copydoc is_key_only_meta_associative_container */
|
||||
template<typename Type>
|
||||
struct is_key_only_meta_associative_container<Type, std::void_t<typename meta_associative_container_traits<Type>::mapped_type>>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "../config/config.h"
|
||||
#include "../core/any.hpp"
|
||||
#include "../core/type_info.hpp"
|
||||
#include "../core/type_traits.hpp"
|
||||
@@ -195,7 +196,7 @@ public:
|
||||
template<typename Type, typename... Args>
|
||||
explicit poly(std::in_place_type_t<Type>, Args &&... args)
|
||||
: storage{std::in_place_type<Type>, std::forward<Args>(args)...},
|
||||
vtable{poly_vtable<Concept>::template instance<Type>()}
|
||||
vtable{poly_vtable<Concept>::template instance<std::remove_const_t<std::remove_reference_t<Type>>>()}
|
||||
{}
|
||||
|
||||
/**
|
||||
@@ -205,8 +206,7 @@ public:
|
||||
*/
|
||||
template<typename Type>
|
||||
poly(std::reference_wrapper<Type> value)
|
||||
: storage{value},
|
||||
vtable{poly_vtable<Concept>::template instance<std::remove_const_t<Type>>()}
|
||||
: poly{std::in_place_type<Type &>, &value.get()}
|
||||
{}
|
||||
|
||||
/**
|
||||
@@ -316,8 +316,9 @@ public:
|
||||
* @return A poly that shares a reference to an unmanaged object.
|
||||
*/
|
||||
[[nodiscard]] friend poly as_ref(poly &other) ENTT_NOEXCEPT {
|
||||
poly ref = as_ref(std::as_const(other));
|
||||
poly ref;
|
||||
ref.storage = as_ref(other.storage);
|
||||
ref.vtable = other.vtable;
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
@@ -267,3 +267,169 @@ TEST_F(MetaContainer, StdSet) {
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, ConstSequenceContainer) {
|
||||
std::vector<int> vec{};
|
||||
entt::meta_any any{std::cref(vec)};
|
||||
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
ASSERT_FALSE(view.resize(3u));
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
|
||||
vec.push_back(42);
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
ASSERT_DEATH(view[0].cast<int &>() = 2, ".*");
|
||||
ASSERT_EQ(view[0].cast<const int &>(), 42);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, 0);
|
||||
|
||||
ASSERT_FALSE(ret.second);
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ((*it).cast<int>(), 42);
|
||||
ASSERT_EQ(++it, view.end());
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_FALSE(ret.second);
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
|
||||
ASSERT_FALSE(view.clear());
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
|
||||
std::map<int, char> map{};
|
||||
entt::meta_any any{std::cref(map)};
|
||||
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_FALSE(view.key_only());
|
||||
ASSERT_EQ(view.key_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.mapped_type(), entt::resolve<char>());
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
|
||||
map[2] = 'c';
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
ASSERT_DEATH((*view.find(2)).second.cast<char &>() = 'a', ".*");
|
||||
ASSERT_EQ((*view.find(2)).second.cast<const char &>(), 'c');
|
||||
|
||||
ASSERT_FALSE(view.insert(0, 'a'));
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
ASSERT_EQ((*view.find(2)).second.cast<char>(), 'c');
|
||||
|
||||
ASSERT_FALSE(view.erase(2));
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.find(2), view.end());
|
||||
|
||||
ASSERT_FALSE(view.clear());
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, ConstKeyOnlyAssociativeContainer) {
|
||||
std::set<int> set{};
|
||||
entt::meta_any any{std::cref(set)};
|
||||
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_TRUE(view.key_only());
|
||||
ASSERT_EQ(view.key_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.mapped_type(), entt::meta_type{});
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<int>()));
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
|
||||
set.insert(2);
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
|
||||
ASSERT_EQ((*view.find(2)).first.cast<int &>(), 2);
|
||||
ASSERT_EQ((*view.find(2)).first.cast<const int &>(), 2);
|
||||
|
||||
ASSERT_FALSE(view.insert(0));
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
|
||||
|
||||
ASSERT_FALSE(view.erase(2));
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.find(2), view.end());
|
||||
|
||||
ASSERT_FALSE(view.clear());
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, SequenceContainerConstMetaAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
ASSERT_DEATH(view[0].cast<int &>() = 2, ".*");
|
||||
ASSERT_EQ(view[0].cast<const int &>(), 42);
|
||||
};
|
||||
|
||||
std::vector<int> vec{42};
|
||||
|
||||
test(vec);
|
||||
test(std::ref(vec));
|
||||
test(std::cref(vec));
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, KeyValueAssociativeContainerConstMetaAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
|
||||
ASSERT_DEATH((*view.find(2)).second.cast<char &>() = 'a', ".*");
|
||||
ASSERT_EQ((*view.find(2)).second.cast<const char &>(), 'c');
|
||||
};
|
||||
|
||||
std::map<int, char> map{{2, 'c'}};
|
||||
|
||||
test(map);
|
||||
test(std::ref(map));
|
||||
test(std::cref(map));
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, KeyOnlyAssociativeContainerConstMetaAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<int>()));
|
||||
ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
|
||||
ASSERT_EQ((*view.find(2)).first.cast<int &>(), 2);
|
||||
ASSERT_EQ((*view.find(2)).first.cast<const int &>(), 2);
|
||||
};
|
||||
|
||||
std::set<int> set{2};
|
||||
|
||||
test(set);
|
||||
test(std::ref(set));
|
||||
test(std::cref(set));
|
||||
}
|
||||
|
||||
@@ -46,6 +46,27 @@ TEST(MetaPointerLike, DereferenceOperatorConstType) {
|
||||
ASSERT_EQ(deref.cast<const int &>(), 42);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOperatorConstAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(deref.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(deref.try_cast<const int>(), nullptr);
|
||||
ASSERT_DEATH(deref.cast<int &>() = 0, ".*");
|
||||
ASSERT_EQ(deref.cast<const int &>(), 42);
|
||||
};
|
||||
|
||||
int value = 42;
|
||||
|
||||
test(&value);
|
||||
test(&std::as_const(value));
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOperatorRawPointer) {
|
||||
int value = 0;
|
||||
entt::meta_any any{&value};
|
||||
|
||||
Reference in New Issue
Block a user