EnTT  3.10.0
container.hpp
1 #ifndef ENTT_META_CONTAINER_HPP
2 #define ENTT_META_CONTAINER_HPP
3 
4 #include <array>
5 #include <map>
6 #include <set>
7 #include <type_traits>
8 #include <unordered_map>
9 #include <unordered_set>
10 #include <vector>
11 #include "../container/dense_map.hpp"
12 #include "../container/dense_set.hpp"
13 #include "meta.hpp"
14 #include "type_traits.hpp"
15 
16 namespace entt {
17 
23 namespace internal {
24 
25 template<typename, typename = void>
26 struct is_dynamic_sequence_container: std::false_type {};
27 
28 template<typename Type>
29 struct is_dynamic_sequence_container<Type, std::void_t<decltype(&Type::reserve)>>: std::true_type {};
30 
31 template<typename, typename = void>
32 struct is_key_only_meta_associative_container: std::true_type {};
33 
34 template<typename Type>
35 struct is_key_only_meta_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {};
36 
37 template<typename Type>
38 struct basic_meta_sequence_container_traits {
39  using iterator = meta_sequence_container::iterator;
40  using size_type = std::size_t;
41 
42  [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
43  return any_cast<const Type &>(container).size();
44  }
45 
46  [[nodiscard]] static bool resize([[maybe_unused]] any &container, [[maybe_unused]] size_type sz) {
47  if constexpr(is_dynamic_sequence_container<Type>::value) {
48  if(auto *const cont = any_cast<Type>(&container); cont) {
49  cont->resize(sz);
50  return true;
51  }
52  }
53 
54  return false;
55  }
56 
57  [[nodiscard]] static iterator iter(any &container, const bool as_end) {
58  using std::begin;
59 
60  if(auto *const cont = any_cast<Type>(&container); cont) {
61  return iterator{begin(*cont), static_cast<typename iterator::difference_type>(as_end * cont->size())};
62  }
63 
64  const Type &as_const = any_cast<const Type &>(container);
65  return iterator{begin(as_const), static_cast<typename iterator::difference_type>(as_end * as_const.size())};
66  }
67 
68  [[nodiscard]] static iterator insert([[maybe_unused]] any &container, [[maybe_unused]] const std::ptrdiff_t offset, [[maybe_unused]] meta_any &value) {
69  if constexpr(is_dynamic_sequence_container<Type>::value) {
70  if(auto *const cont = any_cast<Type>(&container); cont) {
71  // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
72  if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
73  using std::begin;
74  const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
75  const auto curr = cont->insert(begin(*cont) + offset, element ? *element : value.cast<typename Type::value_type>());
76  return iterator{curr, curr - begin(*cont)};
77  }
78  }
79  }
80 
81  return {};
82  }
83 
84  [[nodiscard]] static iterator erase([[maybe_unused]] any &container, [[maybe_unused]] const std::ptrdiff_t offset) {
85  if constexpr(is_dynamic_sequence_container<Type>::value) {
86  if(auto *const cont = any_cast<Type>(&container); cont) {
87  using std::begin;
88  const auto curr = cont->erase(begin(*cont) + offset);
89  return iterator{curr, curr - begin(*cont)};
90  }
91  }
92 
93  return {};
94  }
95 };
96 
97 template<typename Type>
98 struct basic_meta_associative_container_traits {
99  using iterator = meta_associative_container::iterator;
100  using size_type = std::size_t;
101 
102  static constexpr auto key_only = is_key_only_meta_associative_container<Type>::value;
103 
104  [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
105  return any_cast<const Type &>(container).size();
106  }
107 
108  [[nodiscard]] static bool clear(any &container) {
109  if(auto *const cont = any_cast<Type>(&container); cont) {
110  cont->clear();
111  return true;
112  }
113 
114  return false;
115  }
116 
117  [[nodiscard]] static iterator iter(any &container, const bool as_end) {
118  using std::begin;
119  using std::end;
120 
121  if(auto *const cont = any_cast<Type>(&container); cont) {
122  return iterator{std::integral_constant<bool, key_only>{}, as_end ? end(*cont) : begin(*cont)};
123  }
124 
125  const auto &as_const = any_cast<const Type &>(container);
126  return iterator{std::integral_constant<bool, key_only>{}, as_end ? end(as_const) : begin(as_const)};
127  }
128 
129  [[nodiscard]] static bool insert(any &container, meta_any &key, [[maybe_unused]] meta_any &value) {
130  auto *const cont = any_cast<Type>(&container);
131 
132  if constexpr(is_key_only_meta_associative_container<Type>::value) {
133  return cont && key.allow_cast<const typename Type::key_type &>()
134  && cont->insert(key.cast<const typename Type::key_type &>()).second;
135  } else {
136  return cont && key.allow_cast<const typename Type::key_type &>() && value.allow_cast<const typename Type::mapped_type &>()
137  && cont->emplace(key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>()).second;
138  }
139  }
140 
141  [[nodiscard]] static bool erase(any &container, meta_any &key) {
142  auto *const cont = any_cast<Type>(&container);
143  return cont && key.allow_cast<const typename Type::key_type &>()
144  && (cont->erase(key.cast<const typename Type::key_type &>()) != cont->size());
145  }
146 
147  [[nodiscard]] static iterator find(any &container, meta_any &key) {
148  if(key.allow_cast<const typename Type::key_type &>()) {
149  if(auto *const cont = any_cast<Type>(&container); cont) {
150  return iterator{std::integral_constant<bool, key_only>{}, cont->find(key.cast<const typename Type::key_type &>())};
151  }
152 
153  return iterator{std::integral_constant<bool, key_only>{}, any_cast<const Type &>(container).find(key.cast<const typename Type::key_type &>())};
154  }
155 
156  return {};
157  }
158 };
159 
160 } // namespace internal
161 
172 template<typename Type, typename... Args>
173 struct meta_sequence_container_traits<std::vector<Type, Args...>>
174  : internal::basic_meta_sequence_container_traits<std::vector<Type, Args...>> {};
175 
181 template<typename Type, auto N>
182 struct meta_sequence_container_traits<std::array<Type, N>>
183  : internal::basic_meta_sequence_container_traits<std::array<Type, N>> {};
184 
191 template<typename Key, typename Value, typename... Args>
192 struct meta_associative_container_traits<std::map<Key, Value, Args...>>
193  : internal::basic_meta_associative_container_traits<std::map<Key, Value, Args...>> {};
194 
202 template<typename Key, typename Value, typename... Args>
203 struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
204  : internal::basic_meta_associative_container_traits<std::unordered_map<Key, Value, Args...>> {};
205 
211 template<typename Key, typename... Args>
212 struct meta_associative_container_traits<std::set<Key, Args...>>
213  : internal::basic_meta_associative_container_traits<std::set<Key, Args...>> {};
214 
221 template<typename Key, typename... Args>
222 struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
223  : internal::basic_meta_associative_container_traits<std::unordered_set<Key, Args...>> {};
224 
231 template<typename Key, typename Type, typename... Args>
232 struct meta_associative_container_traits<dense_map<Key, Type, Args...>>
233  : internal::basic_meta_associative_container_traits<dense_map<Key, Type, Args...>> {};
234 
240 template<typename Type, typename... Args>
242  : internal::basic_meta_associative_container_traits<dense_set<Type, Args...>> {};
243 
244 } // namespace entt
245 
246 #endif
Associative container for key-value pairs with unique keys.
Definition: dense_map.hpp:265
Associative container for unique objects of a given type.
Definition: dense_set.hpp:229
meta_iterator iterator
Meta iterator type.
Definition: meta.hpp:85
meta_iterator iterator
Meta iterator type.
Definition: meta.hpp:36
EnTT default namespace.
Definition: dense_map.hpp:22
basic_any<> any
Alias declaration for the most common use case.
Definition: fwd.hpp:17
Traits class template to be specialized to enable support for meta associative containers.
Definition: type_traits.hpp:28
Traits class template to be specialized to enable support for meta sequence containers.
Definition: type_traits.hpp:21