meta: container traits not required for const T

This commit is contained in:
Michele Caini
2020-12-23 12:27:46 +01:00
parent ed448cb99f
commit c99e859978
3 changed files with 106 additions and 225 deletions

View File

@@ -34,7 +34,9 @@ struct meta_container_traits: public Trait<Container>... {};
template<typename Container>
struct basic_container {
/*! @brief Iterator type of the container. */
using iterator = std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator>;
using iterator = typename Container::iterator;
/*! @brief Iterator type of the container. */
using const_iterator = typename Container::const_iterator;
/*! @brief Unsigned integer type. */
using size_type = typename Container::size_type;
/*! @brief Value type of the container. */
@@ -58,6 +60,11 @@ struct basic_container {
return cont.begin();
}
/*! @copydoc begin */
[[nodiscard]] static const_iterator cbegin(const Container &cont) {
return cont.begin();
}
/**
* @brief Returns an iterator past the last element of the given container.
* @param cont The container for which to return the iterator.
@@ -66,6 +73,11 @@ struct basic_container {
[[nodiscard]] static iterator end(Container &cont) {
return cont.end();
}
/*! @copydoc end */
[[nodiscard]] static const_iterator cend(const Container &cont) {
return cont.end();
}
};
@@ -85,7 +97,12 @@ struct basic_associative_container {
* @param key The key of the element to search.
* @return An iterator to the element with the given key, if any.
*/
[[nodiscard]] static std::conditional_t<std::is_const_v<Container>, typename Container::const_iterator, typename Container::iterator> find(Container &cont, const key_type &key) {
[[nodiscard]] static typename Container::iterator find(Container &cont, const key_type &key) {
return cont.find(key);
}
/*! @copydoc find */
[[nodiscard]] static typename Container::const_iterator cfind(const Container &cont, const key_type &key) {
return cont.find(key);
}
};
@@ -103,11 +120,7 @@ struct basic_dynamic_container {
* @return True in case of success, false otherwise.
*/
[[nodiscard]] static bool clear([[maybe_unused]] Container &cont) {
if constexpr(std::is_const_v<Container>) {
return false;
} else {
return cont.clear(), true;
}
return cont.clear(), true;
}
};
@@ -125,12 +138,8 @@ struct basic_dynamic_associative_container {
* @return A bool denoting whether the removal took place.
*/
[[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;
}
const auto sz = cont.size();
return cont.erase(key) != sz;
}
};
@@ -148,7 +157,12 @@ struct basic_sequence_container {
* @param pos The position of the element to return.
* @return A reference to the requested element.
*/
[[nodiscard]] static constness_as_t<typename Container::value_type, Container> & get(Container &cont, typename Container::size_type pos) {
[[nodiscard]] static typename Container::value_type & get(Container &cont, typename Container::size_type pos) {
return cont[pos];
}
/*! @copydoc get */
[[nodiscard]] static const typename Container::value_type & cget(const Container &cont, typename Container::size_type pos) {
return cont[pos];
}
};
@@ -167,11 +181,7 @@ struct dynamic_associative_key_only_container {
* @return A bool denoting whether the insertion took place.
*/
[[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;
}
return cont.insert(key).second;
}
};
@@ -190,11 +200,7 @@ struct dynamic_associative_key_value_container {
* @return A bool denoting whether the insertion took place.
*/
[[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;
}
return cont.insert(std::make_pair(key, value)).second;
}
};
@@ -213,11 +219,7 @@ struct dynamic_sequence_container {
* @return True in case of success, false otherwise.
*/
[[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;
}
return cont.resize(sz), true;
}
/**
@@ -229,13 +231,8 @@ struct dynamic_sequence_container {
* @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<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 };
}
[[nodiscard]] static std::pair<typename Container::iterator, bool> insert([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it, [[maybe_unused]] const typename Container::value_type &value) {
return { cont.insert(it, value), true };
}
/**
@@ -247,13 +244,8 @@ struct dynamic_sequence_container {
* element (in case of success) and a bool denoting whether the insertion
* took place.
*/
[[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 };
}
[[nodiscard]] static std::pair<typename Container::iterator, bool> erase([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it) {
return { cont.erase(it), true };
}
};
@@ -285,8 +277,7 @@ 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<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 &) {
[[nodiscard]] static std::pair<typename Container::iterator, bool> insert(const Container &, typename Container::const_iterator, const typename Container::value_type &) {
return { {}, false };
}
@@ -295,8 +286,7 @@ 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<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>) {
[[nodiscard]] static std::pair<typename Container::iterator, bool> erase(const Container &, typename Container::const_iterator) {
return { {}, false };
}
};
@@ -319,23 +309,6 @@ 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.
@@ -352,22 +325,6 @@ 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.
@@ -390,28 +347,6 @@ 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.
@@ -435,29 +370,6 @@ 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.
@@ -476,24 +388,6 @@ 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.
@@ -513,25 +407,6 @@ 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
>
{};
}

View File

@@ -49,7 +49,7 @@ public:
* @param instance The container to wrap.
*/
template<typename Type>
meta_sequence_container(Type &instance) ENTT_NOEXCEPT
meta_sequence_container(std::in_place_type_t<Type>, any 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},
@@ -59,7 +59,7 @@ 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},
storage{std::reference_wrapper{instance}}
storage{std::move(instance)}
{}
[[nodiscard]] inline meta_type value_type() const ENTT_NOEXCEPT;
@@ -109,7 +109,7 @@ public:
* @param instance The container to wrap.
*/
template<typename Type>
meta_associative_container(Type &instance) ENTT_NOEXCEPT
meta_associative_container(std::in_place_type_t<Type>, any 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},
@@ -121,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},
storage{std::reference_wrapper{instance}}
storage{std::move(instance)}
{}
[[nodiscard]] inline bool key_only() const ENTT_NOEXCEPT;
@@ -164,7 +164,7 @@ class meta_any {
switch(op) {
case operation::DEREF:
if constexpr(is_meta_pointer_like_v<Type>) {
*static_cast<meta_any *>(to) = std::ref(*any_cast<const Type>(from));
*static_cast<meta_any *>(to) = std::reference_wrapper{*any_cast<const Type>(from)};
}
break;
case operation::CDEREF:
@@ -174,26 +174,22 @@ class meta_any {
break;
case operation::SEQ:
if constexpr(has_meta_sequence_container_traits_v<Type>) {
if(auto *instance = any_cast<Type>(&const_cast<any &>(from)); instance) {
return *static_cast<meta_sequence_container *>(to) = *instance, void();
}
*static_cast<meta_sequence_container *>(to) = { std::in_place_type<Type>, as_ref(const_cast<any &>(from)) };
}
[[fallthrough]];
break;
case operation::CSEQ:
if constexpr(has_meta_sequence_container_traits_v<Type>) {
*static_cast<meta_sequence_container *>(to) = any_cast<const Type &>(from);
*static_cast<meta_sequence_container *>(to) = { std::in_place_type<Type>, as_ref(from) };
}
break;
case operation::ASSOC:
if constexpr(has_meta_associative_container_traits_v<Type>) {
if(auto *instance = any_cast<Type>(&const_cast<any &>(from)); instance) {
return *static_cast<meta_associative_container *>(to) = *instance, void();
}
*static_cast<meta_associative_container *>(to) = { std::in_place_type<Type>, as_ref(const_cast<any &>(from)) };
}
[[fallthrough]];
break;
case operation::CASSOC:
if constexpr(has_meta_associative_container_traits_v<Type>) {
*static_cast<meta_associative_container *>(to) = any_cast<const Type &>(from);
*static_cast<meta_associative_container *>(to) = { std::in_place_type<Type>, as_ref(from) };
}
break;
}
@@ -1812,24 +1808,40 @@ struct meta_sequence_container::meta_sequence_container_proxy {
}
[[nodiscard]] static bool resize(any &container, size_type sz) {
return traits_type::resize(any_cast<Type &>(container), sz);
if(auto *cont = any_cast<Type>(&container); cont) {
return traits_type::resize(*cont, sz);
}
return false;
}
[[nodiscard]] static bool clear(any &container) {
return traits_type::clear(any_cast<Type &>(container));
if(auto *cont = any_cast<Type>(&container); cont) {
return traits_type::clear(*cont);
}
return false;
}
[[nodiscard]] static iterator begin(any &container) {
return iterator{traits_type::begin(any_cast<Type &>(container))};
if(auto *cont = any_cast<Type>(&container); cont) {
return iterator{traits_type::begin(*cont)};
}
return iterator{traits_type::cbegin(any_cast<const Type &>(container))};
}
[[nodiscard]] static iterator end(any &container) {
return iterator{traits_type::end(any_cast<Type &>(container))};
if(auto *cont = any_cast<Type>(&container); cont) {
return iterator{traits_type::end(*cont)};
}
return iterator{traits_type::cend(any_cast<const Type &>(container))};
}
[[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(any_cast<Type &>(container), any_cast<const typename traits_type::iterator &>(it.handle), value.cast<const typename traits_type::value_type &>());
if(auto *cont = any_cast<Type>(&container); cont && value.allow_cast<const typename traits_type::value_type &>()) {
auto ret = traits_type::insert(*cont, 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 };
}
@@ -1837,12 +1849,20 @@ struct meta_sequence_container::meta_sequence_container_proxy {
}
[[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 };
if(auto *cont = any_cast<Type>(&container); cont) {
auto ret = traits_type::erase(*cont, any_cast<const typename traits_type::iterator &>(it.handle));
return { iterator{std::move(ret.first)}, ret.second };
}
return {};
}
[[nodiscard]] static meta_any get(any &container, size_type pos) {
return std::reference_wrapper{traits_type::get(any_cast<Type &>(container), pos)};
if(auto *cont = any_cast<Type>(&container); cont) {
return std::reference_wrapper{traits_type::get(*cont, pos)};
}
return std::reference_wrapper{traits_type::cget(any_cast<const Type &>(container), pos)};
}
};
@@ -2078,24 +2098,36 @@ struct meta_associative_container::meta_associative_container_proxy {
}
[[nodiscard]] static bool clear(any &container) {
return traits_type::clear(any_cast<Type &>(container));
if(auto *cont = any_cast<Type>(&container); cont) {
return traits_type::clear(*cont);
}
return false;
}
[[nodiscard]] static iterator begin(any &container) {
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::begin(any_cast<Type &>(container))};
if(auto *cont = any_cast<Type>(&container); cont) {
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::begin(*cont)};
}
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cbegin(any_cast<const Type &>(container))};
}
[[nodiscard]] static iterator end(any &container) {
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::end(any_cast<Type &>(container))};
if(auto *cont = any_cast<Type>(&container); cont) {
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::end(*cont)};
}
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cend(any_cast<const Type &>(container))};
}
[[nodiscard]] static bool insert(any &container, meta_any &key, meta_any &value) {
if(key.allow_cast<const typename traits_type::key_type &>()) {
if(auto *cont = any_cast<Type>(&container); cont && key.allow_cast<const typename traits_type::key_type &>()) {
if constexpr(is_key_only_meta_associative_container_v<Type>) {
return traits_type::insert(any_cast<Type &>(container), key.cast<const typename traits_type::key_type &>());
return traits_type::insert(*cont, key.cast<const typename traits_type::key_type &>());
} else {
if(value.allow_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 &>());
return traits_type::insert(*cont, key.cast<const typename traits_type::key_type &>(), value.cast<const typename traits_type::mapped_type &>());
}
}
}
@@ -2104,8 +2136,8 @@ struct meta_associative_container::meta_associative_container_proxy {
}
[[nodiscard]] static bool erase(any &container, meta_any &key) {
if(key.allow_cast<const typename traits_type::key_type &>()) {
return traits_type::erase(any_cast<Type &>(container), key.cast<const typename traits_type::key_type &>());
if(auto *cont = any_cast<Type>(&container); cont && key.allow_cast<const typename traits_type::key_type &>()) {
return traits_type::erase(*cont, key.cast<const typename traits_type::key_type &>());
}
return false;
@@ -2113,7 +2145,11 @@ struct meta_associative_container::meta_associative_container_proxy {
[[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(any_cast<Type &>(container), key.cast<const typename traits_type::key_type &>())};
if(auto *cont = any_cast<Type>(&container); cont) {
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::find(*cont, key.cast<const typename traits_type::key_type &>())};
}
return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cfind(any_cast<const Type &>(container), key.cast<const typename traits_type::key_type &>())};
}
return {};

View File

@@ -33,16 +33,6 @@ 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>>
@@ -67,16 +57,6 @@ 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>>
@@ -101,16 +81,6 @@ 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>>