|
|
@@ -31,18 +31,27 @@ struct dynamic_sequence_container: std::false_type {};
|
|
|
template<typename Type>
|
|
|
struct dynamic_sequence_container<Type, std::void_t<decltype(&Type::clear)>>: std::true_type {};
|
|
|
|
|
|
+template<typename Type>
|
|
|
+inline constexpr bool dynamic_sequence_container_v = dynamic_sequence_container<Type>::value;
|
|
|
+
|
|
|
template<typename, typename = void>
|
|
|
struct key_only_associative_container: std::true_type {};
|
|
|
|
|
|
template<typename Type>
|
|
|
struct key_only_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {};
|
|
|
|
|
|
+template<typename Type>
|
|
|
+inline constexpr bool key_only_associative_container_v = key_only_associative_container<Type>::value;
|
|
|
+
|
|
|
template<typename, typename = void>
|
|
|
struct reserve_aware_container: std::false_type {};
|
|
|
|
|
|
template<typename Type>
|
|
|
struct reserve_aware_container<Type, std::void_t<decltype(&Type::reserve)>>: std::true_type {};
|
|
|
|
|
|
+template<typename Type>
|
|
|
+inline constexpr bool reserve_aware_container_v = reserve_aware_container<Type>::value;
|
|
|
+
|
|
|
} // namespace internal
|
|
|
|
|
|
/**
|
|
|
@@ -55,20 +64,30 @@ struct reserve_aware_container<Type, std::void_t<decltype(&Type::reserve)>>: std
|
|
|
* @tparam Type Type of underlying sequence container.
|
|
|
*/
|
|
|
template<typename Type>
|
|
|
-class basic_meta_sequence_container_traits {
|
|
|
+struct basic_meta_sequence_container_traits {
|
|
|
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Unexpected type");
|
|
|
|
|
|
- friend meta_sequence_container;
|
|
|
-
|
|
|
+ /*! @brief Unsigned integer type. */
|
|
|
using size_type = typename meta_sequence_container::size_type;
|
|
|
+ /*! @brief Meta iterator type. */
|
|
|
using iterator = typename meta_sequence_container::iterator;
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Returns the number of elements in a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @return Number of elements.
|
|
|
+ */
|
|
|
[[nodiscard]] static size_type size(const void *container) {
|
|
|
return static_cast<const Type *>(container)->size();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Clears a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @return True in case of success, false otherwise.
|
|
|
+ */
|
|
|
[[nodiscard]] static bool clear([[maybe_unused]] void *container) {
|
|
|
- if constexpr(internal::dynamic_sequence_container<Type>::value) {
|
|
|
+ if constexpr(internal::dynamic_sequence_container_v<Type>) {
|
|
|
static_cast<Type *>(container)->clear();
|
|
|
return true;
|
|
|
} else {
|
|
|
@@ -76,8 +95,14 @@ class basic_meta_sequence_container_traits {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Increases the capacity of a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param sz Desired capacity.
|
|
|
+ * @return True in case of success, false otherwise.
|
|
|
+ */
|
|
|
[[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) {
|
|
|
- if constexpr(internal::reserve_aware_container<Type>::value) {
|
|
|
+ if constexpr(internal::reserve_aware_container_v<Type>) {
|
|
|
static_cast<Type *>(container)->reserve(sz);
|
|
|
return true;
|
|
|
} else {
|
|
|
@@ -85,8 +110,14 @@ class basic_meta_sequence_container_traits {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Resizes a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param sz The new number of elements.
|
|
|
+ * @return True in case of success, false otherwise.
|
|
|
+ */
|
|
|
[[nodiscard]] static bool resize([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) {
|
|
|
- if constexpr(internal::dynamic_sequence_container<Type>::value) {
|
|
|
+ if constexpr(internal::dynamic_sequence_container_v<Type>) {
|
|
|
static_cast<Type *>(container)->resize(sz);
|
|
|
return true;
|
|
|
} else {
|
|
|
@@ -94,6 +125,12 @@ class basic_meta_sequence_container_traits {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Returns a possibly const iterator to the beginning.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param as_const True for const-only containers, false otherwise.
|
|
|
+ * @param it The meta iterator to rebind the underlying iterator to.
|
|
|
+ */
|
|
|
static void begin(const void *container, const bool as_const, iterator &it) {
|
|
|
if(as_const) {
|
|
|
it.rebind(static_cast<const Type *>(container)->begin());
|
|
|
@@ -102,6 +139,12 @@ class basic_meta_sequence_container_traits {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Returns a possibly const iterator to the end.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param as_const True for const-only containers, false otherwise.
|
|
|
+ * @param it The meta iterator to rebind the underlying iterator to.
|
|
|
+ */
|
|
|
static void end(const void *container, const bool as_const, iterator &it) {
|
|
|
if(as_const) {
|
|
|
it.rebind(static_cast<const Type *>(container)->end());
|
|
|
@@ -110,8 +153,16 @@ class basic_meta_sequence_container_traits {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Assigns one element to a container and constructs its object from
|
|
|
+ * a given opaque instance.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param elem An opaque instance of the object to construct.
|
|
|
+ * @param it The meta iterator to rebind the underlying iterator to.
|
|
|
+ * @return True in case of success, false otherwise.
|
|
|
+ */
|
|
|
[[nodiscard]] static bool insert([[maybe_unused]] void *container, [[maybe_unused]] meta_any &elem, [[maybe_unused]] iterator &it) {
|
|
|
- if constexpr(internal::dynamic_sequence_container<Type>::value) {
|
|
|
+ if constexpr(internal::dynamic_sequence_container_v<Type>) {
|
|
|
// this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
|
|
|
if(elem.allow_cast<typename Type::const_reference>() || elem.allow_cast<typename Type::value_type>()) {
|
|
|
auto *const non_const = any_cast<typename Type::iterator>(&it.base());
|
|
|
@@ -124,8 +175,14 @@ class basic_meta_sequence_container_traits {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Erases an element from a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param it An opaque iterator to the element to erase.
|
|
|
+ * @return True in case of success, false otherwise.
|
|
|
+ */
|
|
|
[[nodiscard]] static bool erase([[maybe_unused]] void *container, [[maybe_unused]] iterator &it) {
|
|
|
- if constexpr(internal::dynamic_sequence_container<Type>::value) {
|
|
|
+ if constexpr(internal::dynamic_sequence_container_v<Type>) {
|
|
|
auto *const non_const = any_cast<typename Type::iterator>(&it.base());
|
|
|
it.rebind(static_cast<Type *>(container)->erase(non_const ? *non_const : any_cast<const typename Type::const_iterator &>(it.base())));
|
|
|
return true;
|
|
|
@@ -140,27 +197,44 @@ class basic_meta_sequence_container_traits {
|
|
|
* @tparam Type Type of underlying associative container.
|
|
|
*/
|
|
|
template<typename Type>
|
|
|
-class basic_meta_associative_container_traits {
|
|
|
+struct basic_meta_associative_container_traits {
|
|
|
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Unexpected type");
|
|
|
|
|
|
- friend meta_associative_container;
|
|
|
-
|
|
|
- static constexpr auto key_only = internal::key_only_associative_container<Type>::value;
|
|
|
+ /*! @brief True in case of key-only containers, false otherwise. */
|
|
|
+ static constexpr bool key_only = internal::key_only_associative_container_v<Type>;
|
|
|
|
|
|
+ /*! @brief Unsigned integer type. */
|
|
|
using size_type = typename meta_associative_container::size_type;
|
|
|
+ /*! @brief Meta iterator type. */
|
|
|
using iterator = typename meta_associative_container::iterator;
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Returns the number of elements in a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @return Number of elements.
|
|
|
+ */
|
|
|
[[nodiscard]] static size_type size(const void *container) {
|
|
|
return static_cast<const Type *>(container)->size();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Clears a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @return True in case of success, false otherwise.
|
|
|
+ */
|
|
|
[[nodiscard]] static bool clear(void *container) {
|
|
|
static_cast<Type *>(container)->clear();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Increases the capacity of a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param sz Desired capacity.
|
|
|
+ * @return True in case of success, false otherwise.
|
|
|
+ */
|
|
|
[[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) {
|
|
|
- if constexpr(internal::reserve_aware_container<Type>::value) {
|
|
|
+ if constexpr(internal::reserve_aware_container_v<Type>) {
|
|
|
static_cast<Type *>(container)->reserve(sz);
|
|
|
return true;
|
|
|
} else {
|
|
|
@@ -168,6 +242,12 @@ class basic_meta_associative_container_traits {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Returns a possibly const iterator to the beginning.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param as_const True for const-only containers, false otherwise.
|
|
|
+ * @param it The meta iterator to rebind the underlying iterator to.
|
|
|
+ */
|
|
|
static void begin(const void *container, const bool as_const, iterator &it) {
|
|
|
if(as_const) {
|
|
|
it.rebind<key_only>(static_cast<const Type *>(container)->begin());
|
|
|
@@ -176,6 +256,12 @@ class basic_meta_associative_container_traits {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Returns a possibly const iterator to the end.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param as_const True for const-only containers, false otherwise.
|
|
|
+ * @param it The meta iterator to rebind the underlying iterator to.
|
|
|
+ */
|
|
|
static void end(const void *container, const bool as_const, iterator &it) {
|
|
|
if(as_const) {
|
|
|
it.rebind<key_only>(static_cast<const Type *>(container)->end());
|
|
|
@@ -184,18 +270,38 @@ class basic_meta_associative_container_traits {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Inserts an element into a container, if the key does not exist.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param key An opaque key value of an element to insert.
|
|
|
+ * @param value An optional opaque value to insert (key-value containers).
|
|
|
+ * @return True if the insertion took place, false otherwise.
|
|
|
+ */
|
|
|
[[nodiscard]] static bool insert(void *container, const void *key, [[maybe_unused]] const void *value) {
|
|
|
- if constexpr(internal::key_only_associative_container<Type>::value) {
|
|
|
+ if constexpr(key_only) {
|
|
|
return static_cast<Type *>(container)->insert(*static_cast<const typename Type::key_type *>(key)).second;
|
|
|
} else {
|
|
|
return static_cast<Type *>(container)->emplace(*static_cast<const typename Type::key_type *>(key), *static_cast<const typename Type::mapped_type *>(value)).second;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Removes an element from a container.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param key An opaque key value of an element to remove.
|
|
|
+ * @return Number of elements removed (either 0 or 1).
|
|
|
+ */
|
|
|
[[nodiscard]] static size_type erase(void *container, const void *key) {
|
|
|
return static_cast<Type *>(container)->erase(*static_cast<const typename Type::key_type *>(key));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Finds an element with a given key.
|
|
|
+ * @param container Opaque pointer to a container of the given type.
|
|
|
+ * @param as_const True for const-only containers, false otherwise.
|
|
|
+ * @param key Opaque key value of an element to search for.
|
|
|
+ * @param it The meta iterator to rebind the underlying iterator to.
|
|
|
+ */
|
|
|
static void find(const void *container, const bool as_const, const void *key, iterator &it) {
|
|
|
if(as_const) {
|
|
|
it.rebind<key_only>(static_cast<const Type *>(container)->find(*static_cast<const typename Type::key_type *>(key)));
|