Compare commits

..

2581 Commits

Author SHA1 Message Date
Michele Caini
76298bc26a update single include file 2022-11-09 12:13:00 +01:00
Michele Caini
7c84ce666e sigh: rollback some changes that apparently create issues with (very old) compilers (ie clang 6) 2022-10-26 12:37:46 +02:00
Michele Caini
a02a7c67cb doc: fix typo 2022-10-26 11:53:43 +02:00
Michele Caini
2bb913b898 any: suppress warnings C4706 due to asserts 2022-10-26 10:57:58 +02:00
Michele Caini
94a8bb57dd doc: review resource.md 2022-10-26 10:50:31 +02:00
Michele Caini
f06852b5c2 doc: fixed typos 2022-10-25 14:50:18 +02:00
Michele Caini
fb14d26015 config: refine the ENTT_ASSERT vs ENTT_ASSERT_CONSTEXPR work 2022-10-25 11:05:50 +02:00
Michele Caini
6a53c8eaca doc: review locator.md 2022-10-25 11:04:13 +02:00
Michele Caini
4a98874431 doc: review faq.md 2022-10-25 11:03:59 +02:00
Michele Caini
baf60502c6 doc: review config.md 2022-10-25 11:03:39 +02:00
Michele Caini
2a01b78b32 any: forward/centralize requests internally 2022-10-24 14:38:55 +02:00
Michele Caini
b02e4efe4d doc: updated links (and thanks @Naios for these) 2022-10-24 12:20:20 +02:00
Michele Caini
3c8f6d2831 doc: minor changes 2022-10-24 11:53:23 +02:00
Michele Caini
95b443af16 tuple: is_tuple[_v] implementation 2022-10-24 11:15:34 +02:00
Michele Caini
b54766d2b4 sigh: small cleanup 2022-10-23 11:42:19 +02:00
Michele Caini
25929d6188 doc: ENTT_ASSERT_CONSTEXPR 2022-10-22 19:10:48 +02:00
Michele Caini
4398c962e7 memory:
* use ENTT_ASSERT_CONSTEXPR
* turn the power-of-two toolset into a constexpr one as it ought to be
2022-10-22 19:10:40 +02:00
Michele Caini
fe8919c540 config: introduce ENTT_ASSERT_CONSTEXPR to facilitate extreme customizations 2022-10-22 19:08:13 +02:00
Michele Caini
bdaeef856d delegate: just an extra safe check 2022-10-22 18:56:55 +02:00
Michele Caini
57ad7696be memory: turn the power-of-two/fast_mod toolset into a non-constexpr one 2022-10-21 11:01:18 +02:00
Michele Caini
7c58c83ee0 memory: review propagate_on_container_swap 2022-10-21 10:57:37 +02:00
Michele Caini
dd7aaa30ca organizer: minor changes 2022-10-20 15:34:57 +02:00
Michele Caini
76f95945fc registry: better use of entt:: to avoid ambiguities 2022-10-20 09:36:51 +02:00
Michele Caini
869836ba79 registry: use allocator to allocate_shared groups with uses-allocator policy 2022-10-20 09:10:20 +02:00
Michele Caini
2358552c27 *: internal review of some traits usage 2022-10-19 12:08:41 +02:00
Michele Caini
e22ea5e189 meta: minor changes 2022-10-18 11:03:03 +02:00
Michele Caini
496fefdd01 meta: favor top-level conversion functions over bases lookup 2022-10-18 10:54:31 +02:00
Michele Caini
26f85050c1 any: debug-only check to detect nasty bugs in the client code, if any 2022-10-18 10:53:51 +02:00
Michele Caini
d478b5bc6a test: minor changes to avoid UBs 2022-10-18 10:50:16 +02:00
Michele Caini
c8337e529e natvis: review a bunch of definitions 2022-10-17 09:54:13 +02:00
Michele Caini
f0995297cf emitter: update destructor check on derived type 2022-10-17 09:53:27 +02:00
Michele Caini
b395df0f56 doc: cleanup 2022-10-14 19:05:42 +02:00
Michele Caini
69a6cc6656 meta: better doc, minor changes to propagate the context to the meta handles 2022-10-14 18:52:05 +02:00
Michele Caini
bf73216a76 meta: minor changes 2022-10-14 17:01:54 +02:00
Michele Caini
621860718b meta: rebind elements to the right context upon invocation if possible 2022-10-14 15:40:31 +02:00
Michele Caini
c34c5da277 meta: minor changes 2022-10-14 14:31:55 +02:00
Michele Caini
8dcabba31b meta: clarify utilities behavior with regard to context, instances and arguments 2022-10-14 12:24:25 +02:00
Michele Caini
294064f11f meta: args are always rebinded to the right context (with non-regression tests) 2022-10-14 11:47:27 +02:00
Michele Caini
d125229312 doc: more about the new meta context rework 2022-10-14 11:46:35 +02:00
Michele Caini
11c1e23a91 meta: context aware copy/move ctor for meta_any 2022-10-14 08:49:44 +02:00
Michele Caini
82bc2e1fe4 test: no need to test mixing meta contexts actually, dropped the todo 2022-10-13 13:12:55 +02:00
Michele Caini
92a00f591d test: context aware meta handle 2022-10-13 11:15:48 +02:00
Michele Caini
04716a7fde meta: minor changes 2022-10-13 09:38:22 +02:00
Michele Caini
b6155080b2 test: a few more tests for meta_handle 2022-10-13 09:37:13 +02:00
Michele Caini
0a61de4a09 test: context aware meta_any 2022-10-13 09:33:43 +02:00
Michele Caini
7121da100a test: context aware meta sequence containers 2022-10-13 09:24:20 +02:00
Michele Caini
7bee969ebf test: context aware meta pointers (dereferencing picks the type from the right context) 2022-10-13 09:12:45 +02:00
Michele Caini
4a0a534796 test: context aware forward_as_meta 2022-10-13 09:09:11 +02:00
Michele Caini
a0041d9062 meta: resolve an ambiguity and avoid redundant default ctors (win-win) 2022-10-13 08:59:16 +02:00
Michele Caini
3dd768bb9b meta: context aware meta template 2022-10-12 19:02:30 +02:00
Michele Caini
2a307a681f test: context aware meta prop 2022-10-12 18:30:21 +02:00
Michele Caini
dd1211d021 meta: combine enable_if_t and a meta policy detection utility to avoid API changes 2022-10-12 16:06:25 +02:00
Michele Caini
09a600d68a meta: propagate API changes to the internal functions 2022-10-12 15:36:31 +02:00
Michele Caini
7c25b46513 test: minor changes 2022-10-12 15:14:58 +02:00
Michele Caini
dc42486de8 test: drop redundant using namespace 2022-10-12 14:57:46 +02:00
Michele Caini
36411faf43 test: context aware meta dtor 2022-10-12 14:56:27 +02:00
Michele Caini
a9cd565d65 test: context aware meta conv 2022-10-12 12:49:39 +02:00
Michele Caini
0adbb0ad16 test: context aware meta ctor 2022-10-12 12:43:58 +02:00
Michele Caini
db31f77d63 test: context aware meta func 2022-10-12 12:22:26 +02:00
Michele Caini
c275afef28 test: context aware meta data 2022-10-12 12:16:35 +02:00
Michele Caini
4bad4f3067 test: context aware meta bases 2022-10-12 10:28:41 +02:00
Michele Caini
d2048c037a test: bare minimum tests for meta types from different contexts 2022-10-12 10:04:28 +02:00
Michele Caini
2a39717893 test: add all desired tests for meta context support 2022-10-12 09:59:03 +02:00
Michele Caini
49c2ae0e77 test: context aware meta resolve 2022-10-12 09:58:20 +02:00
Michele Caini
869c18f150 test: prepare to test meta context support 2022-10-12 09:57:58 +02:00
Michele Caini
d79cb5ca98 meta: turn meta_handle into a context aware wrapper 2022-10-11 15:24:23 +02:00
Michele Caini
acc6390312 meta: drop make_meta, unfortunately it doesn't fit well with the context aware design 2022-10-11 14:56:25 +02:00
Michele Caini
2e59fbbccc meta:
* review pending functions to make them context aware if they aren't already
* suppress a meta_associative_container::insert warning (rvalue-to-lvalue binding)
2022-10-11 14:40:16 +02:00
Michele Caini
bec0037797 meta: fully context aware meta_any 2022-10-11 12:20:25 +02:00
Michele Caini
d08c7ddb58 meta: review meta_associative_container::insert/::erase 2022-10-11 12:11:54 +02:00
Michele Caini
696681fefa meta: context aware meta associative container 2022-10-11 11:53:17 +02:00
Michele Caini
5f9faf7a32 meta: context aware meta sequence container 2022-10-11 11:14:22 +02:00
Michele Caini
f160503aaf meta: unroll meta_type::forward_to_bases to return always scoped elements 2022-10-11 11:09:33 +02:00
Michele Caini
b1e9f75a28 meta: meta_type::construct always returns scoped meta_any objects 2022-10-11 11:01:50 +02:00
Michele Caini
91da98353d meta: keep track of the pending changes 2022-10-11 10:28:48 +02:00
Michele Caini
bc86ceb707 meta: drop resolve trampoline function, no longer required 2022-10-10 18:13:59 +02:00
Michele Caini
0baf316e5f meta: add partial support for meta contexts to meta containers 2022-10-10 18:13:20 +02:00
Michele Caini
082605f9d3 meta: prepare meta containers to support context injection 2022-10-10 18:03:30 +02:00
Michele Caini
0fdd7d7a3a meta: meta_any::allow_cast returns a scoped value now 2022-10-10 16:46:43 +02:00
Michele Caini
eee59e6af9 meta: track pending changes as much as possible 2022-10-10 16:46:43 +02:00
Michele Caini
223a8628e3 meta: meta_any::allow_cast propagates the context now 2022-10-10 16:46:42 +02:00
Michele Caini
c0bb603210 meta: meta_any::operator* propagates the context now 2022-10-10 16:46:42 +02:00
Michele Caini
2981d8746a meta: avoid returning contex-less meta_any from meta objects 2022-10-10 16:46:42 +02:00
Michele Caini
c06280894b meta: make internal meta_invoke accept meta contexts and use them properly 2022-10-10 16:46:42 +02:00
Michele Caini
2f2bdcac4d meta:
* make meta_getter use properly meta contexts
* remove the meta context from the argument list of meta setters (not required)
2022-10-10 16:46:42 +02:00
Michele Caini
2739964a1f meta: make meta_dispatch support and use meta contexts 2022-10-10 16:46:42 +02:00
Michele Caini
c3a2a44830 meta: drop useless [[maybe_unused]] 2022-10-10 16:46:42 +02:00
Michele Caini
37a2c3b76c meta: make meta_construct support and use meta contexts 2022-10-10 16:46:42 +02:00
Michele Caini
146a7b2aa3 meta: rollback redundant functions (reduce the number of generated symbols) 2022-10-10 16:46:42 +02:00
Michele Caini
7e093c951f meta:
* use different function names to disambiguate utility calls
* drop base class meta_policy for policies, no longer required
2022-10-10 16:46:42 +02:00
Michele Caini
4901188409 meta: use meta_any context aware constructors if possible 2022-10-10 16:46:42 +02:00
Michele Caini
15d78f80a6 meta: context aware constructors for meta_any 2022-10-10 16:46:42 +02:00
Michele Caini
d61dff45c1 meta: introduce meta_ctx_arg[_t] 2022-10-10 16:46:42 +02:00
Michele Caini
34abddfbbd meta: move the meta context argument to the first slot of the argument lists 2022-10-10 16:46:42 +02:00
Michele Caini
238ebe4e8f meta: try to get around invalid code that msvc accepts happily otherwise 2022-10-10 16:46:42 +02:00
Michele Caini
502accabbc meta: make default_constructor forward the context to the returned element 2022-10-10 16:46:42 +02:00
Michele Caini
9d1df1dae4 meta: make from_void forward the context to the returned element 2022-10-10 16:46:42 +02:00
Michele Caini
a39cfb9e99 meta: always forward the context to meta_type 2022-10-10 16:46:42 +02:00
Michele Caini
27d0e5f55e meta: always forward the context to meta_func 2022-10-10 16:46:42 +02:00
Michele Caini
a0e5d2c495 meta: always forward the context to meta_data 2022-10-10 16:46:42 +02:00
Michele Caini
d2c89d2a40 meta: always forward the context to meta_prop 2022-10-10 16:46:42 +02:00
Michele Caini
54f66c9094 meta: make meta_range_iterator forward the context to the returned elements 2022-10-10 16:46:42 +02:00
Michele Caini
10be00b352 meta: suppress a bunch of shadow warnings 2022-10-10 16:46:42 +02:00
Michele Caini
9032051bf7 meta: review meta_any::try_cast to use the local context 2022-10-10 16:46:42 +02:00
Michele Caini
2d2e4c784e meta: reintroduce as_ref constructor 2022-10-10 16:46:41 +02:00
Michele Caini
0d4674d8e2 meta: refined meta_conv_node definition 2022-10-10 16:46:41 +02:00
Michele Caini
ac06ad35c1 meta: added bare minimum support for contexts to forward_as_meta 2022-10-10 16:46:41 +02:00
Michele Caini
27e492d750 meta: minor changes 2022-10-10 16:46:41 +02:00
Michele Caini
f8281f2a37 meta: add bare minimum support for contexts to meta_any 2022-10-10 16:46:41 +02:00
Michele Caini
9fc717fa6e meta: track pending points for future refinement 2022-10-10 16:46:41 +02:00
Michele Caini
4a0f2f3fe9 meta: drop redundant constructors for meta_any 2022-10-10 16:46:41 +02:00
Michele Caini
ebdd4118fd meta: context aware internal try_cast 2022-10-10 16:46:41 +02:00
Michele Caini
54ae48936f meta: refine includes 2022-10-10 16:46:41 +02:00
Michele Caini
3c9045a3a8 test: avoid using the trampoline resolve function 2022-10-10 16:46:41 +02:00
Michele Caini
f80f179499 meta: small refinement 2022-10-10 16:46:41 +02:00
Michele Caini
69c6ee0675 meta: high level meta types are now context aware 2022-10-10 16:46:41 +02:00
Michele Caini
4e28d96bef meta: remove the last use of the trampoline resolve function from the meta factory 2022-10-10 16:46:41 +02:00
Michele Caini
6552cc4599 meta: refine factory.hpp as it's likely done now 2022-10-10 16:46:41 +02:00
Michele Caini
75b10cfa09 meta: make meta and meta_reset context aware 2022-10-10 16:46:41 +02:00
Michele Caini
dc394f62c6 meta: fully context aware meta factory 2022-10-10 16:46:41 +02:00
Michele Caini
ea6d6662b4 meta: make meta_ctor_node and meta_func_node fully context aware 2022-10-10 16:46:41 +02:00
Michele Caini
de3ecbdd28 meta: make meta_conv_node context aware 2022-10-10 16:46:41 +02:00
Michele Caini
e5c6559836 meta: make meta_data_node fully context aware 2022-10-10 16:46:41 +02:00
Michele Caini
0d422236d6 doc: minor changes 2022-10-10 16:46:41 +02:00
Michele Caini
199b065fe3 meta: make it compile after the last changes as it ought to be 2022-10-10 16:46:41 +02:00
Michele Caini
c46e107107 meta: try to follow my own coding style :) 2022-10-10 16:46:41 +02:00
Michele Caini
a3f66387b2 meta: further refine meta_type_node to make it context aware 2022-10-10 16:46:41 +02:00
Michele Caini
33383bd0c3 meta: try to follow my own naming convention :) 2022-10-10 16:46:41 +02:00
Michele Caini
35b8d95671 meta: make meta_type_node even more context aware 2022-10-10 16:46:40 +02:00
Michele Caini
6e254fb39d meta: make meta_type_node partially context aware 2022-10-10 16:46:40 +02:00
Michele Caini
f50a03dcb4 meta: make meta_ctor_node context aware 2022-10-10 16:46:40 +02:00
Michele Caini
71554b2c19 meta: drop temporary trampoline for meta_arg 2022-10-10 16:46:40 +02:00
Michele Caini
e7762980ec meta: make meta_ctor_node and meta_func_node partially context aware 2022-10-10 16:46:40 +02:00
Michele Caini
c62099969e meta: make meta_data_node partially context aware 2022-10-10 16:46:40 +02:00
Michele Caini
c45ee64800 meta: make meta_arg context aware 2022-10-10 16:46:40 +02:00
Michele Caini
b53c243ef7 meta: refactor context argument as the last one 2022-10-10 16:46:40 +02:00
Michele Caini
9ee084fc40 meta: make meta_template_node context aware 2022-10-10 16:46:40 +02:00
Michele Caini
9c969fb6ac meta: context aware meta_prop_node 2022-10-10 16:46:40 +02:00
Michele Caini
6a8a9c4b31 meta: context aware meta_arg_node function (with internal temporary trampoline) 2022-10-10 16:46:40 +02:00
Michele Caini
bc0233e34b meta: context aware resolve functions (with internal temporary trampoline) 2022-10-10 16:46:40 +02:00
Michele Caini
afd91b4e5a container: suppress a few shadow warnings 2022-10-10 16:46:26 +02:00
Michele Caini
50349dc2af any/meta: work around the bugs of toolset v141 to also make it happy if possible 2022-10-08 19:51:49 +02:00
Michele Caini
4b10981d75 meta: better support to rvalue references for forward_as_meta 2022-10-08 19:00:13 +02:00
Michele Caini
b16cefd534 any: better support to rvalue references for forward_as_any 2022-10-08 19:00:03 +02:00
Michele Caini
46d6625467 dispatcher: minor changes 2022-10-08 17:08:32 +02:00
Michele Caini
a1a8e134d2 doc: mino changes 2022-10-07 12:25:42 +02:00
Michele Caini
0b6bbcc6a3 signal: move connect_arg_t to fwd.hpp 2022-10-07 12:24:11 +02:00
Michele Caini
5fac237153 any: favor delegating constructors if possible 2022-10-07 12:13:17 +02:00
Michele Caini
d2cc1c880c meta: any: favor delegating constructors if possible 2022-10-07 12:09:01 +02:00
Michele Caini
ac18ad5823 any: favor delegating constructors if possible 2022-10-07 12:08:54 +02:00
Michele Caini
9ac5f6d046 meta: simplify container traits definitions 2022-10-06 19:02:32 +02:00
Michele Caini
08adb29d91 registry: also support empty queries to get and try_get (with tests) 2022-10-06 08:36:14 +02:00
Michele Caini
1721d07746 meta: drop useless [[maybe_unused]] 2022-10-06 08:27:38 +02:00
Michele Caini
9401d560b0 any: drop useless [[maybe_unused]] 2022-10-06 08:27:26 +02:00
Michele Caini
7eae8523cb container: drop useless [[maybe_unused]] 2022-10-06 08:27:12 +02:00
Michele Caini
45b5eeeaa0 doc: update doxy file (and required doxygen version) 2022-10-05 18:51:04 +02:00
Michele Caini
12b436e5b8 sigh: small changes to make doxygen happy 2022-10-05 12:20:43 +02:00
Michele Caini
534dc7e7b7 registry: allocate_shared pools to further improve the use of the allocator 2022-10-04 12:30:25 +02:00
Michele Caini
5dfac37dac dispatcher: just a comment for the future me 2022-10-04 12:29:43 +02:00
Michele Caini
f17a4e7f8e locator: just a comment for the future me 2022-10-04 12:29:22 +02:00
Michele Caini
4b586efe66 registry: use the allocator a bit more if possible 2022-10-03 16:04:42 +02:00
Michele Caini
db6dc1e21b sigh: reduce the number of instantiations and the size of the generated symbols 2022-09-30 10:29:47 +02:00
Michele Caini
da11771dab meta: drop using definitions that are pointless/no longer required 2022-09-29 15:48:43 +02:00
Michele Caini
475e3a70b0 meta: minor changes 2022-09-29 09:48:51 +02:00
Michele Caini
5255afc80d meta: drop useless scope 2022-09-28 18:14:12 +02:00
Michele Caini
7a3f59cc5d delegate: drop useless scope 2022-09-28 18:14:04 +02:00
Michele Caini
9470133e33 registry: don't pass the allocator to the fake storage 2022-09-28 12:54:21 +02:00
Michele Caini
5ab0f9e4c0 dispatcher: const assure 2022-09-27 15:08:29 +02:00
Michele Caini
ef91cd5375 registry: rollback some no longer required changes 2022-09-26 15:43:15 +02:00
Michele Caini
cd9553ca10 registry: ::storage(id) returns a pointer rather than an utterly annoying iterator 2022-09-26 15:42:57 +02:00
Michele Caini
8b27a846a6 view: avoid moving the callback with multi-type views 2022-09-23 11:06:30 +02:00
Michele Caini
9d961ad8aa view: minor changes 2022-09-23 11:00:45 +02:00
Michele Caini
0952f3ce03 view: reduce the number of symbols 2022-09-23 10:59:23 +02:00
Michele Caini
ab33111192 view/group: make ::handle [[nodiscard]] 2022-09-22 17:42:38 +02:00
Michele Caini
9a457c5aca registry: prepare to drop static storage within const assure 2022-09-22 17:42:21 +02:00
Michele Caini
4f1c86c52e view: prepare for partially working empty views 2022-09-22 17:42:15 +02:00
Michele Caini
c605e3b5a1 view: prepare for partially working empty views 2022-09-22 17:42:11 +02:00
Michele Caini
5a8c9b8a95 test: ASSERT_NO_THROW -> ASSERT_NO_FATAL_FAILURE 2022-09-22 17:42:01 +02:00
Michele Caini
2b8e9cab18 view: drop useless constexpr branch 2022-09-22 17:41:59 +02:00
Michele Caini
c3dec4b04e view: added ::refresh function to reinitialize the leading pool 2022-09-21 15:42:38 +02:00
Michele Caini
699aa5cd96 meta: rework internal function meta_arg_node 2022-09-21 14:49:54 +02:00
Michele Caini
fea0210b6e meta: support const/non-const overloads of the same function 2022-09-21 13:57:05 +02:00
Michele Caini
cf12765738 registry: pass the allocator to the pools 2022-09-20 16:04:14 +02:00
Michele Caini
17f47fbc92 storage_type[_t]/storage_for[_t]: allocator support 2022-09-20 11:01:58 +02:00
Michele Caini
1e36b6c4b6 registry: strict check on value_type for allocators 2022-09-20 10:25:29 +02:00
Michele Caini
28692fc142 registry: also adjust construction and swap orders 2022-09-19 15:03:51 +02:00
Dominic Koepke
6eff5a88f6 registry: update (and test) member destruction order (#930) 2022-09-19 13:06:37 +02:00
tocic
5742100973 doc: fix typos (#934) 2022-09-19 12:09:30 +02:00
Michele Caini
c52eea7db7 doc: update README ( thanks @Alan-FGR ) 2022-09-16 15:46:20 +02:00
Michele Caini
2f59f5a8fa meta: refine internal::meta_arg_node + code coverage 2022-09-16 10:06:56 +02:00
Michele Caini
e77fe56e8f natvis: meta 2022-09-15 14:09:50 +02:00
Michele Caini
eea1e7b1f8 meta: further reduce the number of instantiations and allocations 2022-09-15 14:09:44 +02:00
Michele Caini
b0fbccdf10 meta: minor changes 2022-09-15 10:20:29 +02:00
Michele Caini
4f3faef153 meta: remove a few pointless moves 2022-09-15 10:08:50 +02:00
Michele Caini
3ae3c82fbb meta: refine meta_construct to make it work with lambdas (+tests) 2022-09-14 16:29:11 +02:00
Michele Caini
1063fbccbe meta: const correctness 2022-09-14 16:26:14 +02:00
Michele Caini
b9e60c679a meta: added meta_function_descriptor_traits to avoid repetition and errors 2022-09-14 09:46:11 +02:00
Michele Caini
88fd79069b locator: minor changes 2022-09-14 09:22:43 +02:00
Michele Caini
ab859f7fa7 meta: review meta_base_node::cast and meta_any::try_cast to reduce their sizes 2022-09-13 15:57:44 +02:00
Michele Caini
cc4d4dfc2b meta: also make vs2017 happy if possible 2022-09-13 12:45:49 +02:00
Michele Caini
bd62e817dc meta: reduce the size of the erased conversion function 2022-09-13 12:33:14 +02:00
Michele Caini
de34a109e1 meta: internal meta_arg_node is back to its old, unsafe version 2022-09-13 12:08:25 +02:00
Michele Caini
e0e45719fa meta: minor changes 2022-09-12 10:59:08 +02:00
Michele Caini
b21b254258 meta: avoid non-standard rvalue-to-lvalue bindings :) 2022-09-12 10:57:04 +02:00
Michele Caini
ca3ef33f46 meta: further reduce the size of the resolve function 2022-09-12 10:46:53 +02:00
Michele Caini
8c4803d906 meta: minor changes 2022-09-12 10:46:52 +02:00
Michele Caini
ffb9e4b0eb meta: shrink function templates a bit 2022-09-12 10:46:49 +02:00
Michele Caini
6010dbc368 meta: pre-instantiate the details section when constructing a factory 2022-09-12 10:46:46 +02:00
Michele Caini
a6343bd152 doc: updated links (close #933) 2022-09-09 14:14:22 +02:00
Michele Caini
9e4a7f48a4 meta: try to also make clang happy 2022-09-09 12:02:57 +02:00
Michele Caini
6ad7424d4a meta: minor changes 2022-09-08 18:02:07 +02:00
Michele Caini
218fa1ba35 meta: share common code if possible 2022-09-08 15:11:09 +02:00
Michele Caini
b45db747a8 meta: review meta_arg[_node] + increase code coverage 2022-09-08 13:29:10 +02:00
Michele Caini
eedecc07fd meta: avoid tricks and whatnot with meta_arg_node 2022-09-08 10:28:49 +02:00
Michele Caini
dcea36de7a meta: try to share common code if possibile 2022-09-07 17:51:11 +02:00
Michele Caini
ed0e3f4435 meta: share common code 2022-09-07 16:17:29 +02:00
Michele Caini
8595e4bd99 meta: review meta containers to further reduce memory usage 2022-09-07 14:58:44 +02:00
Michele Caini
e31b81294d meta: minor changes for consistency 2022-09-07 14:54:34 +02:00
Michele Caini
ac6e9cf2f0 meta: further reduce the number of instantiations 2022-09-07 14:32:15 +02:00
Michele Caini
dac4ae94c0 meta: further reduce the number of instantiations 2022-09-07 12:48:40 +02:00
Michele Caini
b31b585805 natvis: update meta 2022-09-07 11:33:15 +02:00
Michele Caini
1368c56655 meta: avoid storing meta type nodes by reference in the meta factory 2022-09-07 11:32:49 +02:00
Michele Caini
6cab12a14f test: code coverage 2022-09-06 23:42:12 +02:00
Michele Caini
924a09a9c5 meta: minor changes (to suppress warnings) 2022-09-06 23:42:12 +02:00
Michele Caini
e4f6293f42 meta: use the hot/cold model with meta_type_node 2022-09-06 23:42:12 +02:00
Michele Caini
f197b32b02 meta: cleanup 2022-09-06 23:42:12 +02:00
Michele Caini
b80ab36418 meta: use the hot/cold model with meta_func_node 2022-09-06 23:42:12 +02:00
Michele Caini
d5588333f7 meta: use the hot/cold model with meta_data_node 2022-09-06 23:42:12 +02:00
Michele Caini
10755275ea meta: use the hot/cold model with meta_prop_node 2022-09-06 23:42:12 +02:00
Michele Caini
a30cecdf36 meta: use a shared_pointer to void for meta properties 2022-09-06 23:42:12 +02:00
Michele Caini
0068afa06c meta: cleanup 2022-09-06 23:42:12 +02:00
Michele Caini
38597a6499 meta: hot/cold data to allow copies of meta nodes 2022-09-06 23:42:12 +02:00
Michele Caini
65ee240e8e meta: add a test (and a fix) for a corner case of meta_reset 2022-09-06 23:42:12 +02:00
Michele Caini
336bcf4d11 test: minor changes 2022-09-06 23:42:12 +02:00
Michele Caini
ed74a4c213 meta: explicit initialization of all values of a meta object 2022-09-06 23:42:12 +02:00
Michele Caini
3e29617da8 doc: meta 2022-09-06 23:42:11 +02:00
Michele Caini
715b3e450f meta: make meta_factory<...>::type id argument required 2022-09-06 23:42:11 +02:00
Michele Caini
1ab10f3b28 meta: range iterator is an input iterator but models a random access iterator (close #927) 2022-09-06 23:42:11 +02:00
Michele Caini
304d8a80be meta: avoid warnings due to unused variables 2022-09-06 23:42:11 +02:00
Michele Caini
560a3f664e meta: drop meta_func_node::watermark, compare pointers to invoke instead 2022-09-06 23:42:11 +02:00
Michele Caini
41081204f9 tests: minor changes 2022-09-06 23:42:11 +02:00
Michele Caini
b895dfc901 nativs: review meta after the rework 2022-09-06 23:42:11 +02:00
Michele Caini
93a1d65103 meta: meta_type_node is no longer static 2022-09-06 23:42:11 +02:00
Michele Caini
443d53400d meta: decouple meta containers and meta_type_node 2022-09-06 23:42:11 +02:00
Michele Caini
9725582089 meta: use insert_or_assign rather than operator[] 2022-09-06 23:42:11 +02:00
Michele Caini
cd2634a5d4 meta: use lvalue refs to meta any to construct meta handles 2022-09-06 23:42:11 +02:00
Michele Caini
798d1a4f9e meta: add missing template keywords (love you, msvc) 2022-09-06 23:42:11 +02:00
Michele Caini
e13996f68a meta avoid shadow warnings 2022-09-06 23:42:11 +02:00
Michele Caini
1ee077d511 meta: minor internal changes (try to make all compilers happy) 2022-09-06 23:42:11 +02:00
Michele Caini
ccf301c73d test: review/minor changes 2022-09-06 23:42:11 +02:00
Michele Caini
461fe715b7 meta: decouple meta_template_node and meta_type_node 2022-09-06 23:42:11 +02:00
Michele Caini
9549bb4f4d meta: decouple meta_func_node and meta_type_node 2022-09-06 23:42:11 +02:00
Michele Caini
0215722103 meta: decouple meta_data_node and meta_type_node 2022-09-06 23:42:11 +02:00
Michele Caini
7c6606f27e meta: decouple meta_base_node and meta_type_node 2022-09-06 23:42:11 +02:00
Michele Caini
f0b10965fb meta: decouple meta_prop_node and meta_type_node 2022-09-06 23:42:10 +02:00
Michele Caini
53f2bb7701 meta: meta_func_node is no longer static 2022-09-06 23:42:10 +02:00
Michele Caini
945e61d668 meta:
* meta_prop_node is no longer static
* we can attach multiple properties at different times
* meta property keys are of type id_type only
* removed meta_factory::props (use prop instead)
* meta range returns id and meta object pairs now
* removed mera_prop::key (id returned by meta ranges)
2022-09-06 23:42:10 +02:00
Michele Caini
e74c4bb684 meta: improve internal meta_from_void function 2022-09-06 23:42:10 +02:00
Michele Caini
a8eebcb0e2 meta: make meta_range iterators return an id and meta object pair 2022-09-06 23:42:10 +02:00
Michele Caini
1581aa1cf5 meta: meta_ctor_node is no longer static 2022-09-06 23:42:10 +02:00
Michele Caini
839a2cc86d meta: removed meta_data::id 2022-09-06 23:42:10 +02:00
Michele Caini
3062114f0c meta: meta_data_node is no longer static 2022-09-06 23:42:10 +02:00
Michele Caini
ab3abf23ed meta: avoid allocations for meta_template_node 2022-09-06 23:42:10 +02:00
Michele Caini
b5a7812ab4 meta: added meta_dtor_node for consistency 2022-09-06 23:42:10 +02:00
Michele Caini
565de36155 meta: meta_base is no longer static 2022-09-06 23:42:10 +02:00
Michele Caini
c76f078834 meta: prepare for iterator based meta range 2022-09-06 23:42:10 +02:00
Michele Caini
358a9742c5 meta: removed meta_type::base(id_type) because pointless 2022-09-06 23:42:10 +02:00
Michele Caini
7f9e200cfb meta: meta_conv_node is no longer static 2022-09-06 23:42:10 +02:00
Michele Caini
a12710af70 meta: meta_template_node is no longer static 2022-09-06 23:42:10 +02:00
Michele Caini
871234ec76 any: avoid declaring nested types in an union 2022-09-06 23:41:45 +02:00
Michele Caini
0c062cc351 any: refine replacement for std aligned storage (see #919) 2022-09-06 23:09:44 +02:00
Michele Caini
67271e4672 registry: start to introduce the allocator (work in progress) 2022-09-06 09:43:34 +02:00
Michele Caini
2489a95dab registry: don't store the allocator aside anymore 2022-09-06 08:33:10 +02:00
Michele Caini
70b8bd27b8 any/poly: avoid using aligned_storage_t (deprecated - close #919) 2022-09-05 15:32:49 +02:00
Michele Caini
ee88cf16d1 any: avoid using storage_type to compute in_situ 2022-09-05 15:30:29 +02:00
Michele Caini
d83e818517 test: avoid using aligned_storage_t if possible (see #919) 2022-09-02 15:23:47 +02:00
Michele Caini
6462ceb1f5 meta: turn meta_any::operator!= into an in-class method (close #917) 2022-09-02 10:10:10 +02:00
Michele Caini
e2f8ea110a any: turn operator!= into an in-class method 2022-09-02 10:09:02 +02:00
Kyriet
f1acbbedf9 doc: add section about sorting and reverse-iterating views (#918) 2022-08-31 11:29:46 +02:00
Philipp Kurth
8510f535a5 storage: storage_iterator doesn't refer to the right specialization of component_traits (#924) 2022-08-30 12:16:52 +02:00
Michele Caini
9a97a57423 storage: test the proper use of component traits by the storage iterator 2022-08-30 12:13:57 +02:00
Michele Caini
a50cc628ec natvis: drop meta_type_node is_pointer 2022-08-29 14:30:44 +02:00
Michele Caini
dc922c9e4c storage: how the code coverage tool can be hated sometimes :) 2022-08-29 12:35:34 +02:00
Michele Caini
2f2b0cf98a test: minor changes (help the code coverage tool) 2022-08-29 12:11:55 +02:00
Michele Caini
798d5eeb86 storage: minor changes (help the code coverage tool) 2022-08-29 12:04:35 +02:00
Michele Caini
02d8cefcde locator: avoid shadow warnings 2022-08-29 11:48:17 +02:00
Michele Caini
f627593d63 build system: add explicit dependencies for plugin tests 2022-08-29 11:32:16 +02:00
Michele Caini
9aeddc2cb1 locator: lib plugin test 2022-08-29 11:25:37 +02:00
Michele Caini
6650071d24 locator: lib test 2022-08-29 11:08:03 +02:00
Michele Caini
006822c7fc build system: set PIC property for odr target explicitly 2022-08-29 09:48:23 +02:00
Michele Caini
8bed15e469 natvis: update registry snippet 2022-08-28 18:55:58 +02:00
Michele Caini
4200bb9ebb locator: ::handle and extended ::reset 2022-08-27 17:35:42 +02:00
Michele Caini
fdae346aa6 doc: typo (thanks @DNKpp) 2022-08-25 15:07:34 +02:00
Michele Caini
01acb15fab meta: avoid using traits if not needed 2022-08-22 16:58:00 +02:00
Michele Caini
3a6764a685 meta: any and meta_any catchall ctors work the same 2022-08-22 16:56:02 +02:00
Michele Caini
e2e8a575c6 *: minor changes 2022-08-22 16:35:35 +02:00
Michele Caini
7205fb63fa dense_set: minor changes 2022-08-22 16:35:32 +02:00
Michele Caini
c7b59fdc14 entity/*: minor changes 2022-08-22 16:35:28 +02:00
Michele Caini
e9a59bb014 registry: swap 2022-08-11 12:15:49 +02:00
Michele Caini
76ba063f29 registry:
* accept allocator upon construction
* no allocator-extended move ctor due to type erasure (we can't pass it to pools)
2022-08-11 11:40:57 +02:00
Michele Caini
2988a74fe4 registry: prepare allocator support (still an unused parameter) 2022-08-10 11:10:18 +02:00
Michele Caini
72bc9e3973 doc: cleanup 2022-08-10 10:13:12 +02:00
Michele Caini
31fb2bc2c3 group: basic_registry is no longer a friend class 2022-08-10 08:18:52 +02:00
Michele Caini
768f8cd74c storage mixin: prepare for cross registry mixin 2022-08-10 07:59:42 +02:00
Michele Caini
751e044ce2 sigh_storage_mixin: use the allocator as it ought to be 2022-08-10 07:57:00 +02:00
Michele Caini
3406250cf6 iwyu: cleanup 2022-08-09 18:04:38 +02:00
Michele Caini
e510bdf4f2 dot: updated includes 2022-08-09 18:02:43 +02:00
Michele Caini
fccdff05e3 dense_map: equal_range 2022-08-09 09:50:55 +02:00
Michele Caini
e530b3d6f6 dense_set: equal_range 2022-08-09 09:50:52 +02:00
Michele Caini
0f0b70be23 iwyu: use imp file rather than intrusive pragma exports 2022-08-08 10:59:27 +02:00
Michele Caini
e39f235287 test: review includes 2022-08-06 17:36:04 +02:00
Michele Caini
af5acb8d32 test: minor changes 2022-08-05 18:40:17 +02:00
Michele Caini
a2f70cb5e4 emitter: updated includes 2022-08-05 18:38:53 +02:00
Michele Caini
25d10f03bb iwyu: export all fwd includes 2022-08-05 17:47:42 +02:00
Michele Caini
85c1ad060f test: minor changes 2022-08-05 12:28:22 +02:00
Michele Caini
d9b1cc0db3 iwyu: begin/end exports directive for entt.hpp/fwd.hpp (see #777) 2022-08-05 12:28:05 +02:00
Michele Caini
34205014e9 test: review includes 2022-08-05 12:06:10 +02:00
Michele Caini
749106aa47 test: suppress iwyu warnings for odr.cpp 2022-08-05 12:05:45 +02:00
Michele Caini
b828e0295a build system: update analyzer workflow 2022-08-05 11:46:53 +02:00
Michele Caini
2345002c1c build system: add iwyu workflow (see #777) 2022-08-05 08:56:35 +02:00
Michele Caini
2ce18a47b4 cleanup TODO file 2022-08-05 08:54:20 +02:00
Michele Caini
76b380d7c0 meta: review meta_any::allow_cast 2022-08-04 15:14:43 +02:00
Michele Caini
d3244ab4da cleanup TODO file 2022-08-04 10:58:00 +02:00
Michele Caini
d06ccfb8e3 test: remove unused variable 2022-08-03 18:16:22 +02:00
Michele Caini
6f807d6f9e dense_set: added count 2022-08-03 18:10:03 +02:00
Michele Caini
2b0045e23e dense_map: added count 2022-08-03 18:09:52 +02:00
Michele Caini
57067bc362 dense_set: add max_size 2022-08-03 17:47:54 +02:00
Michele Caini
abe185c003 dense_map: add max_size 2022-08-03 17:47:45 +02:00
Michele Caini
85ca2f3562 doc: updated entity.md and README files 2022-08-03 11:24:23 +02:00
Michele Caini
3d03b01439 storage: full support for non-movable types (close #905) 2022-08-03 10:57:51 +02:00
Michele Caini
879e7d775f component: yet another piece to fully support non-movable types (see #905) 2022-08-02 14:06:35 +02:00
Michele Caini
e9dbd10db4 storage: fix cross range-erase can break when using built-in iterators (close #914) 2022-08-02 09:56:24 +02:00
Michele Caini
acc95bd9b7 doc: registry context 2022-08-02 08:41:45 +02:00
Michele Caini
504c7b5d6d registry (close #911):
* added context emplace_as
* deprecated context emplace_hint
2022-08-02 08:40:06 +02:00
Michele Caini
b20ab29d82 registry: context insert_or_assign 2022-08-02 08:35:10 +02:00
Michele Caini
95b16a0b04 sparse_set: fix cross range-erase can break when using built-in iterators (close #913) 2022-08-01 11:04:56 +02:00
Michele Caini
6ee64d1dc2 *: add a couple of <functional> because of equal_to 2022-07-29 12:06:25 +02:00
Michele Caini
83ecd2d1d9 test: suppress all death tests in release 2022-07-29 10:49:03 +02:00
Michele Caini
325a5dd353 test: utilities to suppress death tests in release 2022-07-29 10:46:15 +02:00
Michele Caini
e0ee35da61 sparse_set/storage/sigh_storage_mixin:
* prepare to support non-movable, non-copyable types
* improve destroying entities
2022-07-29 09:26:28 +02:00
Michele Caini
b3fde98020 build system: make pkg-config work with includedir as absolute paths (close #890) 2022-07-28 11:14:32 +02:00
Michele Caini
3c7c21cea3 cmake: add hand made join_paths (because we don't use cmake v3.20+ yet) 2022-07-28 11:13:12 +02:00
Michele Caini
c73d6c52bf registry context: add get, deprecate at (close #911) 2022-07-28 08:54:43 +02:00
Michele Caini
c38c1454b4 test: code coverage 2022-07-27 10:09:09 +02:00
Michele Caini
06d1d23273 test: minor changes 2022-07-27 09:48:47 +02:00
Michele Caini
4081b46302 test: clean up 2022-07-27 08:55:11 +02:00
Michele Caini
914bf49656 natvis: update emitter definition 2022-07-27 08:54:42 +02:00
Michele Caini
dc634c61c4 natvis: runtime view 2022-07-27 08:54:19 +02:00
Michele Caini
566878b29c natvis: update registry context definition 2022-07-27 08:54:03 +02:00
Michele Caini
0060479e33 cmake: remove aob workflow 2022-07-26 10:23:04 +02:00
Michele Caini
1a0d892201 doc: cleanup 2022-07-26 09:41:10 +02:00
Michele Caini
0424b63bf1 registry: decouple asserts 2022-07-26 09:41:01 +02:00
Michele Caini
de9d3c04e2 registry: remove redundant check 2022-07-25 17:08:19 +02:00
Michele Caini
b0e4a853cf view: drop redundant asserts 2022-07-25 16:35:09 +02:00
Michele Caini
ac8dfe29ae group: drop redundant asserts 2022-07-25 16:35:03 +02:00
Michele Caini
9d33a38ec4 registry: bypassing the check is possible already, remove it as a whole then 2022-07-25 15:25:06 +02:00
Michele Caini
e3076fa5d1 registry: drop useless validity check from remove 2022-07-21 17:14:59 +02:00
Michele Caini
2067b2aea6 registry: remove redundant validity check from orphan 2022-07-21 15:05:01 +02:00
Michele Caini
a14af95f9d registry: remove useless validity check from a get 2022-07-21 11:39:31 +02:00
Michele Caini
8fd2ce8d47 registry: remove useless validity check from erase 2022-07-21 10:56:53 +02:00
Michele Caini
d6edc64d65 registry: remove useless check when invoking patch 2022-07-21 10:19:36 +02:00
Michele Caini
f882158387 registry: renaming for consistency 2022-07-20 17:59:32 +02:00
Michele Caini
6f852c2dcb registry: minor changes 2022-07-20 17:59:22 +02:00
Michele Caini
e47e74fc76 registry: remove validity check from erase 2022-07-20 14:49:49 +02:00
Michele Caini
e604060369 registry: remove validity check from try_get 2022-07-20 14:47:54 +02:00
Michele Caini
80f8051c57 registry: remove validity check from patch 2022-07-20 12:53:44 +02:00
Michele Caini
612c499a3d registry: remove validity check from get 2022-07-20 12:52:11 +02:00
Michele Caini
cceffe6ac4 registry: renaming for consistency 2022-07-19 19:15:04 +02:00
Michele Caini
a74416c730 registry: remove validity check from any_of/all_of 2022-07-19 16:47:33 +02:00
Michele Caini
0830704484 container/*: minor changes 2022-07-19 15:14:08 +02:00
Michele Caini
79f7eaaf9a handle: include null as it ought to be 2022-07-19 08:08:43 +02:00
Michele Caini
389e038445 registry/context: prepare to allocator support 2022-07-18 15:18:00 +02:00
Michele Caini
8f84bd7091 emitter: allocator support 2022-07-18 14:29:31 +02:00
Michele Caini
2146e3ded9 dispatcher: minor changes 2022-07-18 14:28:59 +02:00
Michele Caini
97c0582765 emitter: cleanup/simplification 2022-07-15 08:43:44 +02:00
Michele Caini
c3f230956c organizer: cleanup/remove dependency from <algorithm> 2022-07-15 08:41:46 +02:00
Michele Caini
b914a4a93e meta: try to please all compilers (again) 2022-07-14 09:22:57 +02:00
Michele Caini
befa0fe213 doc: meta 2022-07-14 08:46:06 +02:00
Michele Caini
61ef5a44e0 meta:
* improved sequence container support for non-contiguous containers
* added support to (standard) deque as sequence containers
2022-07-14 08:45:59 +02:00
Michele Caini
131fd0d778 doc: updated readme 2022-07-14 08:43:33 +02:00
Michele Caini
8973757b43 updated TODO (gh stuff) 2022-07-13 11:48:30 +02:00
Michele Caini
14ce88730f meta: minimal (and still inefficient) support for lists as sequence containers 2022-07-13 11:48:30 +02:00
Michele Caini
84cbfb2f91 meta: use clear rather than reserve to spot dynamic sequence containers 2022-07-13 11:48:30 +02:00
Michele Caini
e8f8520251 dense_set: fix an issue when erasing movable keys 2022-07-13 11:24:40 +02:00
Michele Caini
c26558cd6d dense_map: fix an issue when erasing movable keys 2022-07-13 11:24:29 +02:00
Paolo Monteverde
71feb0516d adjacency_matrix: update allocator aware constructor (#909) 2022-07-13 11:22:20 +02:00
Michele Caini
382187089c meta: make meta_type::from_void const as it ought to be 2022-07-11 10:31:08 +02:00
Michele Caini
4faeb5c44e dispatcher: removed unused/useless code 2022-07-07 10:41:53 +02:00
Michele Caini
ac8f569280 nativs: updated meta type representation 2022-07-06 12:16:47 +02:00
Michele Caini
669420d31c meta: try to please all compilers (as usual) 2022-07-06 11:52:32 +02:00
Michele Caini
df48cc9471 meta: minor changes 2022-07-06 11:30:45 +02:00
Michele Caini
274a08070f meta: meta_type::from_void support 2022-07-06 11:30:43 +02:00
Michele Caini
c0e20825ac metx: ctx.hpp -> context.hpp 2022-07-06 11:30:40 +02:00
Michele Caini
15d821f2f8 helper: review includes 2022-07-05 08:39:48 +02:00
Michele Caini
acbd38c1ed container/entity: noexcept-ness review 2022-07-05 08:39:16 +02:00
Michele Caini
92f5f97d83 entity/*: updated includes 2022-07-05 08:36:24 +02:00
Michele Caini
1128b9de81 dispatcher: remove unused include 2022-07-04 17:46:33 +02:00
Michele Caini
fcd60467a7 memory: minor/internal changes 2022-07-04 17:46:03 +02:00
Michele Caini
2f51341633 meta: a few optimizations/improvements (size bench review) 2022-07-04 08:27:05 +02:00
Michele Caini
5799f407ae meta: minor changes 2022-07-04 08:27:02 +02:00
Michele Caini
c7a5e09c0e meta container: small changes 2022-07-04 08:26:58 +02:00
Michele Caini
3318ac2699 meta: reduce a little the number and size of vtables/fake functions 2022-07-04 08:26:53 +02:00
Michele Caini
437f1fea54 view: suppress shadow warnings 2022-07-03 12:23:08 +02:00
Michele Caini
3ab43f894f organizer: suppress shadow warnings 2022-07-03 12:23:03 +02:00
Michele Caini
86f98f40a1 test: added missing include 2022-07-03 12:22:53 +02:00
Michele Caini
655f1dd906 doc: minor changes 2022-07-01 18:56:02 +02:00
Michele Caini
243a382485 registry: drop some lambdas and calls to std:: 2022-07-01 18:09:37 +02:00
Michele Caini
4b74163306 meta: turn the meta_range class into an alias of iterable_adaptor 2022-07-01 18:09:35 +02:00
Michele Caini
50e67d7c15 view: drop <algorithm> (no longer required) 2022-07-01 16:00:47 +02:00
Michele Caini
c5afd8f589 dense_map: remove <algorithm> (no longer required) 2022-07-01 16:00:44 +02:00
Michele Caini
c6ab65d552 meta: coding style 2022-07-01 09:50:55 +02:00
Michele Caini
1a853fe145 doc: core, iterator.hpp 2022-07-01 09:18:00 +02:00
Michele Caini
72abc8e4c4 doc: minor changes 2022-07-01 09:17:49 +02:00
Michele Caini
e15ad2e21b storage: minor changes (for consistency) 2022-06-30 18:35:38 +02:00
Michele Caini
5afc5529c2 doc: runtime_view 2022-06-30 18:32:57 +02:00
Michele Caini
7eed368dc2 sparse_set: minor changes 2022-06-30 16:09:28 +02:00
Michele Caini
600303bb5b observer: derive from storage rather than using one internally 2022-06-30 15:52:43 +02:00
Michele Caini
bcfd6d1b4f runtime view: allocator support 2022-06-29 18:27:43 +02:00
Michele Caini
e65b3a790d runtime view: const/non-const support 2022-06-29 18:27:41 +02:00
Michele Caini
a28467d393 dense set/map: drop <algorithm> and save some bytes here and there 2022-06-29 18:27:25 +02:00
Michele Caini
bf13d9363d updated TODO 2022-06-29 18:27:21 +02:00
Michele Caini
ff9c472f86 registry: remove unused header 2022-06-29 18:27:17 +02:00
Michele Caini
46e601db6e natvis: print both the index and the entity for the storage representation 2022-06-29 18:27:14 +02:00
Michele Caini
d4482d0d26 oeganizer: use a flow builder under the hood 2022-06-29 18:27:11 +02:00
Michele Caini
281289c46a flow: set-with-mode function to ease the transition of the observer class 2022-06-29 18:27:09 +02:00
Michele Caini
bc85d96938 meta: remove a few lambdas 2022-06-29 18:26:12 +02:00
Michele Caini
c2475381fd meta: make meta_associative_container::erase return the number of elements removed 2022-06-29 18:25:47 +02:00
Michele Caini
6ac14f35ad doc: minor changes 2022-06-29 18:25:32 +02:00
Michele Caini
de18834c91 view: remove useless member 2022-06-24 10:51:08 +02:00
Michele Caini
fc7d28c723 test: view constructors 2022-06-24 08:55:31 +02:00
Michele Caini
7ac2ce50a0 registry: use internal type member storage_for_type 2022-06-24 08:53:45 +02:00
Michele Caini
9cf9661484 doc: minor changes 2022-06-24 08:22:51 +02:00
Michele Caini
8dbf00ad3a flow: minor changes 2022-06-23 14:43:22 +02:00
Michele Caini
e0e623fa36 doc: links 2022-06-23 08:57:34 +02:00
Michele Caini
4094669222 doc: typo 2022-06-23 08:51:12 +02:00
Michele Caini
9e19244659 flow: added a couple of [[nodiscard]] 2022-06-23 08:37:17 +02:00
Michele Caini
d41ccb6b34 doc: tabs -> spaces 2022-06-23 08:36:28 +02:00
Michele Caini
72c1da2507 view: storage based model 2022-06-22 09:07:25 +02:00
Michele Caini
2e8c5ea2de doc: typo 2022-06-22 09:05:31 +02:00
Michele Caini
65561fe431 group: minor changes 2022-06-22 09:02:37 +02:00
Michele Caini
cf401aa0b5 doc: minor changes 2022-06-22 09:00:46 +02:00
Michele Caini
9b2c9936c2 doc: dot 2022-06-21 18:30:26 +02:00
Michele Caini
e4aabc7feb adjacency_matrix: single edge iterator 2022-06-21 18:11:36 +02:00
Michele Caini
610951771e adjacency_matrix: add error messages 2022-06-21 14:31:59 +02:00
Michele Caini
f76959af63 test: suppress warnings due to unused variables 2022-06-21 14:24:49 +02:00
Michele Caini
0eb5b0437b dot: directed/undirected support 2022-06-21 12:36:23 +02:00
Michele Caini
c1ac684f9a adjacency_matrix: directed/undirected tag 2022-06-21 12:28:59 +02:00
Michele Caini
473c36aba5 adjacency_matrix:
* make swap accept the right type
* make resize work properly
2022-06-21 11:02:23 +02:00
Michele Caini
38e6722358 dot: try to also please gcc 2022-06-21 09:49:47 +02:00
Michele Caini
d2a0f86908 dot: first draft 2022-06-21 09:26:32 +02:00
Michele Caini
c6707bec97 test: handle 2022-06-20 12:49:33 +02:00
Michele Caini
5c6a11cb8f test: minor changes 2022-06-20 08:30:26 +02:00
Michele Caini
600cc5e167 handle: since it's a reference type, we don't need two overloads for storage 2022-06-20 08:27:57 +02:00
Michele Caini
c441a9ad97 handle: remove visit, use iterable objects instead 2022-06-20 08:22:57 +02:00
Michele Caini
c2d2ba29ea doc: typo 2022-06-18 16:21:37 +02:00
Michele Caini
25af23d3ff registry: minor changes 2022-06-18 16:17:25 +02:00
Michele Caini
cbd6fd8aee view: minor changes 2022-06-18 16:17:07 +02:00
Michele Caini
7a7fc20438 doc: typo (close #898) 2022-06-17 17:10:50 +02:00
Michele Caini
ca4b2b68a7 updated TODO 2022-06-17 17:01:47 +02:00
Michele Caini
f3ae553706 doc: minor changes - thanks @morbo84 2022-06-17 16:27:04 +02:00
Michele Caini
fe6696b107 graph: sync point 2022-06-17 16:06:49 +02:00
Michele Caini
3a85d0f179 doc: graph 2022-06-17 11:39:07 +02:00
Michele Caini
9845d2c87d adjacency_matrix:
* iterator review
* in_edges iterable
2022-06-17 11:36:11 +02:00
Michele Caini
ea8730c2a9 doc: typo (close #896) 2022-06-16 09:53:51 +02:00
Michele Caini
c81868f8f7 flow: removed ::tasks, added operator[] 2022-06-16 09:51:18 +02:00
Michele Caini
33d1839b75 flow: task -> bind 2022-06-16 09:37:12 +02:00
Michele Caini
df10a01af9 flow: increase code coverage, simplify the internals 2022-06-16 09:30:21 +02:00
Michele Caini
4aa40aba4c build system: try to satisfy codecov requirements 2022-06-16 09:01:01 +02:00
Michele Caini
696c94e2ea flow: suppress shadow warnings 2022-06-16 08:23:30 +02:00
Michele Caini
bc5dfb9371 graph: flow (first draft) 2022-06-16 08:11:45 +02:00
Michele Caini
88c63b941d natvis: graph 2022-06-16 07:48:41 +02:00
Michele Caini
b8e12dc42a doc: minor changes 2022-06-15 09:21:49 +02:00
Michele Caini
2974e959e5 doc:: minor changes 2022-06-15 09:11:36 +02:00
Michele Caini
67b2fc085c view: prepare to storage based model 2022-06-15 09:01:57 +02:00
Michele Caini
cb202c15a5 group: minor changes 2022-06-15 09:01:41 +02:00
Michele Caini
850abd440b doc: typo 2022-06-15 08:28:00 +02:00
Michele Caini
01d125f53d group: storage based model 2022-06-14 08:07:01 +02:00
Michele Caini
3f0572c5ce graph: class vs struct definition 2022-06-13 00:39:53 +02:00
Michele Caini
cc6c45f591 adjacency_matrix: edges -> out_edges 2022-06-04 11:40:52 +02:00
Michele Caini
8029777c4e graph: (currently directed only) adjacency_matrix 2022-06-04 10:52:28 +02:00
Michele Caini
a6171551bd input_iterator_pointer: operator* 2022-06-04 09:16:18 +02:00
Michele Caini
6bb67ab5da process: fwd file 2022-06-03 19:42:37 +02:00
Michele Caini
a31c492c83 core: iota_iterator (waiting for C++20) 2022-06-03 19:25:47 +02:00
Michele Caini
c36d5e4a9c organizer: minor changes 2022-06-03 18:56:52 +02:00
Michele Caini
17b3fc93b0 updated todo file 2022-06-01 09:42:02 +02:00
Michele Caini
d2f4ffc433 registry/storage: minor changes 2022-06-01 09:41:41 +02:00
Michele Caini
1c8a296f49 doc: minor changes 2022-06-01 09:21:43 +02:00
Michele Caini
de0e5862dd meta: use a more explicit static_cast (!! tricks some tools) 2022-05-31 10:37:04 +02:00
Michele Caini
e822b8c99e meta: minor changes 2022-05-31 10:33:27 +02:00
Michele Caini
48d767749d meta: removed redundant meta_traits::is_pointer 2022-05-31 10:23:34 +02:00
Michele Caini
fa48c76dd1 any: drop useless remove_const_t 2022-05-29 12:10:32 +02:00
Michele Caini
754fe9f4ec any: make things explicit to avoid cast to same type warnings 2022-05-29 12:09:23 +02:00
Michele Caini
1ad3adfff0 any: drop pointless cast 2022-05-29 12:03:42 +02:00
Michele Caini
0c0fd4d7f7 storage_for: minor changes 2022-05-29 10:08:07 +02:00
Michele Caini
72f5df82b2 doc: some links :) 2022-05-29 09:41:56 +02:00
Michele Caini
c7407f5b6a view:
* reduce (a lot) the number of instantiations due to tuples
* review operator|
2022-05-27 19:03:28 +02:00
Michele Caini
f57975acca view: avoid delegating constructors with tuples 2022-05-27 18:12:38 +02:00
Michele Caini
a8a0c9e571 test: minor changes 2022-05-27 16:39:54 +02:00
Michele Caini
e05277d56a registry: use storage_for[_t] 2022-05-26 11:50:31 +02:00
Michele Caini
0b1985ca7e view: use storage_for[_t] 2022-05-26 11:50:22 +02:00
Michele Caini
637764ee4e group: use storage_for[_t] 2022-05-26 08:46:53 +02:00
Michele Caini
c6e613c317 storage: storage_for[_t] utility 2022-05-26 08:25:47 +02:00
Michele Caini
aa3e769463 doc: type_list_transform 2022-05-25 23:04:15 +02:00
Michele Caini
630ba195d1 input_iterator_pointer: no reason for which it shouldn't be copyable 2022-05-25 16:51:44 +02:00
Michele Caini
13276d2f10 input_iterator_pointer: minor changes 2022-05-25 16:48:07 +02:00
Michele Caini
d59407a339 any: makes assign work for all basic_any types 2022-05-25 16:46:50 +02:00
Michele Caini
92c2fd9409 hashed_string: nit 2022-05-25 11:42:10 +02:00
Michele Caini
063e6160e0 natvis: explicit entity-component mapping 2022-05-25 11:39:42 +02:00
Michele Caini
6155a10037 doc: minor changes 2022-05-25 11:24:20 +02:00
Michele Caini
7428cb353c storage: add default entity type to storage_type 2022-05-25 10:32:40 +02:00
Michele Caini
fe3b5b03eb entity/invoke: properly decay deduced argument to avoid nasty errors with reference types 2022-05-24 14:11:19 +02:00
Michele Caini
497fb90b12 doc: updated core.md 2022-05-24 10:59:50 +02:00
Michele Caini
48ab892de1 type_traits: type_list_transform[_t] utility 2022-05-24 10:59:40 +02:00
Michele Caini
a85ad88d5a entitiy/invoke: use nth_argument_t and avoid explicitly mentioning the registry 2022-05-24 08:31:14 +02:00
Michele Caini
cf2566ff74 doc: nth_argument (core) 2022-05-23 11:47:04 +02:00
Michele Caini
619f51518a type_traits: nth_argument utility (with tests) 2022-05-23 11:46:50 +02:00
Michele Caini
b26330adab delegate: minor changes 2022-05-23 11:35:11 +02:00
Michele Caini
83009bac02 resource: remove use_count (close #889) 2022-05-21 14:18:05 +02:00
Michele Caini
8780d536c7 resource: add member function handle 2022-05-21 14:14:15 +02:00
Michele Caini
99f4134d9d resource: add type member handle_type 2022-05-21 14:12:31 +02:00
Michele Caini
ca02ab7d5d resource: add type member element_type 2022-05-21 14:11:25 +02:00
kcalbCube
dc295ca0e1 doc: add an notice about possible undefined behaviour. (#887) 2022-05-20 10:44:25 +02:00
Michele Caini
8ee91095c5 organizer: make it depend on the registry type and not the entity type 2022-05-20 09:07:32 +02:00
Michele Caini
49c7b2f8f4 entity/*: renaming things to make them clear 2022-05-19 09:00:04 +02:00
Michele Caini
5d80cf11ef helper: decouple invoke and to_entity from the registry type 2022-05-19 08:15:17 +02:00
Michele Caini
bc929bcb90 snapshot: suppress warnings/errors due to shadow template parameters 2022-05-18 15:21:35 +02:00
Michele Caini
26a3057acf handle: decouple from entity type, make it work with all registry types 2022-05-18 15:02:25 +02:00
Michele Caini
96cf0a6d02 handle: prepare for a registry oriented version 2022-05-18 11:12:53 +02:00
Michele Caini
12e773f3fb as_group/as_view: make them transparent to the registry type 2022-05-17 12:40:47 +02:00
Michele Caini
c321997591 snapshot/loader: support all types of registry (allocator oriented) 2022-05-17 12:35:45 +02:00
Michele Caini
b2d98452f1 observer: support all types of registry (allocator oriented) 2022-05-17 12:28:54 +02:00
Michele Caini
16e48aa10f storage_type_t: simplify the definition to make it work with default template arguments for storage_type 2022-05-17 12:17:44 +02:00
Michele Caini
4da85a5f4a storage_type[_t]: flip entity type and value type 2022-05-17 12:07:21 +02:00
Michele Caini
a5c9d3a809 basic_storage: flip entity type and value type 2022-05-17 11:55:53 +02:00
Michele Caini
f288ba744d test: cleanup 2022-05-17 11:35:32 +02:00
Michele Caini
ba5b85de00 storage: use storage_type_t everywhere 2022-05-16 08:59:04 +02:00
Michele Caini
bd2f412225 storage: add storage_type_t 2022-05-16 08:25:50 +02:00
Michele Caini
a86cf32f55 entity: storage_traits -> storage_type 2022-05-16 08:25:23 +02:00
Michele Caini
0c8178c753 view/group/registry: storage_type -> storage_for (prepare for storage_type_t) 2022-05-15 10:45:33 +02:00
Michele Caini
b59e06ec89 storage_traits: storage_type -> type 2022-05-13 14:11:23 +02:00
Michele Caini
10153a371b sparse_set: use null values as watchdogs 2022-05-13 12:12:48 +02:00
Michele Caini
a93c1478c0 sparse_set: check against null rather than tombstone (prepare support for enable/disable) 2022-05-13 11:10:08 +02:00
Michele Caini
215b7a19c9 test: suppress warning due to integral conversions 2022-05-12 17:51:03 +02:00
Michele Caini
14ed666b91 helper: suppress warning with gcc from to_entity 2022-05-12 17:50:13 +02:00
Michele Caini
ac1d61b2c4 sparse_set: refine the check of the bump function 2022-05-12 17:32:25 +02:00
Michele Caini
acb6e90158 sparse_set: bump doesn't allow to set a tombstone version (yet) 2022-05-12 15:58:38 +02:00
Michele Caini
d3609737f5 view: minor changes 2022-05-12 14:23:45 +02:00
Michele Caini
95b91cd7dd runtime_view: remove the dependency on the sparse set class 2022-05-12 12:43:00 +02:00
Michele Caini
affd2a3b91 registry: ::storage<T> doesn't accept const types anymore 2022-05-11 13:48:03 +02:00
Michele Caini
d392259364 TODO: cleanup 2022-05-11 07:49:37 +02:00
Michele Caini
e03f4fac64 sigh_storage_mixin: added fwd decl to entity/fwd.hpp 2022-05-11 07:49:14 +02:00
Michele Caini
538840351a natvis: updated definition for meta_type_node 2022-05-11 07:48:42 +02:00
Michele Caini
1ddad3577c registry: minor changes 2022-05-11 07:47:58 +02:00
Michele Caini
d44d1325fc meta: add meta_type::is_integral and meta_type::is_signed (close #884) 2022-05-10 14:43:08 +02:00
Michele Caini
dc07af6ad1 sigh: updated noexcept token 2022-05-09 12:16:57 +02:00
Michele Caini
c6f1809d60 sigh:
* cleanup
* conditionally noexcept
2022-05-09 12:07:28 +02:00
Michele Caini
261e73bf3e y_combinator: conditionally noexcept 2022-05-09 12:07:13 +02:00
Michele Caini
8c7d2a1e96 allocation_deleter: conditionally noexcept 2022-05-09 12:06:42 +02:00
Michele Caini
72507977bd input_iterator_pointer: conditionally noexcept 2022-05-09 12:05:56 +02:00
Michele Caini
270829f05b iterable_adaptor: constructors are conditionally noexcept now 2022-05-09 08:32:11 +02:00
Michele Caini
b92e4f7e65 iterable_adaptor: move iterators on construction 2022-05-09 08:23:51 +02:00
Michele Caini
8e890135fe compressed pair: make the full class conditionally noexcept 2022-05-06 12:25:07 +02:00
Michele Caini
a6601939d5 compressed_pair: make compressed_pair_element conditionally noexcept 2022-05-06 12:19:14 +02:00
Michele Caini
c608e735d2 test: use page size variables 2022-05-06 12:01:37 +02:00
Michele Caini
e0a1a338a5 view: security net and explicit arrays to avoid regressions 2022-05-06 09:31:23 +02:00
Michele Caini
7aa276df5a entity: oops, typo :) 2022-05-06 08:44:03 +02:00
Michele Caini
d939a72219 config: drop ENTT_NOEXCEPT[_IF] 2022-05-06 08:41:22 +02:00
Michele Caini
96fc59eee5 updated TODO 2022-05-06 08:40:33 +02:00
Michele Caini
989f8568cf helper: use the right page size in all cases 2022-05-06 08:40:17 +02:00
Michele Caini
66f451124f entity: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:37:41 +02:00
Michele Caini
e59ff47f6f core: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:30:49 +02:00
Michele Caini
b176be9ef7 meta: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:23:52 +02:00
Michele Caini
942879bbba signal: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:23:42 +02:00
Michele Caini
2065c4294f resource: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:23:30 +02:00
Michele Caini
cb02f0621c process: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:23:22 +02:00
Michele Caini
971f371eab poly: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:23:14 +02:00
Michele Caini
f21c56bd98 locator: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:23:03 +02:00
Michele Caini
363299a27d containter: prepare to remove ENTT_NOEXCEPT[_IF] 2022-05-06 08:22:55 +02:00
Michele Caini
10e74dad41 doc: drop mentions of ENTT_NOEXCEPT 2022-05-05 14:54:04 +02:00
Michele Caini
dc041b7ea0 test: cleanup/update 2022-05-05 14:53:05 +02:00
Michele Caini
584cfdf64c test: avoid using ENTT_NOEXCEPT in the test suite 2022-05-05 09:24:02 +02:00
Michele Caini
74c498cf15 doc: avoid using ENTT_NOEXCEPT in the doc 2022-05-05 09:02:38 +02:00
Michele Caini
a1e5855f2b updated TODO 2022-05-05 09:00:03 +02:00
Michele Caini
d8e5a97ef3 entity: iterator constexpr-ness review (close #883) 2022-05-04 16:18:37 +02:00
Michele Caini
96804b0b28 meta: constexpr all the way (see #883) 2022-05-04 16:10:37 +02:00
Michele Caini
b0d69c50da resource_cache: constexpr all the way (see #883) 2022-05-04 16:06:54 +02:00
Michele Caini
de6b2e139b container: constexpr all the way (see #883) 2022-05-04 16:04:55 +02:00
Michele Caini
7204840a8a resource: fixed typo 2022-05-04 09:30:23 +02:00
Michele Caini
76369a01ad group: avoid unnecessary instantiations and try to please all compilers 2022-05-04 08:38:28 +02:00
Michele Caini
3a92a93604 y_combinator: constexpr-ness all the way (see #883) 2022-05-03 18:51:03 +02:00
Michele Caini
f1c968372f memory: constexpr-ness all the way (see #883) 2022-05-03 18:48:54 +02:00
Michele Caini
759d9a642f config: add ENTT_ENTT_CONSTEXPR to use in combination with ENTT_TRY and the like (waiting for C++20) 2022-05-03 18:48:11 +02:00
Michele Caini
86d86c3044 iterator: constexpr-ness all the way (see #883) 2022-05-03 18:41:15 +02:00
Michele Caini
c38708c483 compressed_pair: constexpr-ness all the way (see #883) 2022-05-03 18:37:39 +02:00
Michele Caini
1673a5ade9 doc: minor changes 2022-05-03 17:07:06 +02:00
Michele Caini
c56a49ddce group: prepare to the storage reference semantics move 2022-05-02 15:36:05 +02:00
Michele Caini
03477ce400 type_traits: type_list_index[_v] 2022-05-02 10:58:11 +02:00
Michele Caini
14d213d13e ident/family: change names for consistency 2022-05-02 09:14:53 +02:00
Michele Caini
8d86816d8d view: tuple constructor 2022-04-30 11:56:04 +02:00
Michele Caini
12cf3fd8e7 *: spot and clear some misues of = default 2022-04-29 12:35:11 +02:00
Michele Caini
8c23f2de8b core/entity: spot and remove useless add_const_t 2022-04-29 12:24:47 +02:00
Michele Caini
837481a854 group: support both const and non-const excluded types 2022-04-29 12:22:54 +02:00
Michele Caini
b682e58df7 view:
* prepare to storage getters for filters
* support both const and non-const excluded types
2022-04-29 12:18:12 +02:00
Michele Caini
c4f430d0d0 view: minor changes 2022-04-28 23:02:00 +02:00
Michele Caini
c7930ab349 natvis: update registry definition 2022-04-28 16:56:54 +02:00
Michele Caini
045baba7ea compressed_pair: re-add base_type to avoid breaking natvis 2022-04-28 16:51:04 +02:00
Michele Caini
d17ac421ec updated authors and todo files 2022-04-28 16:36:55 +02:00
Qix
049e529f66 test: add mention of storage initialization workaround (ref #827) (#879) 2022-04-28 16:34:45 +02:00
Dominic Koepke
ef6e47f625 tuple: forward_apply functional type (#876) 2022-04-28 16:14:25 +02:00
Michele Caini
1330cb9126 doc: typo 2022-04-27 16:55:43 +02:00
Michele Caini
f0ee8bc89d meta: minor changes 2022-04-27 09:32:32 +02:00
Michele Caini
ebc0c18534 test: add missing template keywords (thanks msvc) 2022-04-27 09:22:07 +02:00
Michele Caini
379a4bdda6 meta: re-added meta_type::remove_pointer (close #878) 2022-04-27 09:17:18 +02:00
Michele Caini
2ce106c50f meta: internal changes 2022-04-26 19:46:57 +02:00
Michele Caini
0ebdfe59ee meta: minor changes 2022-04-26 19:01:15 +02:00
Michele Caini
80c700b1f8 sigh_storage_mixin: allocator support 2022-04-26 11:43:59 +02:00
Michele Caini
103f935d61 meta (close #872):
* container traits don't really support plain arrays anymore (if they ever did)
* fix an issue with insert/erase of meta sequence containers
* add non-regression tests
2022-04-24 17:17:47 +02:00
Michele Caini
164476721a compressed_pair: cleanup 2022-04-22 10:40:10 +02:00
Michele Caini
54dd716d02 any: avoid duplicating operation/policy for all specializations 2022-04-22 10:35:01 +02:00
Michele Caini
ab681ce637 registry: minor changes to ease the transition 2022-04-22 00:02:55 +02:00
Michele Caini
a355de8e97 registry: delegating constructor 2022-04-21 23:39:15 +02:00
Michele Caini
56921d6449 config/component: ENTT_IGNORE_IF_EMPTY -> ENTT_ETO_TYPE 2022-04-21 16:54:50 +02:00
Michele Caini
7e900626bc test: suppress shadow warnings 2022-04-21 13:59:27 +02:00
Michele Caini
dc30c29f4e config/component/storage:
* ENTT_IGNORE_IF_EMPTY is an internal def-only macro
* component_traits review to also support void type
* updated tests for component_traits
* added a non-regression test for storage<void>
2022-04-21 11:43:42 +02:00
Michele Caini
370865bb57 doc: add billy engine 2022-04-21 09:10:23 +02:00
Michele Caini
80015e83d4 sigh/dispatcher: use allocator<void> 2022-04-20 16:40:19 +02:00
Michele Caini
c37c35b52b registry: avoid code duplication 2022-04-19 15:35:39 +02:00
Corentin Schreiber
069004d4eb registry: overflow of version and max number of entities (#864) 2022-04-19 10:58:17 +02:00
Michele Caini
f11695200e doc: updated config.md 2022-04-19 09:10:01 +02:00
Michele Caini
ef2f8a1a18 config: decouple ENTT_NOEXCEPT and exceptions handling (close #867) 2022-04-19 09:09:25 +02:00
Michele Caini
54cc687c50 doc: typo 2022-04-19 00:08:25 +02:00
Michele Caini
51f279160f resource: added more comparison operators for resource handles 2022-04-16 11:38:45 +02:00
Michele Caini
e3113f6976 sparse_set: nodiscard get(s) 2022-04-15 16:02:53 +02:00
Michele Caini
485e29a672 meta: reduce number of generated symbols 2022-04-15 15:10:40 +02:00
Michele Caini
00e67c50ca nativs: updated definition for type_info 2022-04-15 11:46:08 +02:00
Michele Caini
3e7b3edb9c group: reduce instantiations due to extended iterators and merge their definitions 2022-04-15 11:46:08 +02:00
Michele Caini
3c6c9d9462 emitter: minor changes 2022-04-15 11:46:08 +02:00
Michele Caini
6b06a9ff2b storage: cleanup 2022-04-15 11:46:08 +02:00
Michele Caini
803db476bb entity:
* drop utility.hpp
* turn get_t/exclude_t into aliases for type_list
* updated api for basic_registry<...>::group/group_if_exists
* doc review to reflect all the changes above
2022-04-15 11:46:08 +02:00
Michele Caini
c134ea3098 doc: updated signal.md 2022-04-15 11:46:08 +02:00
Michele Caini
6e64f36b39 natvis: review both dispatcher and emitter 2022-04-15 11:46:08 +02:00
Michele Caini
36af39e2b4 emitter: full review 2022-04-15 11:46:08 +02:00
Michele Caini
88929ab730 natvis: minor changes 2022-04-15 11:46:08 +02:00
Michele Caini
02f00e5339 dispatcher: assert within assure as it ought to be 2022-04-15 11:46:08 +02:00
Michele Caini
ee67032af1 sigh: cleanup to reduce redundancy 2022-04-15 11:46:08 +02:00
Michele Caini
8aea00f527 delegate: cleanup to reduce redundancy 2022-04-15 11:46:07 +02:00
Michele Caini
50faed4a50 dispatcher: minor changes 2022-04-15 11:46:07 +02:00
Michele Caini
b982817a56 now working on v3.11.0 2022-04-15 11:45:56 +02:00
Michele Caini
e5172a9240 update single include file 2022-04-15 11:44:22 +02:00
Michele Caini
dcac7942fa type_info: a default constructible type isn't a good idea actually 2022-04-08 12:17:14 +02:00
Michele Caini
4e13529adb registry: ctor that reserves enough memory for count pools 2022-04-08 09:58:05 +02:00
Michele Caini
c553835228 doc: add the kindest feedback ever received to the README 2022-04-07 18:48:38 +02:00
Michele Caini
1b87193fc1 doc: add Ember Sword to the list of games :) 2022-04-07 18:47:40 +02:00
Michele Caini
25fca56319 doc: update AUTHORS file 2022-04-07 18:47:15 +02:00
Alexandr Timofeev
bf4252394c *: protect against minmax (#862) 2022-04-07 14:28:30 +02:00
Michele Caini
22757e064f *: review remove_cv/remove_ref tokens after spotting an error by chance 2022-04-06 15:57:26 +02:00
Michele Caini
fc9fa37e4e doc: minor changes 2022-04-06 15:52:49 +02:00
Michele Caini
2d5e3402fa type_info: allow to construct type_info objects directly 2022-04-06 11:25:44 +02:00
Michele Caini
b7dd26121a type_info: cleanup 2022-04-06 09:55:31 +02:00
Michele Caini
23bdbeef4e doc: updated type_info section 2022-04-06 09:50:42 +02:00
Michele Caini
9ac81c5219 natvis: updated type_info snippet 2022-04-06 09:49:48 +02:00
Michele Caini
6b9d346b8b type_info:
* reserve a seq identifier for empty type_info objects
* require type_index to return non-zero values
* make type_info default constructible
* add type_info::operator bool()
2022-04-06 08:53:55 +02:00
Michele Caini
9e68eb4d2c type_id: type_info from variable 2022-04-05 08:50:08 +02:00
Michele Caini
f1f47ee44a entity: internal changes/cleanup 2022-04-05 08:42:36 +02:00
Michele Caini
436b2b3140 core: use fold expressions rather than std::disjunction if possible 2022-04-05 08:42:20 +02:00
Michele Caini
f6cfa8ae49 enum_as_bitmask: internal changes 2022-04-05 08:41:36 +02:00
Michele Caini
13949a8d1f updated internal TODO list 2022-04-04 17:13:49 +02:00
Michele Caini
88db623dc1 view: avoid unnecessary parameter pack 2022-04-04 12:27:28 +02:00
Michele Caini
976413173a any: invoke type_id with decayed types to avoid unnecessary instantiations 2022-04-04 09:46:52 +02:00
Michele Caini
91d3349585 view: slightly reduce instantiations 2022-04-04 09:46:20 +02:00
Michele Caini
6e1a774921 sigh: slightly reduce instantiations 2022-04-04 09:46:00 +02:00
Michele Caini
6b53b509fa registry/storage: minor changes 2022-04-04 09:18:10 +02:00
Michele Caini
b8b6203ecd doc: minor changes 2022-04-04 09:17:40 +02:00
Michele Caini
81e1500675 dense_set: slightly reduce instantiations 2022-04-04 09:17:13 +02:00
Michele Caini
d2cd18cb1e test: minor changes (try to also please codecov) 2022-04-02 16:10:00 +02:00
Michele Caini
f5ac73f681 resource_cache: use actual template parameters on sfinae expressions 2022-04-01 14:48:52 +02:00
Michele Caini
413630813a resource: updated doc 2022-04-01 14:41:38 +02:00
Michele Caini
73b6ef2293 resource: updated natvis file 2022-04-01 14:41:15 +02:00
Michele Caini
428bfbd810 tests: updated tests for the resource module 2022-03-31 15:43:44 +02:00
Michele Caini
c54409bdfb resource: fully review the resource module 2022-03-31 15:43:07 +02:00
Michele Caini
b63aebfdaf dense_set: strong exception guarantee (emplace/insert) 2022-03-30 15:34:45 +02:00
Michele Caini
335f876a46 dense_map: strong exception guarantee (emplace/insert) 2022-03-30 15:26:39 +02:00
Michele Caini
c5e99342a3 tests: minor changes 2022-03-30 15:14:26 +02:00
Michele Caini
1710eb9249 dense_map: minor changes 2022-03-29 16:56:49 +02:00
Michele Caini
d03770f91f meta: avoid using =default to avoid tricking VS toolset v141 2022-03-29 16:26:01 +02:00
Michele Caini
9fe6f7a6ea entity: avoid using =default to avoid tricking VS toolset v141 2022-03-29 16:25:53 +02:00
Michele Caini
2fc605fc3e container: avoid using =default to avoid tricking VS toolset v141 2022-03-29 16:25:37 +02:00
Michele Caini
edcd5c4713 dense_set: use underlying iterators to exploit their checks 2022-03-28 16:25:09 +02:00
Michele Caini
bd3df1e06a dense_map: use underlying iterators to exploit their checks 2022-03-28 16:24:52 +02:00
Michele Caini
b785d1c82b meta: minor changes (coding style) 2022-03-27 23:25:50 +02:00
Michele Caini
93bf14f84f organizer: cleanup + renaming to avoid conflicts 2022-03-27 23:24:54 +02:00
Michele Caini
5a84646282 dense_map: updated built-in doc 2022-03-25 17:34:44 +01:00
Michele Caini
2e6cfc08f0 registry: refine storage proxy iterator and guarantee iterator conversions 2022-03-25 17:20:23 +01:00
Michele Caini
4b6d3d47ec registry: suppress a false warning from clang 2022-03-25 15:12:25 +01:00
Michele Caini
985abaa12a dense_map/set: minor changes 2022-03-24 17:38:51 +01:00
Michele Caini
a381a7253a resource: updated doc 2022-03-23 15:32:11 +01:00
Michele Caini
b8bb509d5c resource:
* drop the resource_loader class
* made the loader a template parameter of the resource_cache
* updated the API of the resource_cache
2022-03-23 15:31:55 +01:00
Michele Caini
f48dbd0e19 resource_handle: updated doc 2022-03-23 15:29:44 +01:00
Michele Caini
31c1278374 config: removed ENTT_LAUNDER (unused) 2022-03-22 12:44:21 +01:00
Michele Caini
f6aaafd60f config: add ENTT_NOEXCEPT_IF (for future uses) 2022-03-22 12:43:47 +01:00
Michele Caini
ae3dec19fd registry: internal changes to avoid ambiguous calls 2022-03-22 12:43:24 +01:00
Michele Caini
990baa0929 test: typo 2022-03-21 16:14:20 +01:00
Michele Caini
7ecb65a141 doc: updated links 2022-03-21 10:41:53 +01:00
Michele Caini
a1e55103be enum: typo 2022-03-21 10:41:45 +01:00
Michele Caini
1b4fc54405 dense_set:
* emplace create-and-discard mode if strictly required only
* insert uses the insert_or_do_nothing utility internally
* opaque value_to_bucket function
2022-03-21 10:41:28 +01:00
Michele Caini
e5dcea1fa0 dense_map: emplace create-and-discard mode if strictly required only 2022-03-21 10:19:47 +01:00
Michele Caini
9f25195629 dense_map: use insert_or_do_nothing from within insert 2022-03-21 10:17:55 +01:00
Michele Caini
6936fa1c1c dense_map: opaque key_to_bucket function 2022-03-21 08:42:44 +01:00
Michele Caini
7b25eacfc8 dense_map:
* try_emplace should not consume arguments if the element exists
* clean up
2022-03-18 10:51:16 +01:00
Michele Caini
33989a61e3 dense_set: claen up 2022-03-18 10:49:52 +01:00
Michele Caini
08d9e8d076 dense_map/set: minor changes 2022-03-17 14:23:29 +01:00
Michele Caini
da43ef0982 dense_set: avoid potential UBs 2022-03-17 12:36:00 +01:00
Michele Caini
02f12bde81 dense_map: avoid potential UBs 2022-03-17 12:35:46 +01:00
Michele Caini
b55d5375ac *: added missing messages to static asserts 2022-03-17 11:39:45 +01:00
Michele Caini
281f40bd56 dense_set: avoid dispatching based on iterator category if possible 2022-03-17 11:39:45 +01:00
Michele Caini
dcb7c0c27e dense_map: constrain the allocator type 2022-03-17 11:39:45 +01:00
Michele Caini
d3c44a6fa6 dense_map: avoid dispatching based on iterator category if possible 2022-03-17 11:39:45 +01:00
Michele Caini
f432dc6bdc dense_map:
* uses-allocator construction
* iterators model forward/random access iter types but are in the input iter category
* iter value_type is pair<const T &, U &>/pair<const T &, const U &> (zip iter types)
* no risky UBs due to type punning or destroy/construct within a vector
2022-03-17 11:39:45 +01:00
Michele Caini
ce21ee6001 test: minor changes 2022-03-17 11:39:36 +01:00
Michele Caini
a431f5a674 registry: allow creating pools during a destroy (close #853) 2022-03-16 17:18:14 +01:00
Michele Caini
f6153f17ad storage: return a meaningful msg when the type is not movable 2022-03-16 17:17:38 +01:00
Michele Caini
c17ecbc78c resource: add operator==/!= to resource handles 2022-03-16 17:17:35 +01:00
Michele Caini
0feb9f0c56 resource_handle: update member types 2022-03-16 17:17:33 +01:00
Michele Caini
e69cb3d950 memory: suppress warnings due to unreferenced parameters 2022-03-16 17:17:30 +01:00
Michele Caini
e7c03dd512 memory: minor changes 2022-03-16 17:17:26 +01:00
Michele Caini
0c1371ffae test: suppress warning due to unused variables 2022-03-16 17:16:54 +01:00
Michele Caini
8a350acf39 dispatcher: allocator support 2022-03-16 17:16:50 +01:00
Michele Caini
594b3b5531 component: use ignore_as_empty_v to simplify the code here and there 2022-03-16 17:16:36 +01:00
Michele Caini
e13d06fe20 component: reintroduce utility ignore_as_empty_v (it's actually useful sometimes) 2022-03-16 17:16:32 +01:00
Michele Caini
805bb84c8f component_traits:
* removed ::ignore_if_empty member
* use ::page_size 0 for empty types
2022-03-16 17:16:21 +01:00
Michele Caini
1a62338349 storage: split sigh_storage_mixin 2022-03-16 17:15:49 +01:00
Michele Caini
4795ba83ba config: remove module-specific mismatch checks (we cannot protect everyone from themselves) 2022-03-16 17:15:41 +01:00
Michele Caini
ad5b362bca config: use pragma detect_mismatch if possible 2022-03-16 17:15:28 +01:00
Michele Caini
8a735452de config: detect version mismatch 2022-03-16 17:15:25 +01:00
Michele Caini
03d0f3e9ca test: merge no-eto tests with registry tests 2022-03-16 17:15:18 +01:00
Michele Caini
ff0983cc42 storage: more about uses-allocator construction 2022-03-16 17:15:00 +01:00
Michele Caini
159a413c7d meta: avoid creating internal namespace that messes with friend declarations 2022-03-16 17:14:37 +01:00
Michele Caini
6a753d1316 meta: remove unused data member 2022-03-16 17:14:34 +01:00
Michele Caini
c89bf30e05 meta: dereferencing a pointer-like object which converts to bool works in all cases (false implies empty meta_any) 2022-03-16 17:14:32 +01:00
Michele Caini
ba4b5ef9f2 meta: minor changes 2022-03-16 17:14:30 +01:00
Michele Caini
5b39ee221f meta: reduce the number of instantiations due to basic_meta_sequence_container_traits 2022-03-16 17:14:28 +01:00
Michele Caini
65c4432325 meta: use adl lookup within basic_meta_sequence_container_traits 2022-03-16 17:14:26 +01:00
Michele Caini
32bbb27c9f meta: further reduce the number of instantiations due to meta sequence containers 2022-03-16 17:14:24 +01:00
Michele Caini
ef3c030576 meta: further optimize meta sequence containers' iterators 2022-03-16 17:14:22 +01:00
Michele Caini
554a182229 meta: reduce instantiations due to meta containers (drop get_fn) 2022-03-16 17:14:20 +01:00
Michele Caini
9154d78e58 meta: make the meta associative container's iterator an internal class as all other iterators 2022-03-16 17:14:18 +01:00
Michele Caini
82d933aa3d meta: make the meta sequence container's iterator an internal class as all other iterators 2022-03-16 17:14:16 +01:00
Michele Caini
ef0fe9b13c meta:
* relax meta sequence container requirements (::clear is no longer required)
* reduce instantiations due to meta sequence containers
2022-03-16 17:14:14 +01:00
Michele Caini
f6700b7094 meta: drop meta_sequence_container::meta_iterator::base() 2022-03-16 17:14:12 +01:00
Michele Caini
21f00cf251 meta: make meta_sequence_container::meta_iterator model a bidirectional iterator (and keep staying in the input iterator category) 2022-03-16 17:14:10 +01:00
Michele Caini
900d2bf816 meta: prepare meta_sequence_container::meta_iterator to model a bidirectional iterator 2022-03-16 17:14:07 +01:00
Michele Caini
3846fa3f28 meta: begin/end adl lookup 2022-03-16 17:14:04 +01:00
Michele Caini
52f77d61ba sigh:
* fixed doc
* test review/cleanup
2022-03-16 17:13:16 +01:00
Michele Caini
039341de69 poly: fixed forward file 2022-03-16 17:13:09 +01:00
Michele Caini
5adf332a5f registry: ::sortable -> ::owned for component types (close #847) 2022-03-16 17:13:04 +01:00
Michele Caini
efbb32a498 sparse_set: added the ::bump function 2022-03-16 17:12:56 +01:00
Michele Caini
3156dd1321 sigh: constrain the allocator type 2022-03-16 17:12:45 +01:00
Michele Caini
2fbeeafbb8 dense_set: constrain the allocator type 2022-03-16 17:12:42 +01:00
Michele Caini
db680f3bcd snapshot: try to get around an issue of VS, toolset v141 2022-03-16 17:12:01 +01:00
Michele Caini
4a20fa5275 snapshot: internal changes 2022-03-16 17:11:55 +01:00
Michele Caini
3fb2da7174 group: internal changes 2022-03-16 17:11:51 +01:00
Michele Caini
7f8bebbdd5 view: internal changes 2022-03-16 17:11:47 +01:00
Michele Caini
597fc0265f natvis: dense_set 2022-03-16 17:11:31 +01:00
Michele Caini
d5d5770dac natvis: dispatcher 2022-03-16 17:11:26 +01:00
Michele Caini
772ac64e3b config: add ENTT_VERSION 2022-03-16 17:11:03 +01:00
Michele Caini
92d7337f04 config: macro.h (just in case) 2022-03-16 17:10:55 +01:00
Michele Caini
200425114c test: address some feedback by iwyu 2022-03-16 17:10:40 +01:00
Michele Caini
b92a73a2a2 workflow: minor changes 2022-03-16 17:10:34 +01:00
Michele Caini
e83c77b99f build system: updated workflow(s) 2022-03-16 17:10:23 +01:00
Michele Caini
28aa35160d hashed_string: minor changes 2022-02-27 17:46:03 +01:00
Michele Caini
18c9bfa134 compressed_pair: minor changes 2022-02-27 17:45:56 +01:00
Michele Caini
bdb7763237 sigh: rebind allocator internally 2022-02-27 17:45:50 +01:00
Michele Caini
bc9ee46b8f dispatcher: minor changes 2022-02-27 17:45:45 +01:00
Michele Caini
b92b734db2 doc: fixed typo 2022-02-25 16:38:13 +01:00
Michele Caini
2748a6cd3c dense_set: remove the constraint on the allocator type 2022-02-25 15:15:09 +01:00
Michele Caini
888876185d doc: fixed typo 2022-02-25 15:14:14 +01:00
Michele Caini
03fea6358b view/runtime_view: make iterator_type private 2022-02-25 14:10:15 +01:00
Michele Caini
59b0dc6735 test: minor changes 2022-02-25 14:09:22 +01:00
Michele Caini
35a42b2172 dense_set: cleanup 2022-02-24 18:48:28 +01:00
Michele Caini
daa4056f45 registry/storage/sparse_set: minor changes to get around an issue of gcc7.5 2022-02-24 18:48:06 +01:00
Michele Caini
bb5abe633f dense_set: review constructors/assignment operators 2022-02-24 11:46:42 +01:00
Michele Caini
dc238db355 compressed_pair: correctly manage references with piecewise construction 2022-02-24 11:33:12 +01:00
Michele Caini
4c692c23bb test: refine tracked_memory_resource::do_is_equal 2022-02-24 11:33:04 +01:00
Michele Caini
b093e82db3 memory: uninitialized_construct_using_allocator (waiting for C++20) 2022-02-23 09:41:32 +01:00
Michele Caini
7a1c2108a1 dispatcher: enable fetching the number of pending events (#848)
Co-authored-by: WoLfulus <WoLfulus@users.noreply.github.com>
2022-02-23 08:42:33 +01:00
Michele Caini
4aa2b49649 updated TODO file 2022-02-23 08:41:56 +01:00
Michele Caini
cdaced4df6 memory: uses_allocator_construction_args pairs support 2022-02-23 00:19:55 +01:00
Michele Caini
cdd029853b any:
* strong exception guarantee applies
* a test to avoid future regressions
2022-02-22 15:03:07 +01:00
Michele Caini
507bafdd9c any/meta_any: revert changes to introduce ::hash 2022-02-22 12:15:09 +01:00
Michele Caini
07a36123e5 dense_map/set: get around a nasty issue of gcc 7.5 with deduced return types and friend functions 2022-02-22 12:03:41 +01:00
Michele Caini
a205e7ada9 test: it's not a good idea to use discarded values, the sanitizer may complain :) 2022-02-22 09:55:03 +01:00
Michele Caini
25e9330bb4 memory: avoid ambiguous call with C++20 2022-02-22 09:45:03 +01:00
Michele Caini
b2edfa454c test: minor changes (to please all compilers) 2022-02-22 09:30:46 +01:00
Michele Caini
07767a09d9 doc: fixed typo 2022-02-22 08:40:25 +01:00
Michele Caini
e8d85d9269 resource: updated doc/tests 2022-02-22 08:15:09 +01:00
Michele Caini
5cf0ba079f memory: make_obj_using_allocator utility (waiting for C++20) 2022-02-21 16:31:36 +01:00
Michele Caini
e08b1f82ce memory: uses_allocator_construction_args (waiting for C++20) 2022-02-21 08:07:01 +01:00
Michele Caini
c2196149ee test: minor changes 2022-02-20 23:55:04 +01:00
Michele Caini
65b5ce7880 doc: minor changes 2022-02-20 23:44:33 +01:00
Michele Caini
9c254ec3e0 doc: mark C++20 feature (to help the future me find them) 2022-02-20 09:57:24 +01:00
Michele Caini
f4418e0205 test: increase code coverage 2022-02-19 10:46:18 +01:00
Michele Caini
a314f7b42e test: minor changes (code coverage) 2022-02-19 10:41:35 +01:00
Michele Caini
dc5a72cda5 dense set:
* cleaned up implementation
* uses-allocator construction support
* a few more tests
2022-02-19 09:49:47 +01:00
Michele Caini
380cb41ca9 entity: cleanup 2022-02-18 17:08:29 +01:00
Michele Caini
83f7e633a3 tests: allocate_unique with types that don't support uses-allocator construction 2022-02-18 17:08:07 +01:00
Michele Caini
ab1c920435 tests: storage with types that don't support uses-allocator construction 2022-02-18 17:07:44 +01:00
Michele Caini
7094d658f8 test: minor changes 2022-02-18 13:47:59 +01:00
Michele Caini
11617291e3 container: minor changes 2022-02-18 13:47:14 +01:00
Michele Caini
790aa03834 scheduler: allow attaching tasks from already running processes (close #845) 2022-02-18 11:34:42 +01:00
Michele Caini
bcd16ea5ea entity: adjust noexcept policy 2022-02-17 12:17:07 +01:00
Michele Caini
81c044760b core: adjust noexcept policy 2022-02-17 12:16:46 +01:00
Michele Caini
b0e0e80b69 meta: adjust noexcept policy 2022-02-17 09:33:48 +01:00
Michele Caini
280bb1d84f dense_set: suppress shadow warning 2022-02-17 09:22:57 +01:00
Michele Caini
bb42dceaca natvis: updated container/dense_set snippet 2022-02-17 09:22:55 +01:00
Michele Caini
d0873ed551 dense_map: adjust noexcept policy 2022-02-17 09:03:28 +01:00
Michele Caini
0fbddfc47b dense_set: adjust noexcept policy 2022-02-17 09:03:11 +01:00
Michele Caini
3f1dee2650 dense_set: uses-allocator construction 2022-02-17 09:02:35 +01:00
Michele Caini
a4b8b93e7f dense_set: emplace always consumes its arguments 2022-02-17 09:02:21 +01:00
Michele Caini
02d1417ef4 process/scheduler: update noexcept policy 2022-02-16 17:36:49 +01:00
Michele Caini
50812a908c signal: update noexcept policy 2022-02-16 12:40:33 +01:00
Michele Caini
1a1ed55485 resource_handle: minor changes 2022-02-16 12:33:55 +01:00
Michele Caini
09fa322a0e poly: update noexcept policy 2022-02-16 12:33:38 +01:00
Michele Caini
1a9a423c35 locator: adjust noexcept policy 2022-02-16 12:33:22 +01:00
Michele Caini
7b0449213c doc: minor changes 2022-02-16 12:32:33 +01:00
Michele Caini
c0251f5c29 sparse_set/storage: support entity and component types with custom swap functions 2022-02-16 12:29:45 +01:00
Michele Caini
4509d8a60b snapshot: swap properly internally 2022-02-16 12:29:43 +01:00
Michele Caini
b1738b0902 natvis: updated signal/delegate snippet 2022-02-16 12:28:29 +01:00
Michele Caini
45259462aa any: remove call to ENTT_LAUNDER, no longer required due to do p1971r0 2022-02-16 12:27:52 +01:00
Michele Caini
772a7427a2 doc: another update for the EnTT in Action list 2022-02-16 12:26:29 +01:00
Michele Caini
afa58b81f6 doc: added D&D Dark Alliance to the EnTT in Action list 2022-02-16 12:26:25 +01:00
Michele Caini
6822c0f0e3 test: minor changes 2022-02-13 18:40:14 +01:00
Michele Caini
0a155ecb68 test: uses-allocator construction guaranteed for allocate_unique 2022-02-13 18:33:31 +01:00
Michele Caini
15fff94447 test: uses-allocator construction guaranteed for storage classes 2022-02-13 18:32:58 +01:00
Michele Caini
ff06df2acb test: tracked_memory_resource utility 2022-02-13 18:32:10 +01:00
Michele Caini
df9301d591 bjuild system/tests: check for <version> (old compilers support) 2022-02-13 18:31:26 +01:00
Michele Caini
e51b1bbb25 compressed_pair: avoid noexcept specification which cannot be supported 2022-02-13 18:29:34 +01:00
Chris Ohk
aa275f4b1c doc: fix minor typos (#842) 2022-02-12 15:52:43 +01:00
Michele Caini
ed11bda9fd component: automatic traits deduction 2022-02-11 10:35:43 +01:00
Michele Caini
ed34a3f5d4 locator:
* service_locator -> locator
* API review + allocator support
* updated doc and tests
2022-02-10 11:31:55 +01:00
Michele Caini
a99b8b7984 build system: get prepared for the windows-latest switch on GH 2022-02-10 10:32:06 +01:00
Michele Caini
f750254cc2 allocate_unique: static assert that Type isn't an array type 2022-02-09 12:32:36 +01:00
Michele Caini
21ece182f5 any: let the wrapper decide what it means to be an owner 2022-02-09 09:42:49 +01:00
Michele Caini
6439dca43a memory: suppress a (shadow) warning from gcc 2022-02-08 11:56:52 +01:00
Michele Caini
ca424a4577 type_traits: try to also please clang-cl 2022-02-08 11:50:53 +01:00
Michele Caini
87bc2cb1ab any: try to also please gcc7 2022-02-08 11:20:49 +01:00
Michele Caini
58f22cc3b5 meta_any: ::hash function for hashable types (+ bonus doc review) 2022-02-08 11:04:14 +01:00
Michele Caini
fa8362f000 any: ::hash function for hashable types (close #629) 2022-02-08 11:02:30 +01:00
Michele Caini
1816206dfc type_traits: is_std_hashable[_v] 2022-02-08 09:58:26 +01:00
Michele Caini
fcfa994152 doc: compressed_pair, std::tuple_size and std::tuple_element specializations 2022-02-08 09:57:10 +01:00
Michele Caini
e7262660c2 dispatcher: API review to support named queues 2022-02-07 10:52:04 +01:00
Michele Caini
a1e14d5740 doc: memory (power of two, fast modulus, allocate_unique, ...) 2022-02-05 00:18:57 +01:00
Michele Caini
60c11f3f30 dispatcher: minor changes 2022-02-05 00:18:42 +01:00
Michele Caini
3fe584d366 any: rename local variable to make it easier for me to read too :) 2022-02-05 00:18:18 +01:00
Michele Caini
28e38321ee test: put basic test allocator in its own file 2022-02-05 00:18:03 +01:00
Michele Caini
1faeeeeabc memory: allocation_deleter/allocate_unique 2022-02-05 00:14:31 +01:00
Michele Caini
75a0c672b1 iterable_adaptor: decouple iterator types 2022-02-04 08:54:16 +01:00
Michele Caini
db829b21aa doc: minor changes 2022-02-04 08:53:23 +01:00
Michele Caini
24bdc29c27 input_iterator_pointer: minor changes 2022-02-03 08:12:35 +01:00
Michele Caini
692a78984f doc: updated documentation about context variables 2022-02-03 08:09:52 +01:00
Michele Caini
77a399738c registry: support to named context variables (see emplace_hint) 2022-02-03 08:06:52 +01:00
Michele Caini
5d7358899d registry: cleanup the standalone context class 2022-02-03 07:52:27 +01:00
Michele Caini
aca25b9999 build: updated build workflow 2022-02-02 11:55:08 +01:00
Paolo Monteverde
182c6c534b meta: rearrange member data of meta nodes to optimize memory usage (#833) 2022-02-02 08:15:51 +01:00
Michele Caini
0500f155e6 delegate: ::instance() -> ::data() 2022-02-02 08:02:03 +01:00
Michele Caini
125b826f62 meta/signal: added missing includes 2022-02-01 23:11:25 +01:00
Michele Caini
922bfbf724 test: fixed includes (while trying iwyu) 2022-02-01 23:01:04 +01:00
Michele Caini
f1e584fad9 scheduler: add missing header 2022-02-01 14:12:23 +01:00
Michele Caini
0c4dcdea71 config/core: include cstdint also when ENTT_ID_TYPE is defined 2022-02-01 14:11:41 +01:00
Michele Caini
ec4b383198 build: minor changes to workflows 2022-02-01 11:31:44 +01:00
Michele Caini
3328c7e78b doc: fixed funding.yml 2022-02-01 11:30:23 +01:00
Michele Caini
357fcd44d7 poly: make Member type explicit to avoid errors with older compilers 2022-01-31 14:48:20 +01:00
Michele Caini
5a0a682d35 meta: relaxed checks on conversion functions 2022-01-31 09:55:53 +01:00
Michele Caini
1fcb7e5aba dispatcher: minor changes 2022-01-31 08:44:40 +01:00
Michele Caini
eec867bc9e enum:
* remove unused functions
* avoid errors due to narrowing conversions
2022-01-31 08:44:24 +01:00
Michele Caini
5a956d2914 poly: compile-time checks on embedded vtables + code coverage 2022-01-30 16:53:27 +01:00
Michele Caini
e0e29cc363 test: cleanup 2022-01-30 16:52:51 +01:00
Michele Caini
9fc8e03f72 poly: refined fwd file, updated (typed-)tests 2022-01-29 17:32:15 +01:00
Michele Caini
b054e93f0e build system: removed the in-source build check 2022-01-29 17:31:37 +01:00
Michele Caini
653680a356 doc: minor changes 2022-01-29 17:30:20 +01:00
Michele Caini
40035f2e52 gh: updated funding file 2022-01-29 17:29:05 +01:00
Michele Caini
a70b7daec4 build system: workflow cleanup 2022-01-29 17:25:34 +01:00
Michele Caini
0f3e7b5dac doc: minor changes to suppress warnings 2022-01-29 16:15:40 +01:00
Michele Caini
2fbc08b606 test: a handful of minor changes to please all compilers from the CI and remove some lambdas 2022-01-29 11:31:57 +01:00
Michele Caini
e4897f709e test: merge poly tests in a single file, use typed tests to reduce the boilerplate 2022-01-29 10:51:25 +01:00
Michele Caini
84445aa28b test: use gtest typed test suite for enums 2022-01-29 10:50:33 +01:00
Michele Caini
0795f9a9f2 test: separate death tests as suggested in the gtest doc 2022-01-29 10:47:22 +01:00
Michele Caini
44ae0d67f6 sparse_set: set the free list to tombstone rather than null within ::clear 2022-01-28 15:53:36 +01:00
Michele Caini
a74f0ca370 test: code coverage 2022-01-28 14:06:22 +01:00
Michele Caini
266c1fcdcb registry: better/faster remove 2022-01-28 14:06:22 +01:00
Michele Caini
977c3407e7 registry: better/faster erase 2022-01-28 14:06:22 +01:00
Michele Caini
99c2299ed4 test: added missing typename keyword 2022-01-28 14:06:22 +01:00
Michele Caini
39a08f17da sparse_set: clear no longer creates tombstones 2022-01-28 14:06:22 +01:00
Michele Caini
57de1187fc sparse_set/storage:
* reintroduce the swap_and_pop vs in_place_pop split for perf reasons
* rollback to a model with two iterators on virtual functions
* even faster range-erase/clear
2022-01-28 14:06:22 +01:00
Michele Caini
2bba6d4c0d test: code coverage 2022-01-28 14:06:22 +01:00
Michele Caini
2f03b225f7 sparse_set: remove the cursed ::slot function (finally) 2022-01-28 14:06:22 +01:00
Michele Caini
533bc1ce94 sparse_set: review ::clear 2022-01-28 14:06:22 +01:00
Michele Caini
add9df6058 doc: updated todo list 2022-01-28 14:06:21 +01:00
Michele Caini
d3496f3ff5 sparse_set: apparently using an invalid iterator isn't a good idea :) 2022-01-28 14:06:21 +01:00
Michele Caini
e97f7ee725 doc: minor changes 2022-01-28 14:06:21 +01:00
Michele Caini
37497295fb sparse_set/storage:
* refine the try_erase to make it accept an iterator and a count (easier to work with at the call site)
* added a test for the stable clear
* added a note for future improvements
2022-01-28 14:06:21 +01:00
Michele Caini
2e89b3b5b9 sparse_set/storage: make try_erase accept a range of entities 2022-01-28 14:06:21 +01:00
Michele Caini
518bbc651e sparse_set/storage:
* try_emplace returns a basic iterator
* try_erase accepts a basic iterator (prepare for an even faster remove/erase/clear/whatever)
2022-01-28 14:06:21 +01:00
Michele Caini
ffd1d97e03 natvis: updated container.natvis to use the right names 2022-01-28 14:05:41 +01:00
Michele Caini
e503d431f1 doc: minor changes 2022-01-28 14:00:54 +01:00
Michele Caini
49a066714a test: minor changes 2022-01-28 14:00:33 +01:00
Michele Caini
7eec610d21 container:
* dense_hash_map -> dense_map
* dense_hash_set -> dense_set
2022-01-28 13:35:16 +01:00
Michele Caini
530507c36b meta: some compile-time checks to avoid subtle runtime errors 2022-01-27 22:49:35 +01:00
Michele Caini
4d2584d8fc doc: added home hearth to the links page 2022-01-25 18:09:37 +01:00
Michele Caini
0f5057920e doc: added gaia-ecs to the list of similar projects 2022-01-25 18:00:34 +01:00
Michele Caini
a98000cf3b test: I am the winner of the best error message ever but I remain humble :) 2022-01-25 14:56:00 +01:00
Michele Caini
0cec8de164 dense_hash_map/set: suppress warnings due to integral conversions 2022-01-25 09:09:37 +01:00
Michele Caini
1caa8d923d sparse_set/storage: iterator's ::index returns the right offset 2022-01-23 13:05:45 +01:00
Michele Caini
4fa51f8c52 type_traits: removed is_iterator_type[_v], it may be ambiguous and cause errors 2022-01-22 16:59:17 +01:00
Michele Caini
a8be765aa8 registry: disable optimizations based on is_iterator_type, free pools allow to implement them on the user side and more efficiently when needed 2022-01-22 16:52:45 +01:00
Michele Caini
d2d35d490a doc: updated entity.md 2022-01-22 16:45:05 +01:00
Michele Caini
26ba137424 registry: template ::storage support to const qualified types 2022-01-21 19:00:49 +01:00
Michele Caini
e6006663ec registry: remove [[nodiscard]] from the template ::storage method 2022-01-21 11:08:07 +01:00
Michele Caini
74eb2772b6 natvis: support standalone registry context 2022-01-20 15:58:32 +01:00
Michele Caini
3878a696af registry: standalone context type (close #575) 2022-01-20 09:37:31 +01:00
Michele Caini
49ac34c405 doc: avoid confusion with context variables 2022-01-19 16:02:04 +01:00
Michele Caini
a7d4a980ba *: more consistent policy for final classes 2022-01-19 12:41:50 +01:00
Michele Caini
2196db562e registry:: non-template storage(id) returns an iterator rather than a naked pointer 2022-01-19 12:15:22 +01:00
Michele Caini
2ad3e0ed4c hashed_string: updated natvis representation 2022-01-19 09:30:35 +01:00
Michele Caini
6e03fe77ae doc: updated copyright 2022-01-19 07:43:58 +01:00
Michele Caini
af8ec7b5dd registry: remove/erase dispatch based on the iterator type 2022-01-18 08:30:43 +01:00
Michele Caini
7fa29e7341 registry: strict check on storage types to prevent subtle bugs in case of errors 2022-01-18 07:45:03 +01:00
Michele Caini
9c6950d163 hashed_string: I managed to crash clang but I remain humble and try to help it :) 2022-01-17 14:02:02 +01:00
Michele Caini
5d4cbfe8e7 hashed_string: make it work with vs toolset v141 2022-01-17 13:49:11 +01:00
Michele Caini
4747422110 *: added a bunch of final here and there 2022-01-17 13:43:55 +01:00
Michele Caini
7d1416ac74 hashed_string: store size information (close #824) 2022-01-17 08:25:56 +01:00
Michele Caini
2efaa7af7b *: allocator aware classes fail to compile if allocator's value type and container's value type differ 2022-01-15 16:48:33 +01:00
Michele Caini
68e259870f sparse_set/storage:
* support ::erase suppression
* support ::emplace with invalid entities when suppressed
* support ::erase/::remove with invalid entities when suppressed
2022-01-15 00:48:07 +01:00
Michele Caini
29c2c94784 doc: suppress warnings from doc generation 2022-01-15 00:45:35 +01:00
Michele Caini
3f2e1d078f sparse_set/storage: replace the whole try_insert machinery with a force_back parameter to try_emplace 2022-01-15 00:44:47 +01:00
Michele Caini
0a259da05a sparse_set: opaque insert always appends elements 2022-01-14 14:06:41 +01:00
Michele Caini
1b22fe6de2 storage: insert for non-empty types always appends elements 2022-01-13 15:01:06 +01:00
Michele Caini
9b700c3bd2 natvis: removed count filter from sparse set, it makes it harder to debug internal issues 2022-01-13 15:00:34 +01:00
Michele Caini
3b72e30c36 sparse_set: use the right iterator in the catch branch of insert 2022-01-13 14:44:27 +01:00
Michele Caini
9eba103de9 storage: insert for empty types always appends elements 2022-01-13 14:05:33 +01:00
Michele Caini
ecadee3876 sparse_set: added basic virtual try_insert (insert does not use it yet) 2022-01-13 13:47:22 +01:00
Michele Caini
699f9105ae storage: arguments are always ignored for empty types 2022-01-13 13:41:32 +01:00
Michele Caini
8a19e8dafe storage: support chained constructors i.e. parent-to-child propagation 2022-01-13 12:00:15 +01:00
Michele Caini
588c056205 sparse_set/storage: minor changes, more tests 2022-01-11 22:56:22 +01:00
Michele Caini
866a7fb641 natvis: added info about the sparse array of a sparse set 2022-01-11 18:18:41 +01:00
Michele Caini
a5fe42268f test: cleanup 2022-01-11 08:15:09 +01:00
Michele Caini
0bd6816bdd sparse_set: pop_at(pos) -> try_erase(entt) (prepare for inhibited deletions) 2022-01-11 08:06:20 +01:00
Michele Caini
1c6670c7a1 sparse_set: merge ::swap_and_pop and ::in_place_pop 2022-01-10 22:55:46 +01:00
Michele Caini
699a0eb934 sigh_storage_mixin:
* always check the owner in debug
* fixed a test that doesn't invoke bind
2022-01-10 17:22:34 +01:00
Michele Caini
72440ab937 sigh_storage_mixin: always trigger an emplace request notification (in sync with unbalanced destroy) 2022-01-10 00:23:18 +01:00
Michele Caini
9ad807bd58 storage: doc cleanup 2022-01-10 00:16:10 +01:00
Michele Caini
9fb1970ac0 sparse_set/storage: rollback ::policy(pol), incompatible with views 2022-01-09 16:15:47 +01:00
Michele Caini
48dfac2588 storage:
* also support (in theory) fancy pointers
* removed the internal ::construct function
2022-01-09 15:06:41 +01:00
Michele Caini
c6d3714e6f sparse_set: also support (in theory) fancy pointers 2022-01-09 15:06:17 +01:00
Michele Caini
1345c257c3 storage: make final virtual functions private (moving towards private-only hooks) 2022-01-09 14:42:56 +01:00
Michele Caini
19112a8f27 storage: cleanup 2022-01-09 14:25:41 +01:00
Michele Caini
e0979fcf3f sparse_set/storage: make empty virtual functions private (moving towards private-only hooks) 2022-01-08 16:14:54 +01:00
Michele Caini
d514ecbd5e doc: updated documentation about deletion policies 2022-01-08 14:36:04 +01:00
Michele Caini
a53dbb6950 registry: deletion policy is checked at runtime for groups since we can change it dynamically now 2022-01-08 14:34:21 +01:00
Michele Caini
a03b88e0eb dense_hash_[map/set]: suppress super annoying warnings 2022-01-07 14:07:35 +01:00
Michele Caini
4472eb1c40 updated TODO file 2022-01-06 00:23:58 +01:00
Michele Caini
3443987127 meta: meta_type::invoke also searches into the base types for a candidate function 2022-01-04 14:55:30 +01:00
Michele Caini
c73a79fd42 view: cleanup 2022-01-04 13:53:00 +01:00
Michele Caini
dedbe3d431 storage: make shrink_to_size check for tombstones only when needed 2022-01-03 21:30:53 +01:00
Michele Caini
87ef713a17 dense_hash_[map/set]: cleanup 2022-01-03 21:17:37 +01:00
Michele Caini
4ba8ac4fa1 sparse_set: opaque emplace/insert return (eventually invalid) iterators to the inserted elements 2022-01-02 17:21:21 +01:00
Michele Caini
e74e0531bd sparse_set/storage: minor changes 2022-01-02 16:51:08 +01:00
Michele Caini
b67cb4bd1f sparse_set/storage: minor changes to make it easier to read for the future me :) 2022-01-01 17:09:34 +01:00
Michele Caini
22628c9ac4 sparse_set/storage: prepare them for a faster and opaque ::insert 2021-12-31 17:23:50 +01:00
Michele Caini
4dd0862fad runtime_view:
* added ::iterate and ::exclude member functions to attach pools at runtime
* removed vector-based constructor
* removed basic_registry<...>::runtime_view member function
* updated benchmarks accordingly (also reviewed them as a whole just because)
2021-12-30 14:41:05 +01:00
Michele Caini
0ec57fbb8d sparse_set: removed redundant check 2021-12-30 14:38:51 +01:00
Michele Caini
19ab584d32 doc: updated FAQs 2021-12-29 16:34:26 +01:00
Michele Caini
97fe978d14 runtime_view: removed redundant validity check 2021-12-29 00:25:11 +01:00
Michele Caini
2a74c7d897 runtime_view: support to all types of sparse set 2021-12-28 09:28:41 +01:00
Michele Caini
cdf9c2fc6f registry: ctx internal review 2021-12-27 16:18:17 +01:00
Michele Caini
235f84a0d4 registry: minor changes 2021-12-27 15:58:09 +01:00
Michele Caini
ccaa490a2f registry: removed unnecessary dispatching from non-const try_ctx 2021-12-27 15:54:49 +01:00
Michele Caini
8eaf11b510 sparse_set: added the possibility to change the deletion policy at runtime 2021-12-27 15:08:42 +01:00
Michele Caini
57a5faa448 sparse_set: updated doc 2021-12-26 23:31:36 +01:00
Michele Caini
be87191d0a sparse_set:
* opaque emplace returns bool
* opaque insert returnes the number of entities actually emplaced
2021-12-26 17:04:10 +01:00
Michele Caini
40aabe76c7 sparse_set: fixed a throwing case that could leave the set in an inconsistent state 2021-12-26 16:36:30 +01:00
Michele Caini
9d304cb35c doc: fixed typo about in_place_delete 2021-12-23 16:31:07 +01:00
Michele Caini
ee08a4966f doc: updated list of links, added D2R to it too 2021-12-23 14:35:34 +01:00
Michele Caini
aeca69903e doc: updated similar projects 2021-12-22 17:53:45 +01:00
Michele Caini
e1b3f2b95a registry: added weak ::storage for opaque cross registry operations 2021-12-22 16:21:55 +01:00
Michele Caini
25c7436652 doc: minor changes 2021-12-21 14:10:33 +01:00
Michele Caini
771c449621 bump the version number 2021-12-21 13:27:04 +01:00
Michele Caini
61ecaa5756 storage: review to avoid code duplication 2021-12-21 08:33:46 +01:00
Michele Caini
c05dddc56e runtime_view: slightly optimized iterators 2021-12-21 08:33:46 +01:00
Michele Caini
8e0747fd50 updated single include file 2021-12-21 08:32:48 +01:00
Michele Caini
1bcc87c916 runtime_view: removed an useless check, slightly improved performance 2021-12-19 10:25:55 +01:00
Michele Caini
45797907d3 doc: updated toc in the README file 2021-12-18 17:51:02 +01:00
Michele Caini
3498dea486 registry (close #521):
* remove visit
* added storage_proxy_iterator (input iterator category, modeled as a random access iterator)
* added ::storage() (const and non-const) to return an iterable object over all pools
2021-12-17 17:05:14 +01:00
Michele Caini
a4aab8458b group/storage/view: minor changes 2021-12-17 16:57:29 +01:00
Michele Caini
534744d615 iterator: minor changes 2021-12-17 16:57:26 +01:00
Michele Caini
dc5450b95e view: natvis friendly representation 2021-12-17 16:57:24 +01:00
Michele Caini
9e0e276740 dense_hash_set/map: removed unnecessary type members 2021-12-17 16:57:22 +01:00
Michele Caini
1c9c02f3ce view: avoid exposing internal details from iterators 2021-12-17 16:57:20 +01:00
Michele Caini
7774f9f402 storage: review + avoid exposing internal details from iterators 2021-12-17 16:57:18 +01:00
Michele Caini
5607219945 sparse_set: minor changes 2021-12-17 16:57:14 +01:00
Michele Caini
69ef3efd2d dense_hash_map/set: avoid exposing internal details from iterators 2021-12-17 16:57:10 +01:00
Michele Caini
36c118922b group/view:
* added default constructors to input iterators
* make sure that a default constructed iterator compares equal to end()
2021-12-17 08:39:54 +01:00
Michele Caini
1d014953e3 storage: try to also please gcc-9 2021-12-16 14:33:24 +01:00
Michele Caini
c5cb1d9bcc storage/view/group:
* added extended_storage_iterator and storage<T...>::each function to return an extended iterable object
* use extended_storage_iterator and iterable_adaptor everywhere to avoid code duplication
2021-12-16 12:31:44 +01:00
Michele Caini
86d12cf317 doc: brief -> copydoc 2021-12-16 12:30:29 +01:00
Michele Caini
db9e59ede1 core: added iterable_adaptor 2021-12-16 12:29:20 +01:00
Michele Caini
cc9b1b0a05 sparse_set: added const_iterator/const_reverse_iterator and cbegin/cend/crbegin/crend 2021-12-16 08:52:13 +01:00
Michele Caini
5c29de2013 updated TODO 2021-12-15 13:13:16 +01:00
Michele Caini
559db104f8 view: suppress some warnings due to initialization order 2021-12-15 10:24:08 +01:00
Michele Caini
365c57be4c build system: allow compiling the tests with clang-cl (thanks gtest for failing otherwise) 2021-12-15 10:23:34 +01:00
Michele Caini
6f0c84fc68 dense_hash_map/dense_hash_set: remove [[nodiscard]] from friend function declaration 2021-12-15 09:33:23 +01:00
Michele Caini
75782d9e99 registry: review/cleanup 2021-12-14 23:15:57 +01:00
Michele Caini
69ddf4936e registry: remove the visit overload that also takes an entity 2021-12-14 22:57:10 +01:00
Michele Caini
4b3108283f dense_hash_map/dense_hash_set: avoid pointer overflow for end iterators (close #804) 2021-12-14 16:44:34 +01:00
Michele Caini
12d177a6c8 registry: removed ::orphans, use ::each/::orphan instead (no way to further optimize it) 2021-12-13 10:00:32 +01:00
Michele Caini
54717dc7e2 test: minor changes 2021-12-12 17:45:13 +01:00
Michele Caini
631c909abd group: drop conceptually broken reverse iterators 2021-12-12 17:45:06 +01:00
Michele Caini
208746f28f view: get rid of the internal::storage_tuple function, back to the uniform model 2021-12-12 17:05:37 +01:00
Michele Caini
61c5f8ae22 registry/view/group: cleanup 2021-12-12 16:51:48 +01:00
Michele Caini
4e0cca3a08 view: clean up 2021-12-12 01:18:41 +01:00
Michele Caini
b86ffc2370 view: drop conceptually broken reverse iterators 2021-12-12 01:11:20 +01:00
Michele Caini
33574c9885 doc: updated README file 2021-12-10 10:24:08 +01:00
Michele Caini
672c542f99 group: removed ::data, use ::handle<T>().data() and ::storage<T>().data() instead 2021-12-10 09:30:16 +01:00
Michele Caini
f741fe48a1 group: added ::handle to non-owning groups 2021-12-10 08:25:46 +01:00
Michele Caini
4347ebcee2 group: added base_type type member 2021-12-09 17:50:51 +01:00
Michele Caini
4e3e5a5361 doc: updated doc for the ecs module 2021-12-09 17:49:30 +01:00
Michele Caini
8e6439c3d1 group: removed ::raw, use ::storage().raw() instead 2021-12-09 17:49:18 +01:00
Michele Caini
b54d358feb view: removed ::data for single type views, use ::storage().data() instead 2021-12-09 09:37:17 +01:00
Michele Caini
78baa7b12d view: removed ::raw for single type views, use ::storage().raw() instead 2021-12-09 09:21:37 +01:00
Michele Caini
19f1dd22e9 view: minor changes to avoid confusion 2021-12-09 09:12:08 +01:00
Michele Caini
73f583f68a registry: doc cleanup 2021-12-09 09:05:14 +01:00
Michele Caini
52de43e329 registry: removed ::empty<T>(), use ::view<T>().empty() or ::storage<T>().empty() instead 2021-12-09 08:20:34 +01:00
Michele Caini
49ddacaac0 registry: removed ::size<T>(), use ::view<T>().size() or ::storage<T>().size() instead 2021-12-08 15:17:35 +01:00
Michele Caini
4533b3a1c0 registry: minor chages (doc/internals) 2021-12-05 17:01:40 +01:00
Michele Caini
f30ea02794 registry:
* removed registry::reserve<Component> (use registry.storage<Component>.reserve(v) instead)
* removed registry::capacity<Component> (use registry.storage<Component>.capacity() instead)
* removed registry::shrink_to_fit<Component> (use registry.storage<Component>.shrink_to_fit() instead)
2021-12-05 16:20:14 +01:00
Michele Caini
7112dda299 build_system: added all headers to the EnTT target 2021-12-05 16:01:32 +01:00
Michele Caini
02636a7108 view: minor changes 2021-12-05 15:55:40 +01:00
Michele Caini
36a9456e0d test: minor changes to make all major compilers agree at least on something :) 2021-12-04 15:32:38 +01:00
Michele Caini
113893dcea meta: added meta_any::owner 2021-12-04 15:28:52 +01:00
Michele Caini
1abbe9c7b2 test: minor changes (code coverage) 2021-12-04 15:21:49 +01:00
Michele Caini
7205ac791c meta: make policies check function return types 2021-12-03 18:25:11 +01:00
Michele Caini
3335b81ad4 meta:
* dtor support to member functions
* review to introduce strict checks on policies
2021-12-03 17:56:09 +01:00
Michele Caini
d9c9438f3c test: minor changes 2021-12-03 14:39:50 +01:00
Michele Caini
37250843e1 sigh: allocator support 2021-12-02 11:30:54 +01:00
Michele Caini
072ab88721 build system: avoid using windows-2016 (deprecated by GH) 2021-12-01 10:33:43 +01:00
Michele Caini
c208e6b107 natvis: avoid errors due to null/tombstone definition not available in some contexts 2021-11-30 14:44:12 +01:00
Michele Caini
65f3185b39 entity: add page_size to entt_traits to make it more natvis friendly and customizable on a per-type basis 2021-11-30 13:48:12 +01:00
Michele Caini
34f73f8a2b registry: added base_type member type 2021-11-30 11:23:15 +01:00
Michele Caini
cb4142a97d entity: simplified to_version 2021-11-30 09:46:15 +01:00
Michele Caini
80d08d5a34 view:
* fixed init list order to suppress a warning
* try to please gcc that fails to compile valid code
2021-11-30 09:46:14 +01:00
Michele Caini
052aecf533 natvis: basic_view (single and multi type) 2021-11-30 09:46:14 +01:00
Michele Caini
7bde714f18 view: minor changes 2021-11-30 09:46:14 +01:00
Michele Caini
5ff429f656 view:
* added single type view overloads for ::storage to make it compatible with the multi-type view version
* removed the useless tuple from single type views
* updated operator|
2021-11-30 09:46:14 +01:00
Michele Caini
92f27299e1 group: added the ::storage method (with tests) 2021-11-30 09:46:14 +01:00
Michele Caini
f9013375f8 view: added the ::storage method (with tests) 2021-11-30 09:46:14 +01:00
Michele Caini
f18b0045ba registry: get around an issue of the toolset v141 2021-11-30 09:46:14 +01:00
Michele Caini
18173cc4c0 view: minor changes 2021-11-30 09:46:12 +01:00
Michele Caini
6a1ffdd7a5 natvis: bypass some natvis idiosyncrasies to display storage information and content in all cases 2021-11-30 09:45:37 +01:00
Michele Caini
8db78b2190 nativs:
* don't abuse Intrinsic, it also has drawbacks
* refine natvis snippet for dispatcher class
2021-11-30 09:45:37 +01:00
Michele Caini
3fcccae241 component traits:
* added page_size to tune the page size on a per-type basis
* turned in_place_delete into a boolean value
* turned ignore_if_empty into a boolean value
* removed in_place_delete_v (no longer required)
2021-11-30 09:45:37 +01:00
Michele Caini
6ff8add164 entity: added missing includes 2021-11-30 09:45:37 +01:00
Michele Caini
58a8c3c82a natvis: make the ecs stuff work with entity classes 2021-11-30 09:45:37 +01:00
Michele Caini
92c5c656c7 natvis: dispatcher 2021-11-30 09:45:37 +01:00
Michele Caini
61856cd648 natvis: poly 2021-11-30 09:45:37 +01:00
Michele Caini
687f82b5c2 natvis: basic_registry 2021-11-30 09:45:37 +01:00
Michele Caini
920c864bed natvis: tombstone/null 2021-11-30 09:45:37 +01:00
Michele Caini
1360c985b7 natvis: when you discover the intrinsic tag... :) 2021-11-30 09:45:37 +01:00
Michele Caini
b6f953e13b natvis: added simple views + minor changes 2021-11-30 09:45:37 +01:00
Michele Caini
796b96071b registry: minor changes 2021-11-30 09:45:37 +01:00
Michele Caini
ec56ccc690 view: minor changes 2021-11-30 09:45:35 +01:00
Michele Caini
95931b67e1 registry: turn storage_type in a public member type 2021-11-30 09:43:48 +01:00
Michele Caini
706bbb83c9 storage: clean up 2021-11-30 09:43:48 +01:00
Michele Caini
43099f47d0 meta: try to suppress a wrong warning from clang 2021-11-30 09:43:48 +01:00
Michele Caini
eca86999c3 doc: added a section about runtime stuff 2021-11-30 09:43:48 +01:00
Michele Caini
a00b44a5fd example: stamp is back 2021-11-30 09:43:48 +01:00
Michele Caini
5b8dcff2a4 helper: make to_entity also work for stable types (close #768) 2021-11-30 09:43:48 +01:00
Michele Caini
e4d36e4982 registry: decouple ::storage/::assure 2021-11-30 09:43:48 +01:00
Michele Caini
adfdbf138d registry:
* public and runtime pools
* removed basic_registry<...>::prepare
2021-11-30 09:43:48 +01:00
Michele Caini
8d1ba26492 registry: try to also please vs2015 ¯\_(ツ)_/¯ 2021-11-30 09:43:48 +01:00
Michele Caini
792625f763 registry: minor changes/cleanup 2021-11-30 09:43:47 +01:00
Michele Caini
5e8eae4ef8 natvis: delegate, sigh, sink, connection, scoped_connection 2021-11-30 09:43:47 +01:00
Michele Caini
148212da96 natvis: minor changes 2021-11-30 09:43:47 +01:00
Michele Caini
23ddb12529 registry: removed pdata container, pools are standalone objects and thus ready to go public 2021-11-30 09:43:47 +01:00
Michele Caini
186a5e8f7b natvis: updated definition for sparse set and storage 2021-11-30 09:43:47 +01:00
Michele Caini
dfb5fe1e04 sparse_set/storage: opaque get from base 2021-11-30 09:43:47 +01:00
Michele Caini
640f75373e doc: minor changes 2021-11-30 09:43:47 +01:00
Michele Caini
46e5d96ced sparse_set/storage: value type from base, if any 2021-11-30 09:43:47 +01:00
Michele Caini
ad3fbe2052 sparse_set/storage: no virtual swap (the silliest thing I've ever done) 2021-11-30 09:43:47 +01:00
Michele Caini
cd6c60fd46 sparse_set/storage: emplace-from-below with value 2021-11-30 09:43:47 +01:00
Michele Caini
f7be386d5a sparse_set: rename context to bind 2021-11-30 09:43:47 +01:00
Michele Caini
89b2131052 doc:
* const thread safe registry
* detached views
2021-11-30 09:43:47 +01:00
Michele Caini
e5d1ca2e3c registry:
* const thread safe implementation
* views created from const registires can refer placeholder pools (that is, they don't refresh)
2021-11-30 09:43:47 +01:00
Michele Caini
32b8224afd runtime_view: simplify the construction process 2021-11-30 09:43:47 +01:00
Michele Caini
00e7ab1db8 entity: fully remove the poly storage support 2021-11-30 09:43:47 +01:00
Michele Caini
e376a53b09 entity:
* custom move ctor/op for the registry class
* no registry argument from storage emplace, remove, ...
* added sparse set context to forward variables to mixins
* removed sparse set user data
2021-11-30 09:43:47 +01:00
Michele Caini
17a9cd5666 cache: use identity as hashing function 2021-11-30 09:43:47 +01:00
Michele Caini
fc3de662c3 registry: combine dense hash maps and identity when the key is a hashed string already 2021-11-30 09:43:47 +01:00
Michele Caini
8de568c2fc *: combine dense hash map and identity when the key is a hashed string already 2021-11-30 09:43:47 +01:00
Michele Caini
55661883d9 registry: use a dense hash map for context variables 2021-11-30 09:43:47 +01:00
Michele Caini
b59d3ebeaa *: dense_hash_map being a drop-in replacement for unordered_map has its advantages :) 2021-11-30 09:43:47 +01:00
Michele Caini
2866dcdd03 doc: updated documentation about making EnTT work smoothly across boundaries 2021-11-30 09:43:47 +01:00
Michele Caini
b147f9d58c registry: make it run smoothly across boundaries (close #719, close #729) 2021-11-30 09:43:47 +01:00
Michele Caini
8e2a6470ac emitter: make it run smoothly across boundaries 2021-11-30 09:43:47 +01:00
Michele Caini
19230f7672 dispatcher: make it run smoothly across boundaries 2021-11-30 09:43:47 +01:00
Michele Caini
764dfbe46a doc: minor changes 2021-11-30 09:43:47 +01:00
Michele Caini
0ec7631310 view: make all unoptimized single type views check for tombstones 2021-11-30 08:58:51 +01:00
Michele Caini
0b39ece990 meta: fix an issue with meta_factory<T>::prop when using tuple of properties 2021-11-18 15:44:12 +01:00
Michele Caini
97500dff57 meta: fixed an issue with meta_factory::conv when used with member functions + code coverage 2021-11-18 14:53:17 +01:00
Michele Caini
dc6299a029 doc: fixed typos 2021-11-18 09:00:52 +01:00
Michele Caini
58b1e2fb98 hashed string: warnings to clarify that it does not take ownerships of the string or copy it (close #798) 2021-11-16 18:05:17 +01:00
Michele Caini
0302fdaaba build system: update gtest upstream branch name 2021-11-16 09:33:32 +01:00
Michele Caini
09b260e0af view: use explicit types to also please clang 6.x 2021-11-15 14:43:20 +01:00
Michele Caini
24b7e998b2 registry: minor changes 2021-11-13 18:30:35 +01:00
Michele Caini
19068ea5c7 doc: updated links 2021-11-13 12:19:51 +01:00
Michele Caini
b5cd3eb468 natvis: hashed_string + minor changes 2021-11-11 14:40:20 +01:00
Michele Caini
91a2b5a5f7 natvis: expand meta_any as a meta_type_node 2021-11-11 11:16:51 +01:00
Michele Caini
0096f6d962 natvis: meta 2021-11-11 10:04:45 +01:00
Michele Caini
87cfe41b15 natvis: minor changes 2021-11-11 10:04:21 +01:00
Michele Caini
c490086097 license: just make it clear that this is about EnTT :) 2021-11-10 11:02:32 +01:00
Michele Caini
5b3fd7537e meta: avoid a (maybe) UB in meta_any 2021-11-08 15:16:22 +01:00
Michele Caini
2cab2583c0 any: minor changes 2021-11-08 13:41:16 +01:00
Michele Caini
a40a3b594d storage: make try_emplace forward user data to base classes 2021-11-06 23:35:25 +01:00
Michele Caini
0fa586a3d8 type_id: reduce the number of static variables due to type_id 2021-11-06 23:31:57 +01:00
Michele Caini
25977cc569 test: use deduction guides :) 2021-11-05 14:17:33 +01:00
Michele Caini
0be7064493 view:
* support for multiple components of the same type
* removed view.each<T>(F), use view.use<T>().each(F) instead
* removed view.each<T>(), use view.use<T>().each() instead
* added use<integral value>() to set leading pool by index
* added get<integral value...>() to get components by index
2021-11-05 11:02:15 +01:00
Michele Caini
0b13dc254a registry: minor changes 2021-11-05 10:58:30 +01:00
Michele Caini
c1e953ab6e registry: removed redundant compile-time check 2021-11-04 18:45:55 +01:00
Michele Caini
a069764af1 type traits:
* unpack_as_t -> unpack_as_type
* unpack_as_v -> unpack_as_value
2021-11-04 14:17:21 +01:00
Michele Caini
3dbe6c3902 meta: cleanup/review 2021-11-04 12:37:20 +01:00
Michele Caini
9f0b380024 container:
* review dense_hash_map_iterator::operator[]
* review dense_hash_set_iterator::operator[]
* code coverage
2021-11-02 09:29:10 +01:00
Michele Caini
193b102013 entity:
* review sparse_set_iterator::operator[]
* review storage_iterator::operator[]
* code coverage
2021-11-02 09:19:57 +01:00
Michele Caini
511fde91fa natvis: snippet for dense_hash_set 2021-10-30 13:49:11 +02:00
Michele Caini
16e3cfc589 container: added dense_hash_set 2021-10-30 13:45:02 +02:00
Michele Caini
ed2012a36c dense_hash_map: minor changes + test coverage 2021-10-30 13:44:00 +02:00
Michele Caini
46598fde32 dense_hash_map: less risky but still on the edge :) 2021-10-29 12:32:09 +02:00
Michele Caini
94d0c5fa5c compressed_pair: added first_type/second_type member types 2021-10-28 12:18:59 +02:00
Michele Caini
4e72291588 meta: define meta_associative_container_traits for dense_hash_map 2021-10-28 08:22:20 +02:00
Michele Caini
74cdf000b4 doc: fixed a couple of typos 2021-10-26 15:44:05 +02:00
Michele Caini
565dc3327b natvis: snippet for meta_any 2021-10-26 15:01:04 +02:00
Michele Caini
462af21793 entity: avoid shadow warnings 2021-10-26 14:19:55 +02:00
Michele Caini
94af659c86 natvis:
* minor changes to entity.natvis
* snippet for dense_hash_map
2021-10-26 11:04:19 +02:00
Michele Caini
b63c9fc67b dense_hash_map: always guarantee that load factor is less than max load factor 2021-10-26 11:04:19 +02:00
Michele Caini
f519b55a47 natvis: compressed_pair 2021-10-26 11:04:19 +02:00
Michele Caini
2fb039b429 entity: minor changes 2021-10-26 11:04:19 +02:00
Michele Caini
4bce5aed77 natvis: snippets for type_info and basic_any 2021-10-26 11:04:19 +02:00
Michele Caini
eca6032306 entity:
* small changes to the entt_traits class
* natvis snippets for basic_sparse_set and basic_storage (with tombstone detection)
2021-10-26 11:04:19 +02:00
Michele Caini
dd2f515af1 build_system: avoid using INTERNAL for cmake variables since it also implies STRING 2021-10-26 11:04:19 +02:00
Michele Caini
df25482643 build_system: support for natvis files (optionally added to the target) 2021-10-26 11:04:19 +02:00
Michele Caini
df016b3bf9 natvis: prepare support for natvis info 2021-10-26 11:04:19 +02:00
Michele Caini
8699e96609 build_system:
* ENTT_USE_LIBCPP default is OFF
* added ENTT_INCLUDE_HEADERS to make adding headers to the EnTT target optional
* slightly better message handling
2021-10-26 11:04:19 +02:00
Michele Caini
b0dcaaf744 build_system: refine ENTT_USE_SANITIZER usage 2021-10-26 11:04:19 +02:00
Michele Caini
7db001995c build system: make EnTT files show up in IDEs automatically (close #776) 2021-10-26 11:04:19 +02:00
Michele Caini
c88adf9314 meta: avoid unnecessary moves (see #794) 2021-10-26 11:04:19 +02:00
Michele Caini
b13713ce98 meta: support transparently base members when attached to meta types for derived classes 2021-10-26 11:03:29 +02:00
Michele Caini
66b89d170f type_traits: tuple-like type support for is_equality_comparable[_v] 2021-10-22 16:50:00 +02:00
Michele Caini
4311e2e686 type_traits: make is_iterator also support void * 2021-10-22 10:25:02 +02:00
Michele Caini
fd566eff7a code coverage: move to codecov action v2 2021-10-21 11:00:42 +02:00
Michele Caini
efaa3f9e55 *: revert unnecessary changes ¯\_(ツ)_/¯ 2021-10-20 12:18:18 +02:00
Michele Caini
b625ff0902 dense_hash_map: iterator review 2021-10-20 11:44:48 +02:00
Michele Caini
fee80321ef meta_[sequence|associative]_container: iterator review 2021-10-20 10:08:49 +02:00
Michele Caini
4b9331f086 sparse_set: iterator review 2021-10-20 09:41:27 +02:00
Michele Caini
df9316b896 runtime_view: iterator review 2021-10-20 09:32:55 +02:00
Michele Caini
dae5f86d4e storage: iterator review 2021-10-20 09:10:29 +02:00
Michele Caini
75a0cefcb3 meta_range: iterator review 2021-10-20 09:06:54 +02:00
Michele Caini
2271aa5b89 registry: make all_of, any_of and a few other functions remove const qualifiers 2021-10-19 08:45:58 +02:00
Michele Caini
b668e2a967 meta: removed unused reference qualifiers 2021-10-18 16:27:49 +02:00
Michele Caini
ce44c59547 meta: suppress warnings due to unreachable code 2021-10-18 11:27:22 +02:00
Michele Caini
84802d931d clean up todo list 2021-10-12 16:56:12 +02:00
Michele Caini
8183c4383e meta: suppress a shadow warning 2021-10-12 16:55:57 +02:00
Michele Caini
af249098cd container: sparse set based dense hash map 2021-10-12 16:50:28 +02:00
Michele Caini
8fdd063f00 entity: include fwd.hpp from entity.hpp (close #790) 2021-10-12 15:14:36 +02:00
Michele Caini
fe328f6a75 identity: add is_transparent member type 2021-10-10 16:31:45 +02:00
Michele Caini
ef7163acd6 storage: non-const to const iterator conversion guaranteed 2021-10-10 10:58:58 +02:00
Michele Caini
6e45f0d5b8 meta_range: non-const to const iterator conversion guaranteed 2021-10-10 10:46:34 +02:00
Michele Caini
ff41faa3fe memory: all of a sudden I remembered what greater than or equal to means :) 2021-10-10 00:42:25 +02:00
Michele Caini
acb2d332ea type_traits: added is_transparent[_v] utility 2021-10-09 19:19:18 +02:00
Michele Caini
0fb86f21e4 type_traits: add tests for is_ebco_eligible_v 2021-10-09 19:03:28 +02:00
Michele Caini
e4991d367e memory: fast_mod no longer requires a compile-time modulus (but it's still a constexpr function) 2021-10-08 20:24:07 +02:00
Michele Caini
3144cfafd5 memory: added constexpr function next_power_of_two 2021-10-07 16:53:22 +02:00
Michele Caini
c538067544 *: cleanup, minor changes 2021-10-06 11:52:32 +02:00
Michele Caini
f8e137a1dc test: suppress warnings due to missing virtual destructor 2021-10-05 08:40:07 +02:00
Michele Caini
36ea38fd91 resource class vs struct definition 2021-10-05 08:39:54 +02:00
Michele Caini
baae5a7215 test: code coverage 2021-10-05 08:38:06 +02:00
Michele Caini
a4b267227e meta: split meta_invoke_with_args function 2021-10-05 08:37:35 +02:00
Michele Caini
58dd159699 meta: add and typename keywords for fun (thanks to msvc that also accepts invalid code) 2021-10-05 08:14:03 +02:00
Michele Caini
80082f9d51 meta: static functions that require the parent type as first argument are treated as (eventually const) member functions 2021-10-04 18:20:16 +02:00
Michele Caini
7975ffc10b meta: minor changes 2021-10-04 16:36:50 +02:00
Michele Caini
012083a4a1 meta: review utilities + code coverage 2021-10-04 16:21:55 +02:00
Michele Caini
3c67723e83 doc: minor changes 2021-10-04 11:52:22 +02:00
Michele Caini
7f0598b3cb meta: cleanup headers 2021-10-04 09:01:13 +02:00
Michele Caini
c5b27e0ae0 test: minor changes (code coverage) 2021-10-03 16:58:58 +02:00
Michele Caini
4e7ad31f18 resource: dynamic resource handle cast example (close #786) 2021-10-03 00:26:46 +02:00
Michele Caini
c7a3e9d4ac resource: cache const correctness review 2021-10-03 00:01:59 +02:00
Michele Caini
a05e7a84c4 resource: handle as value type, const correctness review 2021-10-02 23:52:22 +02:00
Michele Caini
389cb85410 resource: strict check on resource type for cache 2021-10-02 23:35:40 +02:00
Michele Caini
81ae2bed25 resource: added resource_handle::resource_type 2021-10-02 16:26:44 +02:00
Michele Caini
0ab71bc2e7 view: return a const reference to the leading storage 2021-10-01 16:26:11 +02:00
Michele Caini
81e6bbe643 test: minor changes (thanks msvc for accepting invalid code) 2021-10-01 11:05:21 +02:00
Michele Caini
c4723f3b24 view/group: added missing operator-> here and there 2021-10-01 10:57:32 +02:00
Michele Caini
df4d8e0411 meta: make meta_iterator::operator-> const as it ought to be 2021-10-01 10:57:16 +02:00
Michele Caini
4f1820bcad iterator: review of input iterator pointer type 2021-10-01 10:24:05 +02:00
Michele Caini
e375097e43 doc: minor changes 2021-10-01 09:46:41 +02:00
Michele Caini
c51bec0034 meta: add meta_range::operator-> 2021-09-30 17:34:16 +02:00
Michele Caini
081c3fdb5b iterator: added [[nodiscard]] to input_iterator_proxy::operator-> 2021-09-30 16:57:20 +02:00
Michele Caini
f1e7602775 meta: added operator-> to meta containers' iterators 2021-09-30 16:56:58 +02:00
Michele Caini
acd75ffe1c iterator: added utility input_iterator_proxy 2021-09-30 16:34:09 +02:00
Michele Caini
fc813cb59b doc: minor changes 2021-09-30 14:41:33 +02:00
Michele Caini
044d14f542 *: minor changes 2021-09-29 16:12:39 +02:00
Michele Caini
28b9f07b99 *: code coverage, cleanup 2021-09-29 11:27:13 +02:00
Michele Caini
6f20dd4e45 test: suppress a wrong warning with toolset v141 2021-09-29 11:09:37 +02:00
Michele Caini
2fc05e5b90 meta: add missing template keywords (thanks MSVC for accepting invalid code) 2021-09-29 11:03:08 +02:00
Michele Caini
9afde31f97 meta: make meta_any::assign work with mutating this pointers 2021-09-29 10:57:31 +02:00
Michele Caini
e835ce0697 meta: make meta_any::allow_cast work with mutating this pointers 2021-09-29 09:49:22 +02:00
Michele Caini
6030f56c76 meta: make meta_any::try_cast work with mutating this pointers 2021-09-28 18:50:03 +02:00
Michele Caini
ba89b53c63 doc: cleanup 2021-09-28 15:11:29 +02:00
Michele Caini
1bfb877a3b entity: adds to_entity and to_version to the entt namespace (see #788) 2021-09-28 14:52:52 +02:00
Michele Caini
72776d6fb6 entity: make return type of to_integral explicit 2021-09-28 14:31:09 +02:00
Michele Caini
7bb93420c4 storage: avoid reinventing the wheel :) 2021-09-27 08:55:50 +02:00
Michele Caini
bb1b0e0581 sparse_set: minor changes 2021-09-26 23:28:32 +02:00
Michele Caini
45ddcf0df9 sparse_set: compare allocators before moving in the move operator assignment 2021-09-26 11:08:55 +02:00
Michele Caini
9c4d7a286f memory: avoid warnings due to unused parameters 2021-09-26 11:06:36 +02:00
Michele Caini
7b290b43b5 sparse_set: try not to reinvent the wheel :) 2021-09-26 10:59:00 +02:00
Michele Caini
2e2782b030 sparse_set: partial sorting not supported in case of tombstones 2021-09-25 18:29:45 +02:00
Michele Caini
48f23bd1ba doc: cleanup 2021-09-24 16:22:42 +02:00
Michele Caini
3ece33b26a any: avoid using addressof on the result of an operator assignment without a good reason :) 2021-09-24 13:29:16 +02:00
Michele Caini
efa98379b0 meta: internal changes and cleanup 2021-09-24 12:49:43 +02:00
Michele Caini
324aeba70f meta: suppress a warning due to -Wignored-qualifiers (close #785) 2021-09-24 11:50:51 +02:00
Michele Caini
7b6715c7b5 test: code coverage for the storage class for empty types 2021-09-24 11:18:11 +02:00
Michele Caini
1ea392b6c9 test: minor changes to suppress a bunch of warnings + formatting 2021-09-24 10:19:13 +02:00
Michele Caini
8b1a3849e6 meta_any: support assigning the value wrapped by a meta_any 2021-09-24 10:08:59 +02:00
Michele Caini
e1d7e98c92 any: minor changes 2021-09-23 10:36:30 +02:00
Michele Caini
04b2e1152c any:
* when moving fails, try to copy anyway as a fallback
* code coverage
2021-09-22 17:13:02 +02:00
Michele Caini
d392eba4a0 test: code coverage 2021-09-22 16:49:42 +02:00
Michele Caini
799dec4f1c sparse_set: suppress a warning due to -Wreorder 2021-09-22 16:41:40 +02:00
Michele Caini
11df6ec927 type_id: cannot have a static variable in a constexpr function (right msvc?) 2021-09-22 16:38:41 +02:00
Michele Caini
03e363f5d9 any: added the ::assign function to copy/move assign the wrapped variable 2021-09-22 16:27:56 +02:00
Michele Caini
39211889b0 any (close #782):
* make const type_info * a first citizen
* further reduce vtable size
2021-09-22 12:48:25 +02:00
Michele Caini
db44549276 type_info/type_id:
* type_info is no longer default constructible
* users cannot construct type_info objects anymore
* make type_id refer to an object with static storage duration
2021-09-22 12:41:09 +02:00
Michele Caini
49e702c0c7 hashed_string: minor changes 2021-09-22 08:34:31 +02:00
Michele Caini
c9c5214b3e type_info: operator<, operator<=, operator> and operator>= 2021-09-22 08:34:18 +02:00
Michele Caini
24a537d154 meta: review conversion_helper for meta type nodes 2021-09-21 17:11:28 +02:00
Michele Caini
c32ecf171b sparse_set: added user_data field 2021-09-21 15:54:26 +02:00
Michele Caini
a62ae21628 any: const reference instead of pointer as default argument to ::data 2021-09-21 09:03:39 +02:00
Michele Caini
12f05e8f72 doc: fixed typo (close #784) 2021-09-20 08:07:05 +02:00
Michele Caini
81fb727d20 registry: improved ctx and the like (close #782) 2021-09-19 15:14:43 +02:00
Michele Caini
e7655c761d test: code coverage 2021-09-18 23:22:00 +02:00
Michele Caini
464fcf4300 test: fix a test that I've broken a couple of commits ago :) 2021-09-18 00:06:50 +02:00
Michele Caini
73b67ea9df *: review enums 2021-09-18 00:02:35 +02:00
Michele Caini
04a9c80c14 *: removed pointless continue; 2021-09-17 23:44:15 +02:00
Michele Caini
80b5ed3d22 introduced clang-format (close #733) 2021-09-17 23:42:43 +02:00
Michele Caini
be5ad379b6 *: another handful of changes to please clang-format 2021-09-17 17:21:26 +02:00
Michele Caini
13d901fbfa *: a handful of changes to please clang-format 2021-09-17 16:43:15 +02:00
Michele Caini
f7e7273e91 *: minor changes 2021-09-16 23:09:22 +02:00
Michele Caini
4b3bd265a6 meta: minor changes 2021-09-15 12:43:31 +02:00
Michele Caini
42dcec961b meta: support for multi-setters on meta data members 2021-09-15 09:32:12 +02:00
Michele Caini
6b2a3b2916 meta: prepare for multi-setters on meta data members 2021-09-14 14:57:17 +02:00
Michele Caini
930f9ca436 any: minor changes 2021-09-14 08:52:44 +02:00
Michele Caini
a96a767b9b test: code coverage 2021-09-13 19:32:23 +02:00
Michele Caini
36627dbe78 meta:
* removed meta_ctor, no alternatives provided
* removed meta_type::ctor overloads, no alternatives provided
2021-09-13 19:03:22 +02:00
Michele Caini
f86bc31cbb meta: shared lookup function to avoid unnecessary casts when searching for a meta constructor 2021-09-13 16:37:58 +02:00
Michele Caini
4a08ca4b5e meta: minor changes 2021-09-13 14:58:08 +02:00
Michele Caini
e857aa0640 meta: extrapolate can_cast_or_convert 2021-09-13 12:57:06 +02:00
Michele Caini
d3c98ad334 meta_factory: cleanup 2021-09-13 12:56:39 +02:00
Michele Caini
00dadfe14d meta: reduce the size of instantiated symbols in meta_factory 2021-09-13 12:55:07 +02:00
Michele Caini
f26fa92d47 handle: extended operator==/!= 2021-09-12 18:39:20 +02:00
Michele Caini
7458072df2 hashed_string (close #781):
* operator< and operator<=
* operator> and operator>=
2021-09-12 18:26:08 +02:00
Michele Caini
89aa2a1902 *: operator== is not defined as member if unnecessary 2021-09-12 17:52:29 +02:00
Michele Caini
7ab08779dc type_info: temporarily reintroduce type_info::index for performance reasons 2021-09-10 11:29:05 +02:00
Michele Caini
46b686910b any:
* reintroduced operation::TYPE to avoid fat any types
* added optional req parameter to data
* much faster any_cast
* much faster operator==
* internal review
2021-09-10 11:22:07 +02:00
Michele Caini
940a799207 * : minor changes 2021-09-10 00:04:23 +02:00
Michele Caini
778cee3b27 any:
* operator bool doesn't rely on the vtable
* valid but unspecified state after move converts to true
* compare type info objects to avoid future errors if the logic changes
2021-09-09 17:03:36 +02:00
Michele Caini
fb3252732b type_info: name rollback, hash_code -> hash (why should I introduce a breaking change to match a terrible name from the standard library after all?) 2021-09-09 14:49:39 +02:00
Michele Caini
608f7b75e2 any: avoid creating constexpr variables since constexpr-ness isn't guaranteed 2021-09-09 14:14:58 +02:00
Michele Caini
83853c3dee any:
* ::type() returns the object type if any, type_id<void>() otherwise
* avoid indirection when accessing the type
2021-09-09 14:00:08 +02:00
Michele Caini
8a0343ad6b any: avoid creating type_info objects if unnecessary 2021-09-09 11:44:36 +02:00
Michele Caini
92d43ce620 core: rename type_seq to type_index 2021-09-09 09:53:29 +02:00
Michele Caini
6943822fed type_info:
* make the API closer to that of std::type_info
* remove the ::seq member function
* rename :.hash to ::hash_code
2021-09-09 09:44:58 +02:00
Michele Caini
aa146c4125 type_info: avoid testing constexpr-ness because older compilers don't guarantee it 2021-09-09 09:04:04 +02:00
Michele Caini
b8ec6babb5 any:
* reduced vtable size
* internal rework
2021-09-09 00:40:06 +02:00
Michele Caini
505f4a2b4f type_info:
* constexpr support
* reduce instantiations
* reduce function calls/indirection
2021-09-09 00:20:20 +02:00
Michele Caini
1bb0d017c3 type_info: removed useless friend declaration 2021-09-08 23:43:28 +02:00
Michele Caini
f33ce615d9 meta: suppress warnings due to ignored qualifiers on return types 2021-09-08 11:35:50 +02:00
Michele Caini
0edb49d7c6 core: minor changes 2021-09-08 09:13:54 +02:00
Michele Caini
1fa5a03605 test: code coverage 2021-09-07 17:13:53 +02:00
Michele Caini
fc6bda5cd8 meta: turned an useless function into a constexpr value 2021-09-07 08:54:34 +02:00
Michele Caini
59589b6a71 meta: refine the conversion helper (mostly to please the toolset v141) 2021-09-06 14:51:35 +02:00
Michele Caini
57b0624a0a storage: suppress warnings for unused variables 2021-09-06 12:29:52 +02:00
Michele Caini
2f22395eea meta:
* a more robust meta_any::allow_cast (reviewed all overloads)
* removed internal meta_info dispatcher to reduce useless instantiations
* reviewed meta_conversion_helper
2021-09-06 10:19:23 +02:00
Michele Caini
21bc8d4dfb meta: add meta_conv support to references 2021-09-04 11:43:47 +02:00
Michele Caini
2e74fd8196 meta: const correctness 2021-09-04 11:42:03 +02:00
Michele Caini
fee48ab04c meta: also please toolset v141 :) 2021-09-03 18:55:51 +02:00
Michele Caini
591f885e67 meta: automatic conversion function to underlying type for enums (see #735) 2021-09-03 18:23:49 +02:00
Michele Caini
ef803016c0 meta: suppress a shadow warning 2021-09-03 17:31:15 +02:00
Michele Caini
bac51045e5 meta: automatic arithmetic conversions (see #735) 2021-09-03 14:37:52 +02:00
Michele Caini
cb5e9393a4 meta: internal changes 2021-09-03 11:42:20 +02:00
Michele Caini
097509dd2a view: add operator[] to access (eventually unwrapped) components by entity (close #775) 2021-09-02 16:05:46 +02:00
Michele Caini
6cd44248c7 core: added tuple header and unwrap_tuple utility 2021-09-02 15:32:52 +02:00
Michele Caini
1fd61fbcef meta: added missing [[maybe_unused]] to suppress warnings 2021-09-01 10:06:28 +02:00
Michele Caini
cd2245ef03 doc: fixed typo 2021-09-01 10:03:16 +02:00
Michele Caini
5ddc746915 memory: turn is_power_of_two in a constexpr function 2021-08-31 17:39:47 +02:00
Michele Caini
f7d67067ad test: increase code coverage 2021-08-30 17:06:31 +02:00
Michele Caini
d1a824f76e sparse_set/storage: cleanup 2021-08-30 16:53:20 +02:00
Michele Caini
d7b0fc09d7 storage: refine ::release_memory 2021-08-30 16:36:45 +02:00
Michele Caini
2d07a6ec1f storage:
* decouple iterator from allocator
* test iterator aliases to avoid future regressions
* internal changes/rework
2021-08-30 16:18:28 +02:00
Michele Caini
014ba5a7aa sparse_set:
* test iterator aliases to avoid future regressions
* internal changes/rework
2021-08-30 16:09:59 +02:00
Michele Caini
2f12e524dd config/sparse_set/storage: avoid power-of-two check at config level 2021-08-29 23:27:04 +02:00
Michele Caini
ea6af75e8e memory: added utility function fast_mod 2021-08-29 23:04:40 +02:00
Michele Caini
a595c6ec6f memory:
* added utility class is_power_of_two
* added variable template is_power_of_two_v
2021-08-29 22:15:33 +02:00
Michele Caini
98f785d199 memory: make to_address [[nodiscard]] 2021-08-29 22:00:05 +02:00
Michele Caini
a0ed0c864f entt_traits: removed the (mostly useless) difference_type alias 2021-08-29 19:25:23 +02:00
Michele Caini
d4ac42749e storage: minor changes 2021-08-29 19:10:18 +02:00
Michele Caini
86414671d6 sparse_set: minor changes 2021-08-29 19:09:21 +02:00
Michele Caini
6cb935982d storage: removed a couple of old (and wrong) static asserts 2021-08-29 18:43:35 +02:00
Michele Caini
39ad040d8a sparse_set: decouple iterator from allocator 2021-08-29 18:41:59 +02:00
Michele Caini
4cc3824653 test: basic_registry<...>::get_or_emplace must work for empty types 2021-08-28 09:52:46 +02:00
Michele Caini
6d3e0600a1 storage:
* increase code coverage
* remove a pretty much useless if constexpr
2021-08-28 09:52:19 +02:00
Michele Caini
b52c9c1676 test: use storage (and sigh storage mixin) from base type 2021-08-27 16:47:08 +02:00
Michele Caini
f7506251fe build system: increase ctest timeout because ASSERT_DEATH is... expensive, at least :) 2021-08-27 11:03:35 +02:00
Michele Caini
5b06f298f1 sparse_set/storage: make storage safe to use from the base (to be tested) 2021-08-26 17:52:16 +02:00
Michele Caini
dc5488a198 storage: generalized ::insert for all mixins 2021-08-26 17:14:51 +02:00
Michele Caini
23d162e9e4 sparse_set: ::emplace no longer returns the position 2021-08-26 16:13:26 +02:00
Michele Caini
de6b660b12 sparse_set/storage:
* removed basic_sparse_set<...>::emplace_back
* general cleanup
2021-08-26 15:22:29 +02:00
Michele Caini
60c175a51d storage: ::insert always fills holes before appending 2021-08-26 15:09:30 +02:00
Michele Caini
c0a39c8064 sparse_set: insert always fills holes before appending 2021-08-26 14:56:15 +02:00
Michele Caini
61f4f93cc6 sparse_set: internals review 2021-08-26 14:55:47 +02:00
Michele Caini
764404a472 doc: minor changes, updated todo list 2021-08-26 12:19:43 +02:00
Michele Caini
04da85c88a storage: avoid invoking ::page more than once in a row 2021-08-26 12:11:54 +02:00
Michele Caini
9551b7a597 storage: added empty ::get method to storage for empty types 2021-08-25 17:05:58 +02:00
Michele Caini
f1d537d035 compressed_pair:
* disable structured binding support for clang 6
* avoid using structured binding with compressed pair in the codebase
2021-08-24 13:11:21 +02:00
Michele Caini
b43e723c84 meta: reintroduce meta_type::is_array support 2021-08-24 10:13:56 +02:00
Michele Caini
5466039c1a meta: generic begin/end for meta containers 2021-08-24 09:48:59 +02:00
Michele Caini
74e11117be storage: minor changes 2021-08-24 09:00:55 +02:00
Michele Caini
e0abab2dc4 storage:
* fixed typo in the doc
* get around msvc that also accepts invalid code (again) O.o
2021-08-23 18:18:58 +02:00
Michele Caini
08ff3ff55c sparse_set: erase assertion 2021-08-23 18:15:23 +02:00
Michele Caini
0b79d99cac storage: non-copyable allocator aware container 2021-08-23 18:13:24 +02:00
Michele Caini
38f655e7b8 *: get around the fact that msvc also accepts invalid code O.o 2021-08-21 17:28:30 +02:00
Michele Caini
6f546ffe95 sparse_set: entity ::swap -> ::swap_elements 2021-08-21 17:25:38 +02:00
Michele Caini
ef8211a46e sparse_set: non-copyable allocator-aware container 2021-08-21 17:18:04 +02:00
Michele Caini
52ea5e4074 memory: added pocca/pocma/pocs utility functions 2021-08-21 17:03:07 +02:00
Michele Caini
99621cf08a memory: unfancy -> to_address (waiting for C++20) 2021-08-20 15:28:46 +02:00
Michele Caini
a9ae9ce758 test: code coverage 2021-08-20 00:32:02 +02:00
Michele Caini
fc5a529df8 core:
* added memory.hpp
* added public unfancy function
2021-08-20 00:26:25 +02:00
Michele Caini
bc1081550d storage: minor changes 2021-08-20 00:10:09 +02:00
Michele Caini
e311ab1605 test: try to also please g++-7 2021-08-19 23:32:51 +02:00
Michele Caini
994ade0638 meta_factory: suppress shadow warning 2021-08-19 23:02:28 +02:00
Michele Caini
cf9522bd3b sparse_set: ::clear honors the modality of the set 2021-08-19 17:36:16 +02:00
Michele Caini
7fd1858db0 storage: minor changes 2021-08-19 16:34:03 +02:00
Michele Caini
c41509151b sparse_set:
* (almost) allocator-aware container
* unequal containers not supported
* copying a sparse set isn't supported
2021-08-19 15:50:29 +02:00
Michele Caini
4e12853d4a runtime_view: correctly set the no_tombstone_check member 2021-08-17 11:58:49 +02:00
Michele Caini
e1fadbc9b9 registry: removed ::version/::entity (use entt_traits instead) 2021-08-16 23:30:14 +02:00
Michele Caini
3c4d13d8b9 sparse_set/view:
* added basic_sparse_set<E>::current to return known version of identifiers in set
* sparse arrays also contain updated entity versions, no more unused bits
* basic_sparse_set<E>::contains performs a strict version check
* sparse sets manage correctly foreign entities in all cases now
* no tombstone checks for multi-type views, zero-cost pointer stability model
2021-08-16 17:07:52 +02:00
Michele Caini
732159db07 registry:
* ::current no longer asserts, it returns now tombstone versions for invalid entities
* minor changes to doc and tests
2021-08-16 16:56:11 +02:00
Michele Caini
00894eaccf entity/*: minor changes to doc and tests 2021-08-16 16:52:56 +02:00
Michele Caini
17818178cf entity:
* removed null_t::operator| (use entt_traits<T>::combine instead)
* removed tombstone_t::operator| (use entt_traits<T>::combine instead)
2021-08-14 23:00:02 +02:00
Michele Caini
89c0abfada entity:
* reviewed entt_traits<T>::combine
* added entt_traits::reserved
* use entt_traits<T>::combine where it makes sense to slightly improve perf
2021-08-14 22:26:41 +02:00
Michele Caini
8bbdd92739 entity: added entt_traits<T>::combine 2021-08-14 22:24:43 +02:00
Michele Caini
f724ceb052 entity: cleanup 2021-08-14 16:14:11 +02:00
Michele Caini
b7ac85005f updated TODO 2021-08-13 23:58:57 +02:00
Michele Caini
8ec899a8e7 sigh: make scoped_connection move constructible/assignable (close #760) 2021-08-13 15:35:05 +02:00
Michele Caini
1013c6a50e meta: removed annotation support for meta properties 2021-08-12 19:54:12 +02:00
Michele Caini
2cd5d3bab3 meta: cleanup, minor changes 2021-08-12 19:01:38 +02:00
Michele Caini
d9494960a2 meta:
* removed the possibility of invoking meta_factory::prop multiple times
* further reduced instantiations due to meta properties
2021-08-11 17:11:09 +02:00
Michele Caini
c0eb6590da snapshot: include destroyed list head in the entity count (close #757) 2021-08-11 15:23:46 +02:00
Michele Caini
a9cefcb823 meta: avoid risk of name clashing on meta types and meta data members 2021-08-10 16:07:17 +02:00
Michele Caini
d1ff491010 meta:
* removed meta_type::is_member_object_pointer (no alternative provided)
* removed meta_type::is_member_function_pointer (no alternative provided)
2021-08-10 15:39:26 +02:00
Michele Caini
2aa34f05d3 meta: removed meta_type::is_array (no alternative provided) 2021-08-09 12:47:24 +02:00
Michele Caini
135d6915ee meta, review implicitly generated meta default constructors:
* reduce instantiations and remove their static objects
* these ctors are no longer returned from a direct lookup nor during iterations
2021-08-09 10:07:43 +02:00
Michele Caini
6282195b80 meta:
* removed meta_type::is_integral (no alternative provided)
* removed meta_type::is_floating_point (no alternative provided)
* added meta_type::is_arithmetic, prepare for auto-generated implicit conversions
2021-08-07 20:43:02 +02:00
Michele Caini
adec4f08c6 meta: removed meta_type::is_union (no alternative provided) 2021-08-06 12:07:09 +02:00
Michele Caini
b24fe2f122 test: increase code coverage 2021-08-06 12:06:42 +02:00
Michele Caini
7b35bcb68a meta: use enum-as-bitmask support to get rid of old fashioned enum for meta traits 2021-08-05 10:44:13 +02:00
Michele Caini
4b629045c3 core: added enum-as-bitmask support for enum classes (thanks to @TerensTare for the suggestion) 2021-08-05 10:42:42 +02:00
Michele Caini
c6ba1d05d1 view: avoid polluting global namespace with naked operator| 2021-08-04 16:46:53 +02:00
Michele Caini
3adac90573 meta: removed meta_type::is_function_pointer (no alternative provided) 2021-08-04 16:06:58 +02:00
Michele Caini
0332188b6b meta, get rid of useless info from meta_type to further reduce instantiations:
* removed meta_type::rank (no alternative provided)
* removed meta_type::extent (no alternative provided)
* removed meta_type::rmove_extent (no alternative provided)
* removed meta_type::remove_pointer ((*any).type())
2021-08-03 16:29:19 +02:00
Michele Caini
790a1e2812 view: minor changes to get around an issue of clang 2021-08-02 18:28:48 +02:00
Michele Caini
3bd1e13321 view: removed the foobar alias which was not meant to stay there 2021-08-02 18:24:49 +02:00
Michele Caini
0cd642ca11 view: ::use<T> doesn't modify the view in-place anymore, instead it returns a new view 2021-08-02 18:22:58 +02:00
Michele Caini
d5995998b0 view:
* each<T> doesn't invoke use<T> anymore under the hood
* removed ::traverse function
* minor changes
2021-08-02 18:09:38 +02:00
Michele Caini
62babb9c22 updated TODO 2021-08-01 12:02:43 +02:00
Michele Caini
b98c69521b build_system: add support for c++20 (close #751) 2021-08-01 11:41:31 +02:00
Michele Caini
6cd37b3809 view: get around an issue of msvc when using C++20 2021-08-01 11:21:05 +02:00
Michele Caini
238170d0e2 meta: some changes to make tests compile with C++20 (MSVC) 2021-08-01 11:02:05 +02:00
Michele Caini
6fb5b25530 any: don't compare arrays directly (operator== even deprecated in C++20) 2021-08-01 10:51:48 +02:00
Michele Caini
d63f9e1eff build_system: make ENTT_CXX_STD a cached string variable (not used yet, see #751) 2021-08-01 10:47:14 +02:00
Michele Caini
461865bf3b build_system: make ENTT_ID_TYPE a cached string variable 2021-08-01 10:41:28 +02:00
Michele Caini
e95d9b9cf6 doc: updated links.md 2021-08-01 10:18:21 +02:00
Michele Caini
c52b2a4fa9 entity/*:
* add owned_t utility
* change view def to basic_view<T, get_t<C...>, exclude_t<E...>>
* change group def to basic_group<T, owned_t<O...>, get_t<G...>, exclude_t<E...>>
* remove view dispatcher (reduce instantiations)
* make basic_view::traverse use the local policy
2021-08-01 10:03:45 +02:00
Michele Caini
d0ec5d2da0 dispatcher: mionr changes 2021-08-01 09:58:32 +02:00
Michele Caini
6134058abc type_traits: minor changes (coding style) 2021-08-01 09:58:19 +02:00
Michele Caini
bd4121c260 *: cleanup 2021-07-30 14:27:53 +02:00
Michele Caini
fbab047d7f doc: fixed typo (close #749) 2021-07-30 12:13:13 +02:00
Michele Caini
e216144d07 poly: optimize single function vtables (close #689) 2021-07-29 23:54:10 +02:00
Michele Caini
94d5b11191 any: rvalue any_cast no longer forces by-copy constructor (close #730) 2021-07-29 14:30:16 +02:00
Michele Caini
d3c89da2eb doc: mention vcpkg experimental feature in the readme file (close #743) 2021-07-28 14:52:56 +02:00
Michele Caini
754a8a637e doc: updated list of showcases (close #744) 2021-07-28 14:44:42 +02:00
Michele Caini
ab24a50de7 doc: fixed typo 2021-07-27 18:56:16 +02:00
Michele Caini
8099dde34b view: relax policy constraint if possible 2021-07-27 18:56:14 +02:00
Michele Caini
99198fb07f doc: added a note about the no-policy trick 2021-07-27 18:56:08 +02:00
Michele Caini
18d02a0c95 *: suppress a couple of warnings (shadow/unused) 2021-07-27 18:56:06 +02:00
Michele Caini
e6cac7d5fb group/view: remove references to basic_sparse_set 2021-07-27 18:56:03 +02:00
Michele Caini
d8d6f00fee storage: minor changes + some tests for get/get_as_tuple 2021-07-27 18:56:01 +02:00
Michele Caini
ef5c1a1099 snapshot: minor changes 2021-07-27 18:55:55 +02:00
Michele Caini
2d92d8ee67 storage:
* Removed free function get_as_tuple
* Added get_as_tuple function at storage level
2021-07-27 18:55:52 +02:00
Michele Caini
ae60266477 updated todo list 2021-07-27 18:55:49 +02:00
Michele Caini
88da5261fc component/storage:
* removed ignore_if_empty_v, added ignore_as_empty_v
* removed fake getter requirement for empty storage types
2021-07-27 18:55:46 +02:00
Michele Caini
15efe9f702 sparse_set: make capacity virtual 2021-07-27 18:55:42 +02:00
Michele Caini
badbc5c66e storage: internal review 2021-07-27 18:55:35 +02:00
Michele Caini
d6eea41e13 sparse_set: make reserve virtual 2021-07-27 18:55:31 +02:00
Michele Caini
6a2c54adf5 sparse_set: make shrink_to_fit virtual 2021-07-27 18:55:27 +02:00
Michele Caini
75d4bc7c18 doc: minor changes 2021-07-27 18:55:24 +02:00
Michele Caini
834f7feb27 storage: removed ::sort_n, capture pool and use ::get if needed 2021-07-27 18:55:21 +02:00
Michele Caini
5d2af3f9e1 storage: removed ::sort, capture pool and use ::get if needed 2021-07-27 18:55:19 +02:00
Michele Caini
60e8e4a82a doc: updated list of links (close #723) 2021-07-27 18:54:29 +02:00
Michele Caini
92e23476ab doc: updated list of similar projects (close #731) 2021-07-27 18:54:29 +02:00
Michele Caini
4560fef058 doc: updated list of showcases (close #732) 2021-07-27 18:54:29 +02:00
Michele Caini
c5d6574617 entity: updated fwd decls 2021-07-27 18:54:29 +02:00
Michele Caini
de61a0ca45 view:
* suppress warning for shadow parameter
* adjust deduced type to avoid compile-time errors
2021-07-27 18:54:29 +02:00
Michele Caini
98470caae1 view: suppress warning 2021-07-27 18:54:29 +02:00
Michele Caini
53486c067b view: minor changes 2021-07-27 18:54:29 +02:00
Michele Caini
5b805852fa view: internal iterable_storage class 2021-07-27 18:54:28 +02:00
Michele Caini
94d02eeb4e view: minor changes 2021-07-27 18:54:28 +02:00
Michele Caini
dbfec1b247 view: get rid of filter_to_array, filter is always stored as an array 2021-07-27 18:54:28 +02:00
Michele Caini
a9a1a71145 updated TODO list 2021-07-27 18:54:28 +02:00
Michele Caini
91537bf5f3 sparse_set/storage: try to please the code coverage tool 2021-07-27 18:54:28 +02:00
Michele Caini
1baad08288 storage/sparse_set: ctor review 2021-07-27 18:54:28 +02:00
Michele Caini
1c5b846488 storage: get rid of basic_storage_impl wrapper 2021-07-27 18:54:28 +02:00
Michele Caini
6867760cc4 doc: fixed typo 2021-07-27 18:54:28 +02:00
Michele Caini
516a9209b7 sparse_set/storage: no zero sized allocations on construction 2021-07-27 18:54:28 +02:00
Michele Caini
e352c953dc test: minor changes 2021-07-27 18:54:28 +02:00
Michele Caini
f455846d18 sparse_set/storage: avoid using temporary allocators 2021-07-27 18:54:28 +02:00
Michele Caini
6d45ac942d storage: store aside a compressed allocator to avoid frequent conversions 2021-07-27 18:54:28 +02:00
Michele Caini
48939abafa sparse_set/storage: suppress shadow warnings 2021-07-27 18:54:28 +02:00
Michele Caini
fbc9595f12 sparse_set: used compressed pair to hide the cost of storing allocators 2021-07-27 18:54:28 +02:00
Michele Caini
ed2c714419 compressed_pair: added support for structured binding (with tests) 2021-07-27 18:54:28 +02:00
Michele Caini
ef7731fb8b storage: use underlying allocator 2021-07-27 18:54:28 +02:00
Michele Caini
b5ec03f585 sparse_set:
* added get_allocator
* internal review
2021-07-27 18:54:28 +02:00
Michele Caini
a8b224a364 *: minor explicit names for traits types 2021-07-27 18:54:25 +02:00
Michele Caini
3f3943a233 storage: internal review 2021-07-27 18:53:49 +02:00
Michele Caini
4171b4ae47 resource_handle: add ::use_count (close #727) 2021-07-27 18:53:49 +02:00
Michele Caini
baa4c44632 compressed_pair: minor changes 2021-07-27 18:53:49 +02:00
Hussein Taher
ffed8f37de snapshot: fix warning for discarding a nodiscard (#728) 2021-07-27 18:53:49 +02:00
Michele Caini
8978a0d159 core:
* added trait is_ebco_eligible[_v]
* added class compressed_pair
* tests and doc for compressed_pair
2021-07-27 18:53:49 +02:00
Michele Caini
4d09be0cd3 view: minor changes 2021-07-27 18:53:49 +02:00
Michele Caini
987be01bd6 component: added in_place_delete_v and ignore_if_empty_v 2021-07-27 18:53:49 +02:00
Michele Caini
7f59fc6321 test: minor changes 2021-07-27 18:53:49 +02:00
Michele Caini
feeb122c0d updated todo list 2021-07-27 18:53:49 +02:00
Michele Caini
0754f108c9 sparse_set: fix an issue with assuring pages properly on emplace (close #746) 2021-07-27 18:53:09 +02:00
Michele Caini
ea82f86749 meta: fix precedence issue 2021-07-27 11:39:37 +02:00
Michele Caini
7bd217386a meta: shared simplified visit function 2021-07-27 10:08:20 +02:00
Michele Caini
1f1e02fee1 build system: test id type std::uint64_t on the CI, all platforms 2021-07-26 23:48:26 +02:00
Michele Caini
6d1e4fb3da test: make tests for entity traits work when id_type is std::uint64_t 2021-07-26 23:48:23 +02:00
Michele Caini
9090f84611 test: make tests for hashed string work when id_type is std::uint64_t 2021-07-26 23:48:19 +02:00
Michele Caini
8e5ddba173 sparse set: make vs2017 work (more or less) fine when id_type is std::uint64_t 2021-07-26 23:48:15 +02:00
Michele Caini
86fccb5071 entity: avoid UBs when id type is std::uint64_t (close #745) 2021-07-26 23:48:09 +02:00
Michele Caini
414c3baf15 meta: further reduce size of meta_any's vtable 2021-07-26 17:06:16 +02:00
Michele Caini
bbbddbf617 meta: added internal meta_trait enum to reduce memory usage due to meta node traits 2021-07-26 11:16:00 +02:00
Michele Caini
7638b5a95e meta: suppress warnings, get around visibility issue 2021-07-26 09:55:25 +02:00
Michele Caini
3df6b05c00 doc: fixed typo (close #742) 2021-07-26 09:17:11 +02:00
Michele Caini
8566c58f2b meta: cleanup, prep for hook point 2021-07-23 17:24:41 +02:00
Michele Caini
33ccb71526 meta: add cbegin/cend to meta_range 2021-07-23 15:51:26 +02:00
Michele Caini
2b07b92039 meta (prep for hook func):
* removed meta_type::reset
* added meta_reset overloads
2021-07-23 15:47:40 +02:00
Michele Caini
959bc269e4 test: get rid of inconsistent line (close #741) 2021-07-23 07:53:51 +02:00
Michele Caini
8609068dbf type_traits: try to also please gcc :) 2021-07-22 18:21:22 +02:00
Michele Caini
d6cea80768 core: make is_equality_comparable[_v] work with iterators (close #739) 2021-07-22 18:08:19 +02:00
Michele Caini
0f2d6fb324 meta_any: avoid risky fallthrough in the vtable (close #736) 2021-07-22 17:56:22 +02:00
Michele Caini
f5d303045c meta: make meta_invoke and meta_construct utilities also support lambdas 2021-07-22 17:41:50 +02:00
Michele Caini
ad61b0c84e meta: removed parent link from meta nodes 2021-07-22 17:21:09 +02:00
Michele Caini
18373bb679 meta: meta_any::allow_cast overload for meta types 2021-07-22 16:55:45 +02:00
Michele Caini
c30dfe3bfe meta: add fwd.hpp (see #735) 2021-07-22 16:02:03 +02:00
Michele Caini
4993961c16 *: removed deprecated stuff 2021-07-22 15:20:08 +02:00
Michele Caini
89aece7c28 meta: removed meta_type::is_void 2021-07-21 11:35:35 +02:00
Michele Caini
ec96946513 meta: cleanup/further reduce instantiations 2021-07-21 11:35:35 +02:00
Michele Caini
e49aa0d424 meta: simplified meta_any::try_cast 2021-07-21 11:35:35 +02:00
Michele Caini
b5c929572a meta: possibly reduce number of instantiations due to meta_invoke 2021-07-21 11:35:35 +02:00
Michele Caini
394822aa50 meta: remove internal::meta_visit, further reduce the number of instantiations 2021-07-21 11:35:35 +02:00
Michele Caini
d12ba5e527 meta: reduce lambda instantiations 2021-07-21 11:35:35 +02:00
Michele Caini
ab316bcb2e type_info: use fake vtables 2021-07-21 11:35:35 +02:00
Michele Caini
93fc08df45 meta: template info review 2021-07-21 11:35:35 +02:00
Michele Caini
266dd02ef5 meta: utility review and cleanup 2021-07-21 11:35:35 +02:00
Michele Caini
61c1e359e9 meta: cleanup/review 2021-07-21 11:35:35 +02:00
Michele Caini
32c83986e5 meta: minor changes 2021-07-21 11:35:35 +02:00
Michele Caini
f64af2e69d meta: get rid of useless boolean values in the return types of meta containers 2021-07-21 11:35:35 +02:00
Michele Caini
6e925c7cdd meta: container support review (less instantiations, faster to compile) 2021-07-21 11:35:35 +02:00
Michele Caini
5f50f776c6 meta: remove unnecessary nested alias 2021-07-21 11:35:35 +02:00
Michele Caini
946ccf3db4 meta: reduce instantiations for meta containers 2021-07-21 11:35:35 +02:00
Michele Caini
7a0aea390b meta: minor changes (const correctness) 2021-07-21 11:35:35 +02:00
Michele Caini
ff0e6315f9 doc: fixed typo 2021-07-21 11:35:35 +02:00
Michele Caini
b7fb485349 meta: meta_type::construct should not use base constructors 2021-07-21 11:35:35 +02:00
Michele Caini
45cbe66d5d now working on version 3.9.0 2021-07-21 00:18:12 +02:00
Michele Caini
bc7a6399c1 updated single include file 2021-07-21 00:14:12 +02:00
Michele Caini
2d5a3f24aa doc: updated documentation 2021-07-21 00:07:02 +02:00
Michele Caini
1639429edd registry: minor changes 2021-07-01 15:32:30 +02:00
Michele Caini
f81abf4883 add cpp.hint to .gitignore 2021-07-01 12:32:18 +02:00
Michele Caini
dcddb7d50e registry: allow non-const types in const overloads of registry context variable getters (close #720) 2021-06-30 09:35:36 +02:00
Michele Caini
42a763031c storage: minor changes 2021-06-30 08:55:21 +02:00
Michele Caini
0964ca5918 storage: turn to assure_at_least based on position to avoid errors at call site 2021-06-29 16:36:00 +02:00
Michele Caini
4e870b83cd test: suppress warnings due to suggested braces 2021-06-29 15:17:58 +02:00
Michele Caini
0b19c9be0b storage: add override specifier 2021-06-29 15:10:41 +02:00
Michele Caini
ac655902a0 storage:
* internal review for memory management
* added support for nosy destructors to ::in_place_pop
* optimized ::emplace/::insert
2021-06-29 15:05:03 +02:00
Michele Caini
e4fb293b55 sparse_set: added ::emplace_back 2021-06-29 12:37:39 +02:00
Michele Caini
d3df64ef4b sparse_set: emplace returns the slot used for insertion 2021-06-28 18:51:28 +02:00
Michele Caini
93e3d14f34 sparse_set: added ::slot to return the next slot available for insertion 2021-06-28 18:46:02 +02:00
Michele Caini
bc687d412d test: suppress some warnings due to [[nodiscard]] 2021-06-28 18:02:43 +02:00
Michele Caini
71e85b44b0 sparse_set: make ::policy [[nodiscard]] 2021-06-28 18:00:40 +02:00
Michele Caini
d4b59aff97 sparse_set: tombstone/null debug check in ::contains 2021-06-28 16:51:24 +02:00
Michele Caini
e3c21e1f3d sparse_set/storage (close #707):
* improved perf on erase/remove (and therefore also registry::destroy)
* allow to inhibit a pop from derived classes
* removed about_to_pop (virtual) function
2021-06-28 15:53:59 +02:00
Michele Caini
e012250e0a type_traits: minor changes 2021-06-28 11:43:27 +02:00
Michele Caini
c6bf82664c doc: added a note about optimized range-destroy 2021-06-28 11:20:40 +02:00
Michele Caini
c61e98009f registry/benchmark: rollback optimized remove/erase (benchmarks have shown that they are not worth it) 2021-06-28 10:19:27 +02:00
Michele Caini
44bccaaad6 basic_registry:
* added fast path to destroy
* added fast path to remove
* added fast path to erase
* minor changes
2021-06-28 09:24:12 +02:00
Michele Caini
aebca14dea view: added member type iterator_type to internal class view_iterator 2021-06-28 09:10:52 +02:00
Michele Caini
4576f27f6e sparse_set: minor changes 2021-06-28 09:10:12 +02:00
Michele Caini
0c213fca40 type_traits:
* added entt::is_iterator[_v]
* added entt::is_iterator_type[_v]
2021-06-28 09:09:55 +02:00
Michele Caini
891f596191 view: minor changes 2021-06-25 17:26:22 +02:00
Michele Caini
eb2b724902 benchmark: tombstone policy runs 2021-06-24 14:04:35 +02:00
Michele Caini
1f8c896181 registry:
* deprecated ::destroyed (use ::released instead)
* added ::release overloads (aka force-destroy)
2021-06-24 10:51:03 +02:00
Michele Caini
12b39e1fbe doc: added missing tokens 2021-06-23 16:35:00 +02:00
Michele Caini
206d31f27a registry: const ::view/::group also support non-const types (close #715) 2021-06-23 15:37:46 +02:00
Michele Caini
6709331182 resource_handle: conversion functions (close #706) 2021-06-22 18:54:27 +02:00
Michele Caini
9460e04ea5 entt_traits: review/cleanup 2021-06-22 15:39:15 +02:00
Michele Caini
462bfea733 entt_traits: review to reduce the risk of ambiguous calls 2021-06-22 13:03:32 +02:00
Michele Caini
a2d61dfaeb runtime_view: suppress warning for shadow parameter 2021-06-22 09:58:19 +02:00
Michele Caini
538425e35c doc: in-place delete and pointer stability 2021-06-22 09:53:56 +02:00
Michele Caini
2e86c1f1a2 component: add basic_component_traits aside component_traits 2021-06-22 09:52:43 +02:00
Michele Caini
8aa4d46ce0 runtime_view: support for storage policy (tombstones) 2021-06-21 15:18:13 +02:00
Michele Caini
cdf67a1421 sparse_set: public ::policy method for opaque runtime detection 2021-06-21 14:44:09 +02:00
Michele Caini
93d905d93d updated TODO 2021-06-21 13:04:46 +02:00
Michele Caini
2c35203647 view:
* split view iterator from multi-type view
* stable/packed storage policy support
2021-06-21 13:04:37 +02:00
Michele Caini
216871fe56 runtime_view: minor changes 2021-06-21 12:59:44 +02:00
Michele Caini
03511f39b1 registry:
* prevent groups from being used with tombstones
* support to compact one, several or all pools
2021-06-21 12:59:26 +02:00
Michele Caini
5ad0832b22 group: minor changes 2021-06-21 12:57:35 +02:00
Michele Caini
d49e7ba4b2 sparse_set/storage:
* added component traits (component.hpp)
* support for in-place delete (tombstones)
2021-06-21 12:56:33 +02:00
Michele Caini
a621b36389 type_traits: removed internal is_empty[_v] 2021-06-21 12:44:50 +02:00
Michele Caini
d093df02ac test: minor changes 2021-06-21 12:39:18 +02:00
Michele Caini
2e1529e78d entity:
* Updated doc
* No const-ref for basic types
2021-06-21 12:32:30 +02:00
Michele Caini
90be1db402 entity:
* extended entt_traits<T>::to_type support
* added null_t::operator|
* added tombstone_t::operator|
2021-06-04 11:01:26 +02:00
Michele Caini
29265e4181 doc: updated doxy.in file 2021-06-03 10:44:13 +02:00
Michele Caini
2689a7ef13 registry: minor changes 2021-06-03 09:06:38 +02:00
Michele Caini
88b58cf23d doc: added a note about tombstones 2021-06-03 09:06:36 +02:00
Michele Caini
e2e433480b entity/registry:
* added entt_traits<T>::reserved()
* added tombstone_t type and tombstone constant
* create-with-hint also accepts null entities (discarded)
* registry skips over tombstone versions and rejects them
2021-06-03 09:06:34 +02:00
Michele Caini
b8bc3e4e94 test: exception safety for sparse set and storage 2021-06-03 08:44:48 +02:00
Michele Caini
c28f52b816 sparse_set/storage: exception safety (kind of) 2021-06-03 08:44:43 +02:00
Michele Caini
ca34309f75 config: removed ENTT_NOEXCEPT, added ENTT_NOEXCEPTION 2021-06-03 08:44:30 +02:00
Michele Caini
ea614a0f3f entity: review of entt_traits<T>::to_type 2021-05-28 08:59:50 +02:00
Michele Caini
3e7dc7af29 entity:
* review of entt_traits design
* added static constexpr member function entt_traits::to_integral
* added static constexpr member function entt_traits::to_entity
* added static constexpr member function entt_traits::to_version
* added static constexpr member function entt_traits::to_type
* custom class identifiers must expose member type entity_field
* it's no longer required to specialize entt_traits (breaking change)
2021-05-28 08:59:50 +02:00
Michele Caini
0b3e3fd19a doc: updated links (close #709) and TODO file 2021-05-28 08:58:36 +02:00
Michele Caini
d3372dc05c organizer: wrap std::min to trick windows.h (close #710) 2021-05-28 08:54:41 +02:00
Michele Caini
7d141cb183 storage: fix move ctor/op 2021-05-27 16:16:45 +02:00
Michele Caini
755699c31b config:
* removed entt::page_size
* renamed ENTT_PAGE_SIZE to ENTT_SPARSE_PAGE
* added ENTT_PACKED_PAGE (page size for component arrays)
2021-05-25 10:07:20 +02:00
Michele Caini
acf3d4cd74 sparse_set/storage: suppress a couple of warnings 2021-05-25 10:06:55 +02:00
Michele Caini
92414c91b5 sparse_set/storage: review memory management for fancy allocators and the like 2021-05-24 11:53:45 +02:00
Michele Caini
ff67f402bb sparse_set/storage:
* better performance on insertion
* exception guarantee for nothrow default constructible entity types
2021-05-24 10:36:33 +02:00
Michele Caini
f048a3f1d8 sparse_set: minor changes 2021-05-24 10:27:30 +02:00
Michele Caini
9d39cb51cf storage/registry: review range ::insert (breaking change) 2021-05-24 10:27:30 +02:00
Michele Caini
7624a9d34c sparse_set/storage:
* exception safety guarantee (sort of)
* ::insert optimization for non random access iterators
2021-05-24 10:27:30 +02:00
Michele Caini
0fe73fb6ed storage: free memory in move assignment operator (with tests) 2021-05-24 10:27:10 +02:00
Michele Caini
ae11652493 sparse_set: free memory in move assignment operator (with tests) 2021-05-24 09:52:09 +02:00
Michele Caini
0ab46870ae updated TODO list 2021-05-21 09:00:18 +02:00
Michele Caini
a5381374b8 updated workflow 2021-05-20 11:00:42 +02:00
Michele Caini
7fae655651 updated TODO file 2021-05-19 10:49:23 +02:00
Michele Caini
3d9959c8e5 sparse_set/storage: small review and optimizations 2021-05-19 09:29:37 +02:00
Michele Caini
bc86576aa8 storage: improved performance when emplacing 2021-05-17 12:34:42 +02:00
Michele Caini
7c2bce8baf core: added entt::page_size 2021-05-17 12:07:48 +02:00
Michele Caini
b062bbf58d storage/view/group: reintroduce (opaque) ::raw functions as it ought to be 2021-05-17 11:59:51 +02:00
Michele Caini
8e5a048913 storage: updated pointer type for storage iterator 2021-05-17 10:10:54 +02:00
Michele Caini
ff642ffff7 sparse_set: updated pointer type for sparse set iterator 2021-05-17 10:09:50 +02:00
Michele Caini
656c12cebd view/group: opaque pointer type for ::data 2021-05-17 00:00:06 +02:00
Michele Caini
48f3fcf3bd doc: updated links (close #704) 2021-05-16 22:33:04 +02:00
Michele Caini
d797af695b registry: much faster range ::create 2021-05-16 00:26:57 +02:00
Michele Caini
75e0161c5f view :minor changes 2021-05-15 23:01:50 +02:00
Michele Caini
c0662816f1 updated TODO file 2021-05-14 18:24:09 +02:00
Michele Caini
415a31ce23 storage: forward allocator to base class 2021-05-14 15:12:29 +02:00
Michele Caini
6e603e2e51 sparse_set: suppress conversion warning 2021-05-14 15:12:26 +02:00
Michele Caini
9af318a767 test: minor changes 2021-05-14 15:12:23 +02:00
Michele Caini
30827120f6 registry: cleanup 2021-05-14 15:12:20 +02:00
Michele Caini
6194e12616 entity:
* allocator support for sparse set and storage
* pointer stability when assigning components
* removed ::raw functions (registry, view, group)
* to_entity returns null for invalid components
2021-05-14 15:12:16 +02:00
Michele Caini
59a27fb652 registry: deprecated ::reserve_pools 2021-05-13 11:01:46 +02:00
Michele Caini
f8ec57c2f6 *: cleanup 2021-05-11 10:50:38 +02:00
Michele Caini
844ef5e232 meta: avoid warning for unused variable 2021-05-10 09:49:44 +02:00
Michele Caini
5bf3f7b77e meta: suppress warning for extra ; 2021-05-08 17:19:06 +02:00
Michele Caini
00c0afd093 meta: avoid using y_combinator to clean up types (close #700) 2021-05-08 17:13:52 +02:00
Michele Caini
5228739c87 meta: make it work also with VS2017 2021-05-08 17:13:52 +02:00
Michele Caini
0f6d1268c7 meta: further reduced number of instantiations/size of symbols 2021-05-08 17:13:52 +02:00
Michele Caini
b2a4515d2b any: minor changes 2021-05-08 17:13:51 +02:00
Michele Caini
3576c80d33 meta_any: drastically reduce the number of instantiations/size of vtable 2021-05-08 17:13:51 +02:00
Michele Caini
77afd2d36c any: ::owner function (useful to also review meta_any) 2021-05-08 17:13:51 +02:00
Michele Caini
e6ddd5d9c2 any: drastically reduced the number of instantiations/size of vtable 2021-05-08 17:13:51 +02:00
Michele Caini
b9bf1a234e config: added ENTT_LAUNDER 2021-05-08 17:13:51 +02:00
Michele Caini
0ce9122449 any: reduce vtable size, simplify ref/cref creation 2021-05-08 17:13:51 +02:00
Michele Caini
dc41657872 any: empty vtable for void type 2021-05-08 17:13:51 +02:00
Michele Caini
64d9380031 *: updated messages for deprecated functions 2021-05-08 17:13:51 +02:00
Michele Caini
eca7484e30 doc: updated doc for any/meta_any 2021-05-08 17:13:51 +02:00
Michele Caini
2b5c393a13 meta: forward_as_meta 2021-05-08 17:13:51 +02:00
Michele Caini
0817d416a3 meta: make_meta_any -> make_meta 2021-05-08 17:13:51 +02:00
Michele Caini
ccff753305 any: forward_as_any 2021-05-08 17:13:51 +02:00
Michele Caini
11481a430a meta: minor changes 2021-05-08 17:13:51 +02:00
Michele Caini
e252b22735 test: code coverage 2021-05-08 17:13:51 +02:00
Michele Caini
a32ca8eb1d doc: updated doc for any/meta_any/poly 2021-05-08 17:13:50 +02:00
Michele Caini
1979a2279f poly: removed std::reference_wrapper support (incomplete, breaking change) 2021-05-08 17:13:50 +02:00
Michele Caini
1434f942dd *: make it work with VS2017 2021-05-08 17:13:50 +02:00
Michele Caini
955d325f07 meta_any: deprecated std::reference_wrapper support 2021-05-08 17:13:50 +02:00
Michele Caini
3fac3fe2d7 any: deprecate std::reference_wrapper support 2021-05-08 17:13:50 +02:00
Michele Caini
6ff217e74e meta: removed any reference to std::reference_wrapper/std::ref/std::cref 2021-05-08 17:13:50 +02:00
Michele Caini
cd667fe34b meta: make_meta_any 2021-05-08 17:13:50 +02:00
Michele Caini
3d6202ecfd any: make_any 2021-05-08 17:13:50 +02:00
Michele Caini
c40f0ef2bb type traits: is_equality_comparable support for nlohmann json like types (where T::value_type is T) - close #701 2021-05-08 10:43:27 +02:00
Michele Caini
c4b169edd1 registry: make ::remove and ::erase work also with iterators returned by views 2021-05-07 11:16:32 +02:00
Michele Caini
c6bba98828 registry: ::destroy review 2021-05-06 16:34:36 +02:00
Michele Caini
e5d4f1bb58 entity: deprecate handle::remove_all and registry::remove_all 2021-05-06 16:33:43 +02:00
Michele Caini
cf522d60ca doc: updated doc for handle 2021-05-06 10:31:43 +02:00
Michele Caini
daf72a7c61 entity: registry ::remove/::erase entity/range and safe/unsafe versions (close #486) 2021-05-04 11:36:02 +02:00
Michele Caini
f116ad0594 test: use iterators in the poly storage example 2021-05-03 22:29:39 +02:00
Michele Caini
e59d40834d any: reduce vtable options 2021-04-29 11:17:15 +02:00
Michele Caini
d06328af7f any: small review 2021-04-29 10:24:18 +02:00
Michele Caini
baa9d7d836 any: avoid invalid state from assignment operator for non-copyable types 2021-04-29 10:05:01 +02:00
Michele Caini
b030df55ee registry: clean up 2021-04-22 08:55:20 +02:00
Michele Caini
64eb8a2d0d sparse_set: ::remove returns number of actually removed elements 2021-04-22 08:42:35 +02:00
Michele Caini
7d7c36e0c7 registry: clean up ::remove_all 2021-04-21 16:50:33 +02:00
Michele Caini
9ad5768050 registry: clean up ::clear 2021-04-21 16:46:39 +02:00
Michele Caini
1cafbcff38 sparse_set: remove (and range-remove) if exists 2021-04-21 16:39:51 +02:00
Michele Caini
4bbf93fd0c sparse_set: remove -> erase 2021-04-21 15:46:02 +02:00
Michele Caini
120918bc37 any: refine the aggregate support to make any closer to its standard counterpart 2021-04-21 13:45:51 +02:00
Michele Caini
253448cffb sparse_set: suppress warnings for unused variables 2021-04-20 12:38:06 +02:00
Michele Caini
26f19fb90e storage: cleanup 2021-04-20 12:37:50 +02:00
Michele Caini
e8f982e909 view/group: raw() isn't bound to pointer types 2021-04-19 16:05:08 +02:00
Michele Caini
0fa433187e storage: valid state on component removal (allows component destructors to access pools) 2021-04-19 15:34:41 +02:00
Michele Caini
b0069299ea meta_any: avoid dereferencing C-style arrays 2021-04-15 11:45:10 +02:00
Michele Caini
375d5d3e9b doc: cleanup 2021-04-14 15:44:33 +02:00
Michele Caini
2d9398ae1a entity: handle review 2021-04-14 15:44:27 +02:00
Michele Caini
fc69e91636 test: refined custom id example 2021-04-14 15:44:17 +02:00
Michele Caini
5c56cbd672 process: dead -> finished 2021-04-13 09:02:29 +02:00
Michele Caini
a42255158d config: added error messages to ENTT_ASSERT 2021-04-13 09:02:29 +02:00
Michele Caini
f3d10a97df now working on v3.8.0 2021-04-13 09:02:26 +02:00
Michele Caini
5d15a3d69f updated single include file 2021-04-13 08:46:28 +02:00
Michele Caini
94292872dc ready to cut v3.7.1 (general quality of life improvements, no bug fixes, no new feature) 2021-04-12 23:37:53 +02:00
Michele Caini
5c8a1e7d10 type traits: removed is_std_hashable[_v] 2021-04-12 23:37:46 +02:00
Michele Caini
e98d8426bb meta: treat T(*)[N] as non-pointer-like types 2021-04-12 15:59:35 +02:00
Michele Caini
77f80cecf9 test: re-enable tests left commented by mistake 2021-04-12 15:59:31 +02:00
Michele Caini
bce26a1499 meta: remove dependency on std::array 2021-04-12 15:59:28 +02:00
Michele Caini
453f1c6edc test: std::strcmp ... 🤦‍♂️ 2021-04-12 15:59:20 +02:00
Michele Caini
9f8a36f2c9 any/meta: cleanup/better traits usage 2021-04-12 15:58:59 +02:00
Michele Caini
e6a5945463 meta_any: suppress a warning from clang 2021-04-12 15:56:01 +02:00
Michele Caini
60393fbc5f meta_any: decays Type on storage construction to handle correctly const T[N] types (close #687) 2021-04-12 15:55:59 +02:00
Michele Caini
b9a925dbd4 test: avoid regressions with any and deduced const T[N] types 2021-04-12 15:55:57 +02:00
Michele Caini
5dbdb1bcb5 any: internal support for both aggreagates and non-aggregates (qol enhancement :) 2021-04-12 15:55:55 +02:00
Michele Caini
d55cefc086 meta_any: no redundant copies, better perf 2021-04-12 15:55:53 +02:00
Michele Caini
5380e6d98b any: no redundant copies, better perf 2021-04-12 15:55:49 +02:00
Michele Caini
45cc24e0b8 any: favor aggregate initialization upon construction 2021-04-12 15:55:45 +02:00
Michele Caini
76bf1791eb test: cleanup 2021-04-12 13:02:23 +02:00
Michele Caini
7e9a4c4b16 view: initialize all data members on construction 2021-04-12 12:52:22 +02:00
Michele Caini
75cd5f169f *: review deduction guides 2021-04-12 12:48:36 +02:00
Michele Caini
10636c82a2 view/group: review extended iterable mode (close #686) 2021-04-07 10:33:52 +02:00
Michele Caini
04a6729963 build_system: minor changes 2021-04-06 16:49:11 +02:00
Michele Caini
b5617398ad doc: fixed typo 2021-04-06 16:47:20 +02:00
Michele Caini
da14641ccb meta: reduce instantiations due to meta_prop 2021-04-06 16:47:14 +02:00
Michele Caini
3997bd2396 meta: minor changes 2021-04-06 16:47:03 +02:00
Michele Caini
c876350e05 updated single include file 2021-04-02 12:04:31 +02:00
Michele Caini
1e07b981f0 build_system: manually install missing compilers 2021-04-01 14:42:10 +02:00
Michele Caini
756e909f5e *: (static) assert messages 2021-03-31 15:10:15 +02:00
Michele Caini
2404392daf meta_any: vtable review for empty/void types 2021-03-30 15:55:48 +02:00
Michele Caini
bf6576f5af any: use std::addressof to get the address of an object reliably 2021-03-30 15:27:49 +02:00
Michele Caini
158c2ab76e delegate: removed redundant calls to delegate constructors 2021-03-30 11:52:16 +02:00
Michele Caini
56fa50385e build system: minor changes 2021-03-29 23:32:35 +02:00
Michele Caini
eb05ab5fab test: code coverage 2021-03-29 23:30:13 +02:00
Michele Caini
7f87b637d5 workflow: use lcov to process codecoverage 2021-03-29 23:12:34 +02:00
Michele Caini
4b213adc75 test: cleanup 2021-03-29 19:03:10 +02:00
Michele Caini
7e7d5bbf17 registry: suppress a wrong warning from gcc 7.5 2021-03-29 19:00:09 +02:00
Michele Caini
e18c0a0c19 test: verify that dtor isn't invoked for a meta_any that wraps a reference 2021-03-29 17:01:05 +02:00
Michele Caini
02b6ffc771 build system: add ubsan to the CI 2021-03-29 12:19:52 +02:00
Michele Caini
340d66c24c build system: split build and sanitizer runs 2021-03-29 12:07:49 +02:00
Michele Caini
2cbf9d3620 build system: added poly.md to fake docs all target 2021-03-29 12:03:36 +02:00
Michele Caini
11e6793544 build system: cleanup 2021-03-29 12:00:42 +02:00
Michele Caini
d07e0336a2 test: fix ub in the tests 2021-03-29 10:28:58 +02:00
Michele Caini
7dbfb3d9ae test: code coverage (and try to please new gcov) 2021-03-29 08:23:30 +02:00
Michele Caini
02ef5db6e3 test: cleanup 2021-03-28 00:02:51 +01:00
Michele Caini
bb43bb5508 test: code coverage 2021-03-27 23:59:13 +01:00
Michele Caini
a771f083a7 process: added rejected state 2021-03-27 23:19:15 +01:00
Michele Caini
67f8bce1dd test: code coverage 2021-03-27 23:03:24 +01:00
Michele Caini
3b6dd23598 scheduler: small review for perf improvements 2021-03-27 22:48:54 +01:00
Michele Caini
66bbeae7da test: code coverage 2021-03-27 22:47:15 +01:00
Michele Caini
059334a861 test: code coverage 2021-03-27 18:14:36 +01:00
Michele Caini
f874c8309f registry: make vs2017 happy again 2021-03-26 15:35:11 +01:00
Michele Caini
27be812cc3 registry: small review of const correctness for components 2021-03-26 15:11:37 +01:00
Michele Caini
2adc2e97e1 registry: a "better" get 2021-03-26 14:49:42 +01:00
Michele Caini
dc4279a2d0 any/poly: review align parameter and default values (close #676) 2021-03-26 13:05:52 +01:00
Michele Caini
85bff4525a registry: non-const try_get doesn't create pools anymore 2021-03-26 09:38:58 +01:00
Michele Caini
bd648c0745 registry: avoid embedding asserts with return expressions 2021-03-25 11:13:50 +01:00
Michele Caini
d5e7005edd doc: minor changes to make doxygen happy 2021-03-25 09:46:06 +01:00
Michele Caini
8913c7ea18 poly: make vs2017 happy again 2021-03-24 13:53:02 +01:00
Michele Caini
0e2afe4f98 resource: remove the requirement to use shared_ptr (close #679) 2021-03-24 12:03:43 +01:00
Michele Caini
a936f7cdbe doc: added a note about configurable alignment requirements for any and poly 2021-03-24 12:03:43 +01:00
Michele Caini
44fa466618 poly: support for alignment requirements 2021-03-24 12:03:43 +01:00
Michele Caini
b05d84e8e3 test: minor changes 2021-03-24 12:03:43 +01:00
Michele Caini
7787c1ddd7 poly: redefine poly to basic_poly, introduce poly alias declaration 2021-03-24 12:03:43 +01:00
Michele Caini
52bfddd2e7 any: support for sbo storage alignment (close #676) 2021-03-24 12:03:43 +01:00
Michele Caini
f59adcdc37 test: no sbo overaligned any 2021-03-24 12:03:43 +01:00
Michele Caini
e996d3398f any: take in consideration alignment requirements for in_situ test (see #676) 2021-03-24 12:03:43 +01:00
Michele Caini
d73892d25a build system: more on pkg-config + updated README file 2021-03-18 13:48:38 +01:00
Alexandru-Sergiu Marton
1ebf614d79 build system: add pkg-config support (#674) 2021-03-18 13:48:38 +01:00
Michele Caini
f9c995f03f storage: cleanup 2021-03-18 13:47:53 +01:00
Michele Caini
2dcdd561f0 registry: minor changes 2021-03-17 16:10:00 +01:00
Michele Caini
90f97aa8d7 doc: updated try-it link (close #678) 2021-03-17 15:10:10 +01:00
Michele Caini
5a4b067cee view:
* removed view_pack and its tests
* added the possibility of combining different views
* updated documentation
2021-03-17 14:57:51 +01:00
Michele Caini
cabcc761c6 view: uniform design (prepare for chaining) 2021-03-16 17:14:20 +01:00
Michele Caini
a40ac1c46c registry: minor changes 2021-03-16 13:38:29 +01:00
Michele Caini
85ddfc4d21 test: clean up 2021-03-16 13:13:55 +01:00
Michele Caini
037a35df1d storage: removed storage category 2021-03-15 18:47:17 +01:00
Michele Caini
64c753023e doc: minor changes 2021-03-15 17:52:50 +01:00
Michele Caini
9d72ffb9fe test: minor changes 2021-03-12 13:52:46 +01:00
Michele Caini
4162d4fbc6 type_info: a more reliable operator bool 2021-03-12 09:33:42 +01:00
Michele Caini
a4d16bffd3 any: minor changes 2021-03-12 08:42:41 +01:00
Michele Caini
bcaf1489c0 meta: extended template info support 2021-03-11 12:17:48 +01:00
Michele Caini
a85712e8aa meta:
* removed has_meta_sequence_container[_v]
* removed has_meta_associative_container[_v]
2021-03-11 10:40:13 +01:00
Michele Caini
0f95d02cdc any: minor changes 2021-03-10 08:55:02 +01:00
Michele Caini
c151d55237 dispatcher: help std::is_copy_constructible to solve its problems with std::vector :) 2021-03-10 08:51:06 +01:00
Michele Caini
785cd6bc11 storage (close #675):
* stable sigh_storage_mixin::swap_and_pop
* added tests to avoid regressions
2021-03-09 16:09:19 +01:00
Michele Caini
8ec7e3cc97 test: suppress warnings for unused variables 2021-03-09 12:25:32 +01:00
Michele Caini
e376493970 test: removed unnecessary static functions 2021-03-09 12:17:00 +01:00
Michele Caini
08e2322d79 test: meta corner cases and re-registration 2021-03-09 12:11:25 +01:00
Michele Caini
2832767daa meta: updated doc 2021-03-09 12:10:55 +01:00
Michele Caini
62e12ee0aa meta: no need to check the instance in the dtor wrapper 2021-03-09 10:34:06 +01:00
Michele Caini
80e73c1089 meta:
* props no longer depend on the value type
* more tests for meta_prop
2021-03-09 10:26:21 +01:00
Michele Caini
4f93995bd7 test: suppress warnings + increase code coverage 2021-03-09 10:24:28 +01:00
Michele Caini
03c7dac92f meta: internal review to fully support re-registration 2021-03-09 09:50:48 +01:00
Michele Caini
d0b93f565a meta: prop key is returned by const reference rather than by copy 2021-03-08 15:22:25 +01:00
Michele Caini
1512fbae55 meta: safer factory, no-op re-registration 2021-03-08 14:52:46 +01:00
Michele Caini
4d91afdf9f meta: allow range-reset 2021-03-08 14:44:08 +01:00
Michele Caini
c239c3fea3 factory: avoid re-registration of data and type if already registered 2021-03-08 09:29:54 +01:00
Michele Caini
a0b431e8c4 doc: context aliased properties 2021-03-08 09:01:13 +01:00
Michele Caini
005e03aeb3 registry:
* context const correctness
* added support for aliased variables to context
* code coverage to avoid regressions
2021-03-06 22:51:01 +01:00
Michele Caini
6002d373e2 meta: factory ignores already existing unnamed meta objects 2021-03-05 11:32:32 +01:00
Michele Caini
a53066424b meta: cleanup/minor changes 2021-03-04 10:22:36 +01:00
Michele Caini
38ab02ff88 doc: minor changes 2021-03-03 16:49:20 +01:00
Michele Caini
fee0b29a0b registry: added missing template keyword (thanks msvc for accepting it anyway) 2021-03-03 14:24:38 +01:00
Michele Caini
2553695029 meta: minor changes 2021-03-03 12:26:59 +01:00
Michele Caini
301939983f registry: minor changes 2021-03-03 12:26:11 +01:00
Michele Caini
cd9ae1fbad poly: ::emplace support for reference types 2021-03-03 12:25:34 +01:00
Michele Caini
54e9bc86cc doc: updated links 2021-03-02 12:05:49 +01:00
Michele Caini
a1dd4c28c3 view: clean up 2021-03-02 11:21:40 +01:00
Michele Caini
6d3857f337 registry: clean up 2021-03-01 23:55:57 +01:00
Michele Caini
c4be3e731a poly: fwd.hpp 2021-02-28 23:29:36 +01:00
Michele Caini
ea4407b847 doc: fixed typo 2021-02-28 23:24:32 +01:00
Michele Caini
a62a83044f poly: make it work also with non-default Len 2021-02-27 17:34:09 +01:00
Michele Caini
e7e7b06744 doc: updated links 2021-02-26 14:36:20 +01:00
Michele Caini
2222e31885 config: ENTT_PAGE_SIZE sets the number of elements of a page, not the size in bytes 2021-02-25 00:18:04 +01:00
Michele Caini
c3f7f83c55 registry/view (close #660):
* const registry::view is no longer thread safe
* views are always valid when created from a registry, either const or not
* added a note to the doc about const registry and multithreading
2021-02-23 17:01:38 +01:00
Michele Caini
86e18f68c4 sparse_set: added unchecked operator[](pos) 2021-02-23 15:01:05 +01:00
Michele Caini
cc7d9e03d9 doc: updated list of similar projects 2021-02-23 14:39:37 +01:00
Michele Caini
c8639ae434 meta: minor changes 2021-02-23 12:00:59 +01:00
Michele Caini
85cf32516e view: minor changes 2021-02-22 16:52:54 +01:00
Michele Caini
bc85817b07 doc: updated doc for type_seq and the like 2021-02-22 16:39:42 +01:00
Michele Caini
1016394be5 *: minor changes 2021-02-22 16:35:36 +01:00
Michele Caini
de35cbf4af type_info: add conversion operators to underlying types (close #664) 2021-02-22 14:48:35 +01:00
Michele Caini
bb1acee36a entity:
* sparse_set: added optional user data to ::remove and ::clear
* sparse_set: remove the payload, it was really meh
* storage: review sigh_storage_mixin, simplified storage_adapter_mixin
* registry: pass itself twhen adding/patchin/removing components

test: updated tests for sparse set and poly storage
examples: added a test to avoid regressions on storage_adapter_mixin
2021-02-22 14:32:29 +01:00
Michele Caini
c6a2ed78c3 poly: add missing template keyword 2021-02-22 09:45:55 +01:00
Michele Caini
7729958082 doc: updated links 2021-02-21 16:39:29 +01:00
Michele Caini
ccdaec86b3 poly: added configurable sbo size (0 -> forced dyn) 2021-02-20 00:12:43 +01:00
Michele Caini
42afeef993 any: updated tests (sbo vs zeroed sbo size) 2021-02-19 23:46:44 +01:00
Michele Caini
3d06911886 test: code coverage (codecov is odd sometimes) 2021-02-19 16:26:55 +01:00
Michele Caini
98f929e41e any: try to get around an issue with clang only 2021-02-19 16:23:33 +01:00
Michele Caini
94d4e0231e *: suppress a few warnings + fix a call that msvc accepted by mistake 2021-02-19 16:11:19 +01:00
Michele Caini
e60cdb2e3b config: update ENTT_PAGE_SIZE 2021-02-19 15:50:09 +01:00
Michele Caini
550c021097 any: make VS happy :) 2021-02-19 14:56:39 +01:00
Michele Caini
1aec7f71b8 any: doc + test for configurable sbo 2021-02-19 14:45:26 +01:00
Michele Caini
07565927f2 any:
* added configurable sbo size (0 -> forced dyn)
* reverted changes for forced dyn vtable
2021-02-19 12:51:30 +01:00
Michele Caini
fda78ede1b any: prepare for in-place forced dynamic construction 2021-02-19 11:48:25 +01:00
Michele Caini
1249a4f8d3 any/meta_any/poly: as_ref is a member function, no longer an in-class friend function exported in the global namespace 2021-02-19 11:19:32 +01:00
Michele Caini
4e631f1536 meta_handle: deleted copy constructor (close #661) 2021-02-18 23:49:39 +01:00
Michele Caini
1757dbc225 registry: get around an issue of gcc 2021-02-16 17:12:02 +01:00
Michele Caini
8149e204d2 *: refine code that msvc accepts by mistake (🤦‍♂️) 2021-02-16 15:55:45 +01:00
Michele Caini
412f2ef63e doc: updated/reviewed 2021-02-16 15:08:34 +01:00
Michele Caini
ea33673daa registry: faster, better ::clear 2021-02-16 14:53:33 +01:00
Michele Caini
169b816613 entity:
* sparse_set: stable virtual remove
* basic_storage: fake get for empty types,
* sigh_storage_mixin: use swap_and_pop, drop ::remove, ignore emptiness
* poly_storage: ::remove is no longer part of its interface by default
2021-02-16 14:46:42 +01:00
Michele Caini
48edf077fc sigh_storage_mixin:
* Owner as template parameter (to make it reusable in other contexts)
* Use storage payload for retrieving the owner from the storage
2021-02-16 10:44:03 +01:00
Michele Caini
91db153710 registry: rebind pools from move constructor/assignment operator 2021-02-15 18:11:02 +01:00
Michele Caini
ea1f010b1a sparse_set/storage: swap_at and swap_and_pop are protected and non-final 2021-02-15 15:57:17 +01:00
Michele Caini
935a852745 storage:
* Removed storage_adapter_mixin (intermediate step towards the owner-as-payload model)
* The class sigh_storage_mixin expects a plain storage as a base class (intermediate step towards the owner-as-payload model)
* Further reduced the number of instantiations
* All storage classes must expose a ::patch function
2021-02-15 15:56:27 +01:00
Michele Caini
0eb6d7de3c sparse_set: added opaque payload (mainly meant to attach owners for augmented storage mixins) 2021-02-15 15:15:41 +01:00
Michele Caini
3118cd4fa5 sparse_set: added ::at to get the entity at a given position, if any 2021-02-15 14:56:18 +01:00
Michele Caini
18832fcb37 core: make type_id [[nodiscard]] (see #658) 2021-02-14 11:04:12 +01:00
Michele Caini
612554f6af registry: minor changes 2021-02-12 18:18:39 +01:00
Michele Caini
1c794591b9 sparse_set: review sort_n 2021-02-12 15:47:52 +01:00
Michele Caini
a8d95b284d meta: general renaming, size -> arity when it returns the arity of a function 2021-02-12 11:05:07 +01:00
Michele Caini
772c2dba2f type traits: add is_std_hashable[_v] (see #629) 2021-02-11 11:57:55 +01:00
Kartik Saranathan
9d1a210c97 core: PS4 build fix for entt::any (#657)
PS4 headers doesn't define __cpp_lib_launder which fails to compile with -Werror
2021-02-11 10:16:28 +01:00
Michele Caini
b04b966db1 meta:
* updated meta_any::operator== to make it consistent across boundaries
* constness review for meta_type_node
2021-02-10 15:57:20 +01:00
Michele Caini
e2c61d90e9 meta: use meta_node internally to generate template_info 2021-02-09 18:27:40 +01:00
Michele Caini
d50655c4f7 test: suppress a couple of shadow warnings 2021-02-09 18:20:42 +01:00
Michele Caini
5e4c63736b meta: added minimal class template support to meta_type 2021-02-09 17:18:24 +01:00
Michele Caini
b90b71c8c0 meta: support for proxy pointers 2021-02-09 10:57:50 +01:00
Michele Caini
722033e906 meta: split node.hpp and meta.hpp 2021-02-09 09:59:51 +01:00
Michele Caini
b6ec91fcd0 doc: updated links, removed broken one 2021-02-09 08:17:49 +01:00
Michele Caini
e94c0d003a any/registry:
* copying an entt::any always returns a copy of the contained object
* registry::storage returns references (eventually const) to the poly storage
2021-02-08 11:46:22 +01:00
Michele Caini
5c46ccb37e meta:
* avoid copies from meta_type::invoke (small perf improvement)
* meta_handle::operator* no longer available
* added meta_handle::operator bool
2021-02-08 11:33:53 +01:00
Michele Caini
fd989feea3 any: review copy, prepare for #652 2021-02-06 23:22:32 +01:00
Michele Caini
1b53e83dde any: minor changes 2021-02-06 18:35:08 +01:00
Michele Caini
3ebe827b51 doc: minor changes 2021-02-05 11:10:04 +01:00
Michele Caini
b8266e1169 registry: minor changes 2021-02-04 16:12:06 +01:00
Michele Caini
4efbe24607 test: minor changes (code coverage) 2021-02-04 12:14:35 +01:00
Michele Caini
e96ac1f6ff handle: rename ::has/::any to ::all_of/any_of 2021-02-04 12:03:38 +01:00
Michele Caini
14915368c7 test: avoid some ASSERT_DEATH that don't trigger in release mode 2021-02-04 11:50:52 +01:00
Michele Caini
0ff5c18743 registry: rename ::any to ::any_of 2021-02-04 09:45:11 +01:00
Michele Caini
240814cc85 registry: rename ::has to ::all_of 2021-02-04 09:36:28 +01:00
Michele Caini
1912350cc6 registry: use entt::any to store context variables 2021-02-04 09:21:27 +01:00
Michele Caini
146faa6008 doc: updated links 2021-02-04 08:20:03 +01:00
Michele Caini
e5fa67850b sparse_set/registry: avoids UB with sparse_set::clear and component-less registry::clear 2021-02-03 16:18:25 +01:00
Michele Caini
1377b51341 doc: minor changes 2021-02-03 13:07:39 +01:00
Ευάριστος
db67fb3539 build system: delete @bazel_tools//src/conditions:windows_msys. (#649)
This condition is no longer available from Bazel 4.0.0.
2021-02-03 10:08:38 +01:00
Michele Caini
6d216406f3 registry: minor changes 2021-02-03 10:04:16 +01:00
Michele Caini
ab225eaec1 registry: updated precondition of ::assign 2021-02-02 23:37:09 +01:00
Michele Caini
4d6d9e567d registry: minor changes 2021-02-02 13:53:51 +01:00
Michele Caini
0fcf0142ba sparse_set: prepare for detached pools 2021-02-02 12:59:07 +01:00
Michele Caini
ab907e4fef updated README 2021-02-01 10:04:54 +01:00
Michele Caini
1c1c3eb271 meta: added support to self pointer in meta_any 2021-01-29 22:13:31 +01:00
Michele Caini
a03a569534 meta: support for std::vector<bool> and the like 2021-01-29 18:58:18 +01:00
Michele Caini
309fb0fa83 test: updated storage poly example (close #644) 2021-01-29 11:10:01 +01:00
Michele Caini
14c1431848 doc: fixed typo (close #646) 2021-01-29 10:06:22 +01:00
Michele Caini
c3dc32415b meta: make meta utility public and freely available to users 2021-01-28 12:19:02 +01:00
Michele Caini
44d6246278 doc: fixed typo 2021-01-28 12:18:33 +01:00
Michele Caini
5bbd7e03f9 meta: prepare to make internal utilities public 2021-01-27 16:47:01 +01:00
Michele Caini
f5f463b411 any: relaxed checks/constraints 2021-01-26 16:45:02 +01:00
Michele Caini
6eaefbe25c doc: update doc of the runtime reflection system (close #641) 2021-01-26 08:41:41 +01:00
Michele Caini
4b5c2c85a5 doc: updated inline doc (close #640) 2021-01-26 08:36:56 +01:00
Michele Caini
0f951cd322 test: suppress a warning due to an unused variable 2021-01-25 15:22:46 +01:00
Michele Caini
cf0da32fd0 meta: iterators of meta associative containers return keys by const reference rather than by copy 2021-01-25 15:12:59 +01:00
Michele Caini
5a3085c42b registry: removed data<T> and raw<T> (use view<T>::data/::raw instead) 2021-01-25 12:29:22 +01:00
Michele Caini
42cc480bf5 doc: updated links and TODO file 2021-01-23 18:39:08 +01:00
Michele Caini
2822eda858 poly: added ::reset 2021-01-23 18:22:15 +01:00
Michele Caini
6c804b5ca2 meta: added meta_any::reset 2021-01-23 18:19:11 +01:00
Michele Caini
5149d1395e any: minor changes 2021-01-23 18:18:54 +01:00
Michele Caini
f75a2dab8d any (meta/poly): make T& in place construction work with references rather than pointers 2021-01-23 18:09:41 +01:00
Michele Caini
a045c88c61 any: added ::reset 2021-01-23 18:04:03 +01:00
Michele Caini
a5fdf917df test: minor changes (code coverage) 2021-01-22 20:13:15 +01:00
Michele Caini
80a0e47f1a core: more tests for hashed_string (code coverage) 2021-01-22 15:39:03 +01:00
Michele Caini
a304313ad4 any: more tests for the support to not copyable types (code coverage) 2021-01-22 15:28:24 +01:00
Michele Caini
05b1d5a4da meta: more tests for entt::resolve (code coverage) 2021-01-22 15:22:36 +01:00
Michele Caini
edeef3541c meta: tests (code coverage) for meta_ctor (implicitly generated default constructor) 2021-01-22 15:20:03 +01:00
Michele Caini
cd929d8e65 meta: review + tests (code coverage) for implicitly generated default constructors 2021-01-22 15:17:58 +01:00
Michele Caini
b005971427 doc: removed broken badge 2021-01-22 15:17:19 +01:00
Michele Caini
c35614fb63 meta: more tests for meta pointers (code coverage) 2021-01-22 15:08:45 +01:00
Michele Caini
18e16b09f2 any: more tests (code coverage) 2021-01-22 14:57:50 +01:00
Michele Caini
b18b76c1f0 meta: as_ref_t adapts to const objects/const-ref return types 2021-01-22 11:41:17 +01:00
Michele Caini
c9f65267ba meta: factory getter, better is_invocable_v test 2021-01-22 09:17:37 +01:00
Michele Caini
cce52c673b view: use get_as_tuple internally 2021-01-22 09:17:00 +01:00
Michele Caini
fdde216f0e doc: minor changes 2021-01-21 10:32:25 +01:00
Michele Caini
d1901a97d1 doc: minor changes 2021-01-21 09:59:43 +01:00
Michele Caini
eb2077b95b meta: suppress warnings 2021-01-20 19:51:59 +01:00
Michele Caini
fad3bdeed4 meta: ::reset doesn't remove the implicitly generated default constructors 2021-01-20 15:29:35 +01:00
Michele Caini
e1a537e547 doc: minor changes 2021-01-20 15:20:51 +01:00
Michele Caini
ba098e1199 any: use actual constructors to be more like std::any 2021-01-15 17:24:10 +01:00
Michele Caini
0ec755fccf meta: iterable base types as instances of meta_type 2021-01-15 14:34:27 +01:00
Michele Caini
997dd433b3 doc: type list and value list 2021-01-15 11:04:06 +01:00
Michele Caini
4aea1567db type_traits: make is_equality_comparable work with all major compilers 2021-01-15 10:37:14 +01:00
Michele Caini
446c8df3b4 type_traits: added type_list_diff[_t] 2021-01-15 08:36:22 +01:00
Michele Caini
f4bd868d6a type_traits: is_equality_comparable, support for standard containers 2021-01-14 12:56:31 +01:00
Michele Caini
8490264af3 doc: updated list for similar projects 2021-01-13 15:21:01 +01:00
Michele Caini
505cfdd193 any: detect C-style arrays and use delete[] when needed 2021-01-13 13:30:10 +01:00
Michele Caini
39ecd1545c meta: support for dereferencing pointers to functions 2021-01-13 13:14:21 +01:00
Michele Caini
9b80c0028d meta:
* implicitly generated default constructor (overridable)
* pointer-like to void support (no dereference)
2021-01-13 11:53:15 +01:00
Michele Caini
35276b55af any: support for non-copyable types 2021-01-12 16:24:18 +01:00
Michele Caini
eb63dd6227 meta: merged internal.hpp with meta.hpp 2021-01-11 15:08:44 +01:00
Michele Caini
9f24b3c584 meta: minor changes 2021-01-11 14:58:50 +01:00
Michele Caini
53e951d96d meta: removed internal::meta_range 2021-01-11 12:31:55 +01:00
Michele Caini
17dd386937 meta_any: minor changes 2021-01-11 11:53:06 +01:00
Michele Caini
3eb00382e7 meta: removed meta_base, meta_base_node is used internally when needed 2021-01-11 10:46:51 +01:00
Michele Caini
98b5f7a26a meta: removed meta_conv, meta_conv_node is used internally when needed 2021-01-11 10:34:30 +01:00
Michele Caini
fb70ec1cb0 doc: minor changes 2021-01-11 09:46:47 +01:00
Michele Caini
47ada87ba2 now working on version 3.7.0 2021-01-09 17:15:42 +01:00
Michele Caini
7a949dd328 updated single include file 2021-01-09 16:45:27 +01:00
Michele Caini
3982217b67 Update README.md 2021-01-08 11:59:08 +01:00
Michele Caini
8cb61da9c2 *: minor changes 2021-01-08 11:43:26 +01:00
Michele Caini
375c780d3b doc: updated links (close #630) 2021-01-07 09:23:09 +01:00
Michele Caini
f3b6c2ce5d doc: updated links (close #628) 2021-01-06 14:41:27 +01:00
Michele Caini
a7a2c96382 registry: added ::reserve_pools 2021-01-05 09:35:41 +01:00
Michele Caini
99336ef746 doc: dark mode friendly header 2021-01-04 16:33:26 +01:00
Michele Caini
72d2adfe1c *: updated copyright 2021-01-04 14:09:53 +01:00
Michele Caini
707574e294 meta: avoid warnings for unused variables 2021-01-04 12:25:55 +01:00
Michele Caini
18ffbd0027 registry: group -> group_if_exists (close #626) 2021-01-04 08:34:56 +01:00
reworks
68a0e4f39a doc: update links.md (#627) 2021-01-03 16:35:16 +01:00
Michele Caini
ddb99ced34 storage: storage type check 2021-01-02 16:42:49 +01:00
Michele Caini
cb2782bc71 registry: ::remove requires at least a component now (close #623) 2021-01-01 23:55:13 +01:00
Alex Perry
52cade9267 doc: fixed missing prefix "L" (#622) 2021-01-01 23:46:24 +01:00
Michele Caini
ec600eb2f4 any: use feature tests to get around an issue with clang 6.0.0 2020-12-31 11:40:08 +01:00
Michele Caini
61e96e2dab *: get around an issue with entt::integral_constant on (very) old compilers 2020-12-30 18:04:57 +01:00
Michele Caini
9f5433053d poly: minor changes 2020-12-30 17:18:43 +01:00
Michele Caini
d2489a57b7 doc: updated links 2020-12-30 13:12:54 +01:00
Michele Caini
e5841cd467 poly: suppress warnings for unused variables 2020-12-29 18:15:33 +01:00
Michele Caini
820d52428f doc: updated references 2020-12-29 16:51:38 +01:00
Michele Caini
ae6931b046 any: avoid unreachable code 2020-12-28 16:14:05 +01:00
Michele Caini
90a97b90bb doc: minor changes 2020-12-28 16:07:36 +01:00
Michele Caini
4b38d81f00 algorithm: use plain for rather than for_each 2020-12-27 23:07:37 +01:00
Michele Caini
8c27ca9e36 *: suppress some warnings (see #620) 2020-12-27 00:12:28 +01:00
Michele Caini
4b89fc390d poly: renaming to avoid conflicts with libraries that redefine words randomly (close #615) 2020-12-26 17:00:51 +01:00
Michele Caini
29c1766714 registry: const poly storage function 2020-12-24 16:48:07 +01:00
Michele Caini
2e5a9f117c *: cleanup 2020-12-23 19:09:31 +01:00
Michele Caini
2abcbcd30f meta: support for pointer-like types with a custom dereference operator other than operator* 2020-12-23 19:00:05 +01:00
Michele Caini
ac8bde4ea8 doc: get around an issue with doxygen 2020-12-23 17:31:08 +01:00
Michele Caini
78a13efc6c any: minor changes 2020-12-23 12:28:07 +01:00
Michele Caini
c99e859978 meta: container traits not required for const T 2020-12-23 12:27:46 +01:00
Michele Caini
ed448cb99f doc: filled some todos here and there 2020-12-23 11:30:43 +01:00
Michele Caini
5d472a1f2e test: suppress warnings 2020-12-23 09:42:40 +01:00
Michele Caini
92a938db0e meta: reduced instantiations from meta iterators 2020-12-23 09:42:38 +01:00
Michele Caini
aa979b2046 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
2020-12-23 09:42:36 +01:00
Michele Caini
2daaf899d3 any: comparison functions (==, !=) 2020-12-23 09:42:33 +01:00
Michele Caini
fa4c6bccbc meta_any: make ref to pointer-like types work in all cases 2020-12-23 09:42:31 +01:00
Michele Caini
bedea4b11a *: added error messages to static asserts 2020-12-23 09:42:29 +01:00
Michele Caini
bc415242f2 test:
* support for pointer-like to const
* internal meta_range coverage
* fully tested meta_handle
* references as arguments for meta_ctor
* invoke const function on const reference for meta_func
* references as arguments for meta_func
* as_cref_t return type for meta_func
* setter and getter on const reference for meta_data
* as_cref_t getter for meta_data
* set by const and non-const reference for meta_data
* const invoke for meta_any
* const get for meta_any
* aob
2020-12-23 09:42:26 +01:00
Michele Caini
2eeb7552d6 test:
* more on any const and non-const reference support
* poly support for const and non-const references
* poly as_ref overloads
2020-12-23 09:42:24 +01:00
Michele Caini
3a6ecb10a7 meta_sequence_container: extended support for const iterators 2020-12-23 09:42:22 +01:00
Michele Caini
f55004d1e4 test: any::as_ref for const references 2020-12-23 09:42:19 +01:00
Michele Caini
1a3304a886 meta_any:
* set is necessarily non-const
* added non-const overloads for get and invoke
2020-12-23 09:42:17 +01:00
Michele Caini
58bcbe75b7 meta: minor changes 2020-12-23 09:42:14 +01:00
Michele Caini
753df6decf poly: updated doc (const references) 2020-12-23 09:42:11 +01:00
Michele Caini
c32f947c18 meta:
* support for pointers to const types
* use std::reference_wrapper instead of std::ref to let pass constness
2020-12-23 09:42:09 +01:00
Michele Caini
6123e4ac8a any/meta/poly: as_ref const and non-const overloads 2020-12-23 09:42:07 +01:00
Michele Caini
c52f16f5b8 meta:
* meta_any: convert -> allow_cast
* support for const references
* as_cref_t policy
2020-12-23 09:42:04 +01:00
Michele Caini
3dac65a012 *: minor changes 2020-12-23 09:42:01 +01:00
Michele Caini
bc089bc4c1 any_cast: review any_cast for better support to const references 2020-12-23 09:41:58 +01:00
Michele Caini
1075ded4dc test: minor changes 2020-12-23 09:41:55 +01:00
Michele Caini
5578ea2f30 meta_any: added support for const references, reviewed meta_any::cast (T vs T &) 2020-12-23 09:41:52 +01:00
Michele Caini
ade3e58829 any: added support to const references 2020-12-23 09:41:49 +01:00
Michele Caini
ee2e88476c any: instance type is now const void * instead of void * 2020-12-23 09:41:44 +01:00
Michele Caini
1726e983ad doc: added Minecraft Earth to the list :) 2020-12-23 09:38:27 +01:00
Michele Caini
44341f0bcc doc: cleaned up example in the README 2020-12-21 13:44:50 +01:00
Michele Caini
366da3d0fe type_info: use remove_cv_t rather than remove_const_t 2020-12-17 10:17:31 +01:00
Michele Caini
f7fa2f605b poly: minor changes 2020-12-17 10:17:23 +01:00
Michele Caini
6854dea47e delegate: use type_list rather than tuple internally 2020-12-17 10:17:11 +01:00
Michele Caini
9d7e1cd99d registry: use type_list rather than tuple internally 2020-12-17 10:17:04 +01:00
Michele Caini
330f3dff77 core: updated ident, removed dependency on <tuple> 2020-12-17 10:16:54 +01:00
Michele Caini
073c46e7bf any: const void * return type for the fake vtable 2020-12-17 10:14:43 +01:00
Michele Caini
9950b2ea34 type_traits: added type_list_element[_t] and value_list_element[_v] 2020-12-17 10:13:02 +01:00
Michele Caini
a7c2a5c49b doc: updated links 2020-12-17 10:12:47 +01:00
Michele Caini
c2c39cd0d0 doc: suppress a warning from doxygen 2020-12-14 11:19:04 +01:00
Michele Caini
b6e7c36b11 delegate: use constness_as_t internally 2020-12-14 11:17:24 +01:00
Michele Caini
002f92fe1e organizer: fixed an issue for free functions with payload (close #613) 2020-12-14 11:17:10 +01:00
Michele Caini
d6d0cdf9aa build system: avoid enabling tests by default when EnTT is the top dir project 2020-12-14 08:43:23 +01:00
Martin Stump
7d002df94f build system: add MAIN_PROJECT check for test option (#610)
* Add MAIN_PROJECT check for test option
* Set MAIN_PROJECT=OFF initially
2020-12-14 08:43:18 +01:00
Michele Caini
f0d7408f94 doc: minor changes 2020-12-13 23:52:16 +01:00
Keith Rosenberg
7154678347 doc: mention aggregate initialization usage in registry::emplace, refs #592 (#593)
* update example to explain aggregate initialization usage, refs #592
* cleanup example; add details about parameterized constructors and aggregate initialization

Co-authored-by: kthrose <kthrose@netpoetica.com>
2020-12-13 23:29:01 +01:00
Fahmi Akbar Wildana
68f0743c40 doc: add @javelin/ecs in references.md (#611) 2020-12-13 23:26:22 +01:00
Michele Caini
3d5905c878 doc: added more details 2020-12-12 16:39:45 +01:00
Michele Caini
a344a1ca59 doc: typo 2020-12-12 15:37:11 +01:00
Michele Caini
5f539ddfb7 doc: updated documentation (core, entity, poly) 2020-12-12 15:13:46 +01:00
Michele Caini
a974235d10 core/entity/meta/poly:
* updated poly (static vtable, design review)
* .ref -> as_ref (any, meta_any, poly)
* poly storage
2020-12-12 15:09:29 +01:00
Michele Caini
2d17ef5c7e meta: removed as_ref tag 2020-12-12 14:58:31 +01:00
Michele Caini
dda8c209df type_traits: added type_identity trait (waiting for C++20) 2020-12-12 14:55:30 +01:00
Michele Caini
be88d5dfb8 type_info: minor changes 2020-12-12 14:51:41 +01:00
Michele Caini
4a537d82d3 minor changes 2020-12-08 19:38:31 +01:00
Michele Caini
6f36723097 runtime_view: public constructor (close #597) 2020-12-06 15:37:51 +01:00
Michele Caini
35bce924f8 handle: added support for destroy (close #598) 2020-12-03 12:17:49 +01:00
Michele Caini
9356e8ccb5 config: reintroduce ENTT_DISABLE_ASSERT (close #599) 2020-12-03 11:18:27 +01:00
Michele Caini
1ffde24ef6 *: updated TODO 2020-12-03 10:55:08 +01:00
Michele Caini
2f52bef882 poly: first implementation 2020-12-02 15:49:40 +01:00
Michele Caini
b1369582e1 type_traits: added value_list 2020-12-02 15:49:05 +01:00
Michele Caini
cf176719a8 *: minor changes here and there 2020-12-02 15:48:36 +01:00
Michele Caini
d7ed72ac06 meta_any: single vtable function to reduce instantiations and storage requirements 2020-12-02 11:10:04 +01:00
Michele Caini
83322664f1 any: doc + more tests 2020-12-02 11:10:04 +01:00
Michele Caini
5af7e96f70 meta/*: removed meta_storage, meta_any uses any internally 2020-12-02 11:10:04 +01:00
Michele Caini
c95041d7c3 core: standalone any class 2020-12-02 11:10:04 +01:00
Michele Caini
62f40dcb21 meta_storage: internal review for better memory usage 2020-12-02 11:10:04 +01:00
Michele Caini
b4f88e303a meta_storage: branchless implementation 2020-12-02 11:10:04 +01:00
Michele Caini
cd0ec69446 meta: reduced instantiations due to meta any, use a fake vtable function 2020-12-02 11:10:04 +01:00
Michele Caini
909415d167 organizer: bug fixing/tests (thanks to @Green-Sky) 2020-12-02 11:09:52 +01:00
Michele Caini
337bc6d97a view_pack: support for multiple views of the same type 2020-12-02 11:09:51 +01:00
Michele Caini
6c9fab7da1 type_traits: minor changes 2020-12-02 11:09:51 +01:00
Michele Caini
315b1f5913 type traits: added is_complete[_v] 2020-12-02 11:09:51 +01:00
Michele Caini
c2d1859858 emitter: truly const emitter, no lazy initialization 2020-12-02 11:09:51 +01:00
Michele Caini
37ba7316e0 doc: fixed typo 2020-12-02 11:09:51 +01:00
Michele Caini
fc1292b1d1 test: get around the best bug ever of msvc, toolset v141 2020-12-02 11:09:51 +01:00
Michele Caini
0507680cc1 view/group: try to get around an issue of gcc v7.5 + suppress some warnings here and there 2020-12-02 11:09:51 +01:00
Michele Caini
60475d3354 view/group: safe invalid views/groups (close #470) 2020-12-02 11:09:51 +01:00
Michele Caini
b1cd794b2c registry: truly const registry 2020-12-02 11:09:51 +01:00
Michele Caini
cd98ecff88 view: default constructible views 2020-12-02 11:09:51 +01:00
Michele Caini
f8ec4027ee group: default constructible groups 2020-12-02 11:09:51 +01:00
Michele Caini
d980a5cf44 build system: use asan on the CI 2020-12-02 11:05:00 +01:00
Michele Caini
761604d044 config: favor detection of clang over that of msvc, otherwise clang-cl will fail 2020-12-02 11:04:21 +01:00
Michele Caini
0f4161f616 build system: added older compiler versions to the CI 2020-12-02 10:46:05 +01:00
Michele Caini
4a668c97a3 type_info: get around a nasty bug of clang < 9 when using libstdc++ 2020-12-02 10:45:41 +01:00
Michele Caini
9d687c25b3 storage: safe self-move to support standard containers (close #601) 2020-12-01 22:59:14 +01:00
Michele Caini
0b73082aa0 build system: minor changes to make it work again with the CI 2020-11-20 17:05:20 +01:00
Gnik
085e1ae157 build system: prefix cmake variables with ENTT_. (#585) 2020-11-20 16:30:22 +01:00
Tom Yaxley
7c0db3203b meta: allow checking meta_any for nullptr (#591) 2020-11-20 09:43:39 +01:00
Michele Caini
bc987ed03f *: force add the version to the single include file 2020-11-20 09:43:36 +01:00
Michele Caini
57e1bf3afd doc: fixed typo 2020-11-20 09:43:34 +01:00
Michele Caini
90606bd410 hashed_string: literals are now enclosed within entt::literals, ENTT_HS_SUFFIX and ENTT_HWS_SUFFIX no longer exist (close #590) 2020-11-20 09:43:28 +01:00
Michele Caini
9744a3745c doc: updated references 2020-11-20 09:43:21 +01:00
Zoltán Kurucz
14e051f970 Fixed const, non-const types section intro in entity.md (#589) 2020-11-14 16:49:11 +01:00
Michele Caini
2396c9b6da snapshot: avoid setting the wrong version for entities during a restore (close #588) 2020-11-14 16:48:11 +01:00
Michele Caini
c386a9d140 runtime_view: removed ::empty, misleading information (breaking change) 2020-11-11 17:03:48 +01:00
Michele Caini
12847593c2 runtime_view: size -> size_hint, misleading name (breaking change) 2020-11-11 17:03:44 +01:00
Michele Caini
6cfa024ea2 doc: small changes 2020-11-11 13:15:46 +01:00
Michele Caini
4b43d99660 group: removed/reduced scope for ::raw, misleading information (breaking change) 2020-11-11 13:15:44 +01:00
Michele Caini
c1bfc29e7f group: removed ::data<T>, misleading information (breaking change) 2020-11-11 13:15:42 +01:00
Michele Caini
7e91e27f14 group: removed ::empty<T...>, misleading information (breaking change) 2020-11-11 13:15:39 +01:00
Michele Caini
f8015036a9 group: removed ::size<T>, misleading information (breaking change) 2020-11-11 13:15:37 +01:00
Michele Caini
b7ef1607dc view: public constructors and deduction guides 2020-11-09 10:31:51 +01:00
Michele Caini
b93a31dd5b helper: removed Const template parameter, used the same model of the handle class (const/non-const entity) 2020-11-08 23:34:32 +01:00
Michele Caini
fa09964f10 storage: a better iterator 2020-11-08 23:03:27 +01:00
Michele Caini
0038728be3 storage: removed const T specialization for storage_traits 2020-11-08 01:06:06 +01:00
Michele Caini
ec56651959 doc: fixed typo in core.md 2020-11-08 00:58:48 +01:00
Michele Caini
8259371d6a handle: minor changes 2020-11-08 00:46:34 +01:00
Michele Caini
d8623991c0 constness_as: updated doc 2020-11-08 00:46:03 +01:00
Michele Caini
0c205431b0 doc: updated documentation for the core classes 2020-11-08 00:37:06 +01:00
Michele Caini
58dbaf4a51 type_traits: added constness_as[_t] 2020-11-08 00:36:41 +01:00
Michele Caini
3b50ebae83 delegate: updated doc 2020-11-07 23:55:53 +01:00
Michele Caini
8b895eff7a *: minor changes to get around some nasty bugs of compilers 2020-11-06 17:29:48 +01:00
Michele Caini
70af0365bf entity:*: removed broken references to the old actor class 2020-11-06 15:00:01 +01:00
Michele Caini
bb3e3bfa1f meta: containers traits are no longer internal details only 2020-11-06 14:58:22 +01:00
Michele Caini
54aa98a752 entity/*: remove the requirement for get_as_tuple from storage classes 2020-11-06 14:49:39 +01:00
Michele Caini
3bff0aa1ea sigh_storage_mixin: don't use get_as_tuple anymore 2020-11-06 12:37:10 +01:00
Michele Caini
b012231635 registry: don't use get_as_tuple and assume that users know what they are doing 2020-11-06 11:32:39 +01:00
Michele Caini
6c6f05fc91 snapshot: cleanup 2020-11-06 11:21:46 +01:00
Michele Caini
3338d5e105 storage_traits: small review 2020-11-06 11:20:10 +01:00
Michele Caini
390ec2f0c1 entity/*: merged storage.hpp and pool.hpp 2020-11-05 18:53:22 +01:00
Michele Caini
4ebdf7a6e8 pool: pool_traits/pool_t -> storage_traits/storage_t 2020-11-05 18:48:52 +01:00
Michele Caini
6f1366dbb5 entity/*: use pool introspection rather than is_empty for filtering 2020-11-05 17:23:39 +01:00
Michele Caini
503791d3c0 view: removed chunked iteration, no real benefits so far and there is no way to make it consistent across all views in future 2020-11-05 15:10:23 +01:00
Michele Caini
902dc49de2 storage: added .get_as_tuple(entity) 2020-11-05 14:29:45 +01:00
Michele Caini
2d299f31e5 storage: removed the requirement to expose try_get 2020-11-05 12:55:34 +01:00
Michele Caini
df298587b8 type_info: suppress warnings for uninitialized members 2020-11-05 12:46:24 +01:00
Michele Caini
b9c33008d8 sparse_set: faster remove/range-remove 2020-11-05 12:21:42 +01:00
Michele Caini
ca97f1c4a3 test: oops, re-enable all bench 2020-11-05 11:10:33 +01:00
Michele Caini
effed56653 sparse_set: a better swap 2020-11-05 10:00:00 +01:00
Michele Caini
7b501aa89b sparse_set/storage: virtual sort 2020-11-04 23:52:48 +01:00
Michele Caini
6c0d0d465b storage: minor changes 2020-11-04 17:19:40 +01:00
Michele Caini
a52bd20912 registry: minor changes 2020-11-04 17:05:22 +01:00
Michele Caini
aabcc445ee *: minor changes 2020-11-04 16:59:35 +01:00
Michele Caini
d491e504cc type_info: small review 2020-11-04 10:49:30 +01:00
Michele Caini
3142e430e7 hashed_string: constexpr ::value suitable for uses with string views 2020-11-04 10:48:40 +01:00
Michele Caini
b784d80a50 pool: minor changes 2020-11-04 00:08:04 +01:00
Michele Caini
7344654308 doc: cleanup 2020-11-03 23:24:59 +01:00
Michele Caini
e01b35c39c config: update default page size 2020-11-03 00:45:46 +01:00
Michele Caini
b8b2c4ee73 handle: get around an issue of VS, toolkit v141 2020-11-03 00:45:24 +01:00
Michele Caini
8cd1ce97f7 handle: it's now possible to convert a handle to a handle view and a handle view to a more restricted one (see #583) 2020-11-03 00:36:11 +01:00
Michele Caini
05b514b743 Revert "entity: minor changes"
This reverts commit af69a0a1fd.
2020-11-02 14:05:07 +01:00
Michele Caini
22596e0f5b entity: added handle_view (close #583) 2020-11-02 13:05:38 +01:00
Michele Caini
e7031794df registry: suppress some warnings (close #582) 2020-11-01 21:49:09 +01:00
Michele Caini
af69a0a1fd entity: minor changes 2020-11-01 00:29:04 +01:00
Michele Caini
52fa690764 view: added use<T> to set explicitly the type that should drive all iterations in a multi type view 2020-10-29 00:03:26 +01:00
Michele Caini
4ad411e320 traits: is_eto_eligible[_v] -> is_empty[_v], internal version 2020-10-28 22:58:26 +01:00
Michele Caini
09da190e93 entity/*: rollback erase -> remove (no longer a breaking change :) 2020-10-28 16:24:44 +01:00
Michele Caini
797dd56bb7 test: removed temporary multi storage example, added a note to the todo list for a refined example 2020-10-28 16:16:52 +01:00
Michele Caini
5e1d77fcd5 doc: updated documentation for registry remove/erase 2020-10-28 13:03:15 +01:00
Michele Caini
2820f2658b entity/: differentiate between remove and erase to avoid name clashing on the custom path (breaking changes) 2020-10-28 12:21:35 +01:00
Michele Caini
f3fc32660b *: updated TODO 2020-10-28 08:43:43 +01:00
Michele Caini
2d4b00ec24 registry: added ::destroyed, made ::assign much faster (breaking changes, close #522) 2020-10-27 23:01:28 +01:00
Michele Caini
86808f5035 doc: minor changes 2020-10-27 09:06:18 +01:00
Michele Caini
82946e2372 pool: storage_adapter -> storage_adapter_mixin 2020-10-27 00:09:32 +01:00
Michele Caini
22d117a397 doc: fixed typo (close #578) 2020-10-26 22:35:49 +01:00
Michele Caini
662cfc9fdc *: cleanup 2020-10-26 15:41:54 +01:00
Michele Caini
a3e73909cf group/view/view_pack: review 2020-10-26 15:31:00 +01:00
Michele Caini
95bafc8ced *: try to get around an issue of gcc v7.5 2020-10-26 15:29:58 +01:00
Michele Caini
05f1906f77 *: get around an issue with clang 2020-10-26 12:43:55 +01:00
Michele Caini
dbbb131424 view_pack: added more functionalities 2020-10-26 12:38:45 +01:00
Michele Caini
fc7ec35242 doc/test: minor changes 2020-10-26 12:29:45 +01:00
Michele Caini
7ac10472dc view/group: small review 2020-10-26 10:50:17 +01:00
Michele Caini
d255889c5c group: added reverse iterators, rbegin and rend to iterable groups 2020-10-26 08:55:17 +01:00
Michele Caini
7662da22fc view: added reverse iterators, rbegin and rend to iterable views 2020-10-25 23:19:56 +01:00
Michele Caini
64cc200df0 test: code coverage 2020-10-25 15:13:13 +01:00
Michele Caini
63c983683c meta: avoid shadow warnings 2020-10-25 15:13:13 +01:00
Michele Caini
92f79c99f7 meta: review overloaded meta functions 2020-10-25 15:13:13 +01:00
Innokentiy Alaytsev
24f937fe4f [meta] Meta-function overload support (#538)
Now meta-functions can be overloaded. When a function with a duplicate
identifier is registered, it's added into the meta-type function list after the
first meta-function with the same id. During the invocation, the meta-functions
with the requested id are iterated, and the best matching one is chosen. The
overload that doesn't require any type conversions or the minimal number of
those is considered the best match. If none of the overloads matches the given
arguments or if there are multiple matching overloads requiring the same number
of type casts then the invocation will fail the same way it happens in C++.

Signed-off-by: Innokentiy Alaytsev <alaitsev@gmail.com>
2020-10-25 15:13:13 +01:00
Michele Caini
47bb682890 doc: updated links 2020-10-23 21:16:38 +02:00
codylico
9ab674ef9a doc: add a note on registry::try_get (#576) 2020-10-23 23:12:35 +02:00
Michele Caini
83eb0de916 doc: updated links 2020-10-22 09:11:52 +02:00
Koward
6359a12dbb doc: Unreal Engine 4 usage instructions (#574) 2020-10-22 09:09:00 +02:00
Michele Caini
eb8e96f413 example: multi instance storage 2020-10-21 08:40:03 +02:00
Michele Caini
138bd96167 doc: updated links 2020-10-21 08:34:22 +02:00
Michele Caini
0d5ea4711d pool/storage: split storage_adapter from basic_storage 2020-10-20 09:45:11 +02:00
Michele Caini
fa4212f07b storage_adapter: extended ::remove 2020-10-20 08:54:58 +02:00
Michele Caini
c7635a7e3d *: updated todo list 2020-10-20 08:23:21 +02:00
Michele Caini
3923c4cfd2 test: more tests, suppress warnings 2020-10-19 22:46:37 +02:00
Michele Caini
6ad884080c meta_func/meta_ctor: support for registering external member functions 2020-10-19 22:38:08 +02:00
Michele Caini
c578a43611 doc: updated doxy file 2020-10-19 12:24:35 +02:00
Michele Caini
aebfa7161f registry: extended ::remove 2020-10-19 12:01:04 +02:00
Michele Caini
682bc502e2 view_pack: minor changes 2020-10-19 09:08:49 +02:00
Michele Caini
cf018ff74c entity: updated operator==/operator!= (close #573) 2020-10-18 23:37:18 +02:00
Michele Caini
5a9cb251ad doc: updated links 2020-10-18 23:24:48 +02:00
Jan Niklas Hasse
bbbf5a5edf Allow compilation for Windows with GNU-like compilers (#566)
Besides MSVC (and compatible compilers like clang-cl) there's also GCC
(MinGW) and GNU-like Clang on Windows. Therefore setting command line
flags in CMake should check for MSVC instead of $<PLATFORM_ID:Windows>.
2020-10-17 18:26:50 +02:00
Michele Caini
7df0449100 view_pack: suppress a shadow warning caused by an unused variable 2020-10-17 18:22:26 +02:00
Michele Caini
820add87ea test: gtest is now working as expected (close #571) 2020-10-17 18:19:49 +02:00
Michele Caini
9a574aa00c doc: more on view_pack 2020-10-17 18:11:09 +02:00
Michele Caini
10da82a331 view_pack: ::each allows to remove the entity from the callback 2020-10-17 18:08:43 +02:00
Michele Caini
26c816e78c type_traits: is_applicable[_v] and is_applicable_r[_v] for tuples 2020-10-17 17:51:58 +02:00
Michele Caini
808e238384 view/group: full callback is tested first now (breaking changes) 2020-10-17 17:19:38 +02:00
Michele Caini
ff068e032b test: code coverage 2020-10-17 00:30:15 +02:00
Michele Caini
5072e96277 view_pack: get around an issue of VS2017 2020-10-17 00:19:27 +02:00
Michele Caini
c55c1c0615 *: view_pack class and tests 2020-10-16 23:59:44 +02:00
Michele Caini
9983faef70 view/group: consistent ::get without template arguments (breaking changes) 2020-10-16 16:15:04 +02:00
Michele Caini
70a264e939 view: updated noexcept-ness for iterators 2020-10-16 09:55:09 +02:00
Michele Caini
9ef6008c67 doc: updated links 2020-10-16 08:29:09 +02:00
Michele Caini
5a3e816544 view/groups: extended get (breaking changes) 2020-10-15 17:02:50 +02:00
Michele Caini
3e385fb884 view/group: minor changes 2020-10-15 16:41:06 +02:00
Michele Caini
fa5cce7477 pool/registry: rename to avoid name clash with virtual functions 2020-10-15 16:13:41 +02:00
Michele Caini
b2de76e8a0 test: temporary workaround for an upstream regression in googletest (see #571) 2020-10-15 15:27:40 +02:00
Michele Caini
edb363b236 sparse_set: avoid comparisons between different types 2020-10-15 15:23:56 +02:00
Michele Caini
12dcfdb5e1 view: candidate selection happens on construction only 2020-10-15 15:23:32 +02:00
Michele Caini
86c1dd7f32 test: suppress some warnings here and there 2020-10-15 15:11:15 +02:00
Michele Caini
d8ff4285da registry: suppress warnings for uninitialized variable 2020-10-15 15:11:05 +02:00
Michele Caini
7effde0478 view: minor changes 2020-10-15 12:52:16 +02:00
Michele Caini
559ee931fb view/group: proxy() -> each() (breaking changes - I know, I shouldn't have changed it before) 2020-10-15 10:06:00 +02:00
Michele Caini
cb27a7fe3e pool: storage adapter and signal mixin are now independent from each other 2020-10-15 09:03:14 +02:00
Michele Caini
c33a8dc2c8 doc: typo 2020-10-14 23:54:58 +02:00
Michele Caini
11fcf88b88 *: some final here and there 2020-10-14 23:54:49 +02:00
Michele Caini
4f0baa80d7 *: object_type -> value_type (breaking changes) 2020-10-14 19:50:00 +02:00
Michele Caini
ddea97bc88 storage: emplace returns the newly created object 2020-10-14 19:44:17 +02:00
Michele Caini
102c9891a0 test: code coverage for sparse set and storage range-erase 2020-10-14 19:37:28 +02:00
Michele Caini
fb4784b695 test: minor changes 2020-10-14 19:18:02 +02:00
Michele Caini
9a0650c703 pool/storage/sparse_set: pushed range-erase at the bottom of the hierarchy 2020-10-14 19:08:23 +02:00
Michele Caini
a62b93acec storage: updated except specification 2020-10-14 17:06:07 +02:00
Michele Caini
2d11bdc736 doc: minor changes 2020-10-14 16:47:39 +02:00
Michele Caini
7d263d36a0 storage: split basic_storage and storage 2020-10-14 16:44:11 +02:00
Michele Caini
4965fd5888 sparse_set: split basic_sparse_set and sparse_set 2020-10-14 16:35:16 +02:00
Michele Caini
36db8b6f59 group: use operator+ for type lists 2020-10-14 16:08:58 +02:00
Michele Caini
9e69f62a39 doc: updated doc for multi component views 2020-10-14 16:08:09 +02:00
Michele Caini
f307021cf1 view: removed multi component view ::raw and ::data (breaking changes) 2020-10-14 16:04:57 +02:00
Michele Caini
0709c402f8 test: reduced the amount of madness by a few degrees :) 2020-10-14 15:54:20 +02:00
Michele Caini
df5deb8b88 view: removed multi component view ::size (breaking changes) 2020-10-14 15:54:08 +02:00
Michele Caini
111dd40097 view: removed multi component view ::empty (breaking changes) 2020-10-14 15:54:00 +02:00
Michele Caini
c83e7d7995 view: removed multi component view ::size<T> (breaking changes) 2020-10-14 15:53:40 +02:00
Michele Caini
718f964de7 type traits: make type_list_cat work with vs2017 2020-10-14 15:37:19 +02:00
Michele Caini
ce0db9b968 type_list: removed type_list_size[_v] in favor of type_list::size (breaking changes) and added operator+ for type lists 2020-10-14 15:36:52 +02:00
Michele Caini
3f0d602353 doc: typo 2020-10-14 15:35:55 +02:00
Michele Caini
5364d778b0 doc: updated links 2020-10-14 15:30:18 +02:00
Michele Caini
0ddec227fa test: minor changes 2020-10-13 14:29:36 +02:00
Michele Caini
a5ea35ee56 meta: use type info objects rather than plain hashes (breaking changes) 2020-10-13 13:48:52 +02:00
Michele Caini
a3e03fb889 type_info: a better operator== 2020-10-13 13:48:18 +02:00
Michele Caini
b7711f0182 doc: updated documentation for meta (clost #569) 2020-10-13 12:52:38 +02:00
Michele Caini
aae199ff1c test: updated plugin examples 2020-10-13 12:41:07 +02:00
Michele Caini
8d0611a188 meta: meta_handle accepts only lvalue references as it ought to be 2020-10-08 14:08:44 +02:00
Michele Caini
958b245c3d doc: typos 2020-10-07 16:05:16 +02:00
Michele Caini
fbb77092eb doc: updated links (engine.... vrooooommm) 2020-10-06 09:32:11 +02:00
Michele Caini
ebc8328712 meta: added size_of to meta type (close #565) 2020-10-06 09:08:50 +02:00
Michele Caini
7967c6dfc8 traits: added size_of[_v] 2020-10-06 09:08:11 +02:00
Michele Caini
fca08a5162 view/group: minor changes 2020-10-05 16:12:27 +02:00
Michele Caini
49f65d6762 registry: internal rework (close #564 among the other things) 2020-10-05 12:52:55 +02:00
Michele Caini
7684e1bad5 doc: minor changes 2020-10-05 11:21:21 +02:00
Michele Caini
46e974d201 registry/pool: removed internal <pool>::patch overload 2020-10-05 08:03:36 +02:00
Michele Caini
ab55d0abc8 doc: updated links 2020-10-03 23:44:00 +02:00
Michele Caini
ed668d5144 view: updated value_type for view_proxy 2020-10-02 10:42:22 +02:00
Michele Caini
dec0f28a2b organizer: added new type to entt/entity 2020-10-02 10:41:56 +02:00
Michele Caini
de7d79f1f4 doc: added a reference to ENTT_USE_ATOMIC where it matters (close #562) 2020-10-02 10:10:55 +02:00
Michele Caini
d204d580dd type info: minor changes 2020-09-29 14:06:09 +02:00
Michele Caini
e4e38edf24 type_info: updated documentation 2020-09-29 08:52:45 +02:00
Michele Caini
3721a1f90b handle: fixed an issue with the comparison operators + minor changes 2020-09-29 08:47:14 +02:00
Vennor
897850c3eb Truly invalid entt::handle (#551) 2020-09-28 22:45:40 +02:00
Michele Caini
a22efb25c6 sparse_set/storage: avoid virtual erase 2020-09-25 17:09:07 +02:00
Michele Caini
f7e80879ae type_info: comparison operators 2020-09-25 16:43:05 +02:00
Michele Caini
bf902e6398 doc: updated links 2020-09-24 17:08:27 +02:00
Michele Caini
aed817f724 doc: updated links (entt topic on GH) 2020-09-24 09:00:01 +02:00
Michele Caini
5ac76d29fc doc: minor changes 2020-09-24 08:44:41 +02:00
Michele Caini
81311ddd03 registry: visit/ctx return type info objects and not only the hash values (breaking changes) 2020-09-24 08:25:49 +02:00
Michele Caini
3c52070243 type_info/type_id: minor changes 2020-09-24 08:25:49 +02:00
Michele Caini
9070f50658 meta_range: minor changes 2020-09-24 08:25:49 +02:00
Michele Caini
ecc3c56cb1 doc: removed all references to old type_info class template 2020-09-24 08:25:49 +02:00
Michele Caini
a86191f6e0 type traits: added type_list_contains[_v] 2020-09-24 08:25:49 +02:00
Michele Caini
aa5fdac522 type_info: it's now copyable and moveable as it ought be 2020-09-24 08:25:49 +02:00
Michele Caini
3cd32c74a1 type info: updated documentation 2020-09-24 08:25:49 +02:00
Michele Caini
2e2f6a03d9 type info: untyped type_info class and type_id functions 2020-09-24 08:25:49 +02:00
Michele Caini
25a073f20b type info: revised to support opaque type info objects (contains breaking changes) 2020-09-24 08:25:49 +02:00
Michele Caini
0fb244e381 type info: removed has_type_index[_v] utility 2020-09-24 08:25:49 +02:00
Michele Caini
631ba70b72 signal: removed unused functions 2020-09-24 08:25:49 +02:00
Michele Caini
0a1d6b2a6f doc: removed reference to ENTT_STANDALONE 2020-09-24 08:25:48 +02:00
Michele Caini
94bfa5ea25 test: get around an issue of toolset v141 2020-09-24 08:25:48 +02:00
Michele Caini
118c14bf1e lib: standalone mode is now the default 2020-09-24 08:25:48 +02:00
Michele Caini
cf395f707a doc: minor changes 2020-09-24 00:13:58 +02:00
Michele Caini
6e040fa87c doc: more on hashed strings (close #559) 2020-09-24 00:09:45 +02:00
Michele Caini
c0a7f84382 doc: correct definition for ranges (close #560) 2020-09-23 23:55:48 +02:00
Michele Caini
826d7b7c26 registry: reintroduce old function type for signals, the registry is now provided to listeners 2020-09-23 23:02:49 +02:00
Michele Caini
91e63d0f19 pool: doc related changes 2020-09-22 08:07:29 +02:00
Michele Caini
2d69e5f6ff doc: updated documentation about signals from a registry 2020-09-22 08:07:14 +02:00
Michele Caini
23f0fcd024 registry: suppress some warnings 2020-09-22 08:06:56 +02:00
Michele Caini
3fcd82abad test: suppress a warning 2020-09-22 08:06:45 +02:00
Michele Caini
d766c39791 *: minor changes 2020-09-22 08:06:41 +02:00
Michele Caini
a76c3b3baa updated TODO file 2020-09-22 08:06:35 +02:00
Michele Caini
9290b4eecc view: size -> size_hint for multi component views (close #553) 2020-09-22 08:06:30 +02:00
Michele Caini
eccfec4b4f registry: use pool_t instead of default_pool 2020-09-22 08:06:24 +02:00
Michele Caini
80aadd3874 registry/pool: split the default pool from the registry class, allow for custom pools 2020-09-22 08:06:16 +02:00
Michele Caini
9da15826db registry: component signals return only the entity 2020-09-22 08:06:04 +02:00
Michele Caini
8c403f8795 bench: added a couple of tests for recycling entities 2020-09-22 08:05:56 +02:00
Michele Caini
b010824dbd registry: faster ::create 2020-09-22 08:05:51 +02:00
Michele Caini
3340f8864f entt/entity: removed deprecated stuff 2020-09-22 08:05:23 +02:00
Michele Caini
9fb3cdfc4c now working on version 2.6 2020-09-22 08:05:04 +02:00
Michele Caini
3a3a2c2702 doc: updated links and references to similar projects 2020-09-22 08:03:55 +02:00
Michele Caini
be38919758 doc: removed references to entt::component (close #557) 2020-09-22 08:03:44 +02:00
Michele Caini
a816ccf6ee meta_any: support for pointer-like types to non-const, non-copyable types (close #556) 2020-09-22 08:03:39 +02:00
Michele Caini
5e85068e35 meta: @Innokentiy-Alaytsev was right and I was not :) 2020-09-22 08:03:33 +02:00
Michele Caini
77865ab4a1 meta: update doc + minor stylistic changes 2020-09-22 08:03:28 +02:00
Innokentiy Alaytsev
5fc6ee27f6 Fixed trailing spaces
Signed-off-by: Innokentiy Alaytsev <alaitsev@gmail.com>
2020-09-22 08:03:21 +02:00
Innokentiy Alaytsev
5995adf8b6 Implemented shortcuts for meta-functions and meta-data
The shortcut for meta-functions allows invoking them directly from an instance
of meta_type or meta_any. If the meta-function was not found or the arguments
don't match its signature an invalid meta_any object is returned.

The shortcut for meta-data allows getting and setting meta-data directly from an
instance of meta_type of meta_any. If the meta_data was not found or
getting/setting it failed and invalid meta_any object is returned.

Signed-off-by: Innokentiy Alaytsev <alaitsev@gmail.com>
2020-09-22 08:03:12 +02:00
Michele Caini
c9f47ed89a sparse_set: minor changes 2020-09-22 08:02:23 +02:00
Michele Caini
d6325ffcfa now working on v3.5.2 2020-09-22 08:02:04 +02:00
Michele Caini
9d72472114 entity: updated difference type for 32b identifiers 2020-09-03 16:22:05 +02:00
Michele Caini
102350a125 entity: removed support for 16b identifiers 2020-09-03 16:22:00 +02:00
Michele Caini
1c650cb136 observer: fixed an issue with exclusion lists (close #549) 2020-09-03 16:21:52 +02:00
Michele Caini
625e74653d test: get around comdat folding 2020-09-03 16:17:11 +02:00
Michele Caini
5bad762293 now working on version 3.5.1 2020-09-03 14:34:34 +02:00
Michele Caini
fc1ff11352 updated single include file 2020-08-31 22:47:23 +02:00
Michele Caini
0595ba384e *: suppress some warnings 2020-08-29 21:59:44 +02:00
Michele Caini
f80f5e9955 doc: updated links 2020-08-29 16:14:11 +02:00
Michele Caini
f689014c3e emitter: the event isn't const by default anymore (close #547) 2020-08-21 18:09:05 +02:00
Michele Caini
9b24655bbf dispatcher: the event isn't const by default anymore (see #547) 2020-08-21 18:02:41 +02:00
Michele Caini
c3201070a1 doc: updated FAQs (close #543) 2020-08-21 16:16:40 +02:00
Michele Caini
8a146209e4 sigh: updated documentation 2020-08-21 15:59:56 +02:00
Michele Caini
2b719726cd view: suppress warnings 2020-08-21 12:24:34 +02:00
Michele Caini
27209e4836 doc: updated links 2020-08-19 16:39:24 +02:00
Michele Caini
0497762f94 doc: typo 2020-08-19 10:41:01 +02:00
Michele Caini
b38f1e744b doc: updated README - EnTT runs everywhere 2020-08-19 10:15:16 +02:00
Michele Caini
481c49e18e doc: added a new link to similar projects 2020-08-19 10:06:38 +02:00
Michele Caini
69cf9115b5 doc: added a new link to the list of showcases (close #546) 2020-08-19 10:02:31 +02:00
Michele Caini
3eedd89efe config/core/entity: added is_eto_eligible[_v] and used it where it makes sense 2020-08-17 18:21:21 +02:00
Michele Caini
ad262ea624 entity/*: suppress some warnings here and there 2020-08-16 12:10:55 +02:00
Michele Caini
08cd8c95f7 updated todo list 2020-08-16 11:25:28 +02:00
Michele Caini
c86790c6b8 test: minor changes 2020-08-16 11:24:57 +02:00
Michele Caini
e466d9252f view: rebind the view only when possible 2020-08-14 12:12:57 +02:00
Michele Caini
02f8a0baa6 view: stable candidate computed on construction 2020-08-14 11:58:10 +02:00
Michele Caini
9f7bbe3f9d doc: updated links 2020-08-14 11:02:37 +02:00
Michele Caini
e81e0e97e0 meta: workaround for an issue of VS2019 (see #314) 2020-08-12 09:05:20 +02:00
Michele Caini
52554c3972 test: suppress a bunch of warnings 2020-08-11 16:53:03 +02:00
Michele Caini
48b6c4876a runtime view: suppress warnings for shadow variables 2020-08-11 16:52:24 +02:00
Michele Caini
99e89c2540 registry: suppress warnings for shadow variables 2020-08-11 16:52:06 +02:00
Michele Caini
0e8453d4ed entt_traits: updated difference types 2020-08-11 15:27:41 +02:00
Michele Caini
c750b746b3 meta: explicit return type to get around an issue with VS2017 2020-08-10 18:16:26 +02:00
Michele Caini
0ac07e2e83 meta: reset is now part of meta_type 2020-08-10 18:15:11 +02:00
Michele Caini
ead6cb9ca3 test: suppress warnings 2020-08-10 10:04:14 +02:00
Michele Caini
c401f9211d test: minor changes 2020-08-10 10:04:14 +02:00
Michele Caini
abb72c0a9a view: rbegin/rend 2020-08-10 10:04:13 +02:00
Michele Caini
bc9172bd43 doc: updated links 2020-08-10 10:04:13 +02:00
Michele Caini
b205a5e49d group: rbegin/rend 2020-08-10 10:04:13 +02:00
Michele Caini
fccf9642d8 view: prepare multi component views for reverse iterators 2020-08-10 10:04:13 +02:00
Michele Caini
96dd68f52b doc: typo 2020-08-10 10:04:12 +02:00
Michele Caini
7f923bb389 doc: added more details about observers (close #536) 2020-08-10 10:04:12 +02:00
Michele Caini
7ab7ebb3f6 doc: added a note about in-place sorting 2020-08-10 10:04:12 +02:00
Michele Caini
4eacb58a3e doc: minor changes 2020-08-10 10:04:12 +02:00
Michele Caini
24248832d1 group/view: explicit proxy object 2020-08-10 10:04:11 +02:00
Michele Caini
a53f0900bd view/group: make range return types explicit in preparation for faster/unsafe reverse iterators 2020-08-10 10:04:11 +02:00
Michele Caini
6a1a5a0f74 sparse set: minor changes 2020-08-10 10:04:10 +02:00
Michele Caini
65aa4e145e registry: minor changes 2020-08-10 10:04:10 +02:00
Michele Caini
cf903aa082 storage: added reverse iterators 2020-08-10 10:04:09 +02:00
Michele Caini
75dd86e8ef sparse set: added reverse iterators 2020-08-10 10:04:09 +02:00
Michele Caini
70a3d62c14 doc: udpated links 2020-08-10 10:04:08 +02:00
Michele Caini
291e3cd229 view: minor changes 2020-08-10 10:04:08 +02:00
Michele Caini
9b28c1fdd2 runtime view: suppress warning (close #540) 2020-08-10 10:01:09 +02:00
Michele Caini
d1d73da039 doc: fixed typo (close #534) 2020-07-28 21:51:59 +02:00
Michele Caini
59f041b9a9 view: minor changes 2020-07-27 10:50:11 +02:00
Michele Caini
fbf3b9ce4d doc: help doxygen not to go crazy (thanks to @erez-o for pointing this out) 2020-07-27 00:07:11 +02:00
Michele Caini
9be2e1c4c9 sigh: don't use std::forward with fake forwarding references 2020-07-26 01:09:58 +02:00
Michele Caini
a06c9f890c meta: cleanup 2020-07-25 23:35:52 +02:00
cugone
fc8e8874a9 *: fix C4003 NOMINMAX issue (#531) 2020-07-25 23:09:26 +02:00
Michele Caini
09e0f68616 view: suppress shadow warnings 2020-07-25 23:02:52 +02:00
Michele Caini
0e7e36f80d view: chunked iteration for multi-component views (close #462) 2020-07-25 18:47:20 +02:00
Michele Caini
8484dcd332 doc: updated links 2020-07-24 11:00:33 +02:00
Michele Caini
8a46296b48 meta: simplified iterators for meta containers 2020-07-24 11:00:33 +02:00
Michele Caini
b748a910b2 meta: fix an issue with meta_associative_container::meta_iterator::value 2020-07-24 11:00:33 +02:00
Michele Caini
932603eea3 *: minor changes 2020-07-24 11:00:33 +02:00
Michele Caini
5056972f79 meta: ctors and funcs also accept a meta_any * + size pair (close #528) 2020-07-24 11:00:33 +02:00
Michele Caini
d99ccca291 meta: minor changes 2020-07-24 11:00:33 +02:00
Sackhorn
1d9b26d9ec doc: backslash typo in FAQ (#532) 2020-07-24 11:00:12 +02:00
Michele Caini
3a64707c6e doc: updated links 2020-07-21 15:43:58 +02:00
Michele Caini
6f4071bd75 view: check filter array correctly (close #527) 2020-07-21 13:12:51 +02:00
Michele Caini
1354fdc613 *: suppress some warnings here and there (close #525) 2020-07-20 00:20:55 +02:00
Michele Caini
991244655a dispatcher: opaque disconnect (close #523) 2020-07-19 12:18:15 +02:00
Michele Caini
0d07d935bf *: removed redundant namespace names 2020-07-19 12:13:51 +02:00
Michele Caini
bd56b642a7 doc: updated links 2020-07-19 11:03:06 +02:00
Sackhorn
d989f0edf2 Update entity.md (#524)
Small typo fix in wiki
2020-07-19 10:20:52 +02:00
Michele Caini
f561cf9c8f build system: suppress wrong warning 2020-07-16 18:03:16 +02:00
Michele Caini
13502e5467 entity: explicit casts to suppress misleading warnings 2020-07-16 17:48:29 +02:00
Michele Caini
045c2a6f05 delegate: removed redundant calls to delegate constructor 2020-07-15 18:13:44 +02:00
Michele Caini
725e9feb68 entity: removed unused constructors from range iterators (being default constructible isn't a requirement for input iterators) 2020-07-15 17:33:21 +02:00
Michele Caini
6e45126f53 test: added explicit test for ENTT_NO_ETO 2020-07-15 16:09:41 +02:00
Michele Caini
6ebc39e038 entity: added sfinae-friendly utility for component-to-pool conversions 2020-07-14 18:25:01 +02:00
Michele Caini
8b0a7c302b storage: workaround for an issue of vs2017 2020-07-14 17:46:08 +02:00
Michele Caini
0c3e50da2f build system: try to reproduce an issue of vs2019, toolset v141 2020-07-14 15:11:39 +02:00
Michele Caini
d220cf4acc platform: minor changes 2020-07-13 23:56:01 +02:00
Innokentiy Alaytsev
eb1ce7e927 meta: Deduplicate the STL-compatible container traits (#518) 2020-07-13 23:55:19 +02:00
Michele Caini
46f6f41a6b entity: remove asserts from to_entity, it's potentially UB as from the standard 2020-07-12 23:53:20 +02:00
Michele Caini
2fa59fc43c entity: added debug asserts to to_entity 2020-07-12 16:45:00 +02:00
Michele Caini
b7763b3887 test: minor changes 2020-07-11 17:59:23 +02:00
Michele Caini
8c002b67d5 runtime view: support for excluded components (close #512) 2020-07-11 17:26:20 +02:00
Michele Caini
7692c4a377 test: ENTT_ID_TYPE -> entt::id_type 2020-07-11 15:56:30 +02:00
Michele Caini
1f0acec06c doc: minor changes 2020-07-11 15:07:23 +02:00
Michele Caini
1b5295a8fe helper: added to_entity function that returns the entity associated with a given component 2020-07-11 12:32:58 +02:00
Michele Caini
0b699a3f20 view: fixed the constrained range-each 2020-07-10 17:54:07 +02:00
Michele Caini
409d7a499d test: code coverage 2020-07-10 17:45:17 +02:00
Michele Caini
ba7428f3d6 group: small changes to get around an issue of g++ v7.5 2020-07-10 17:35:57 +02:00
Michele Caini
c12c32d26e view/group: updated range iterators (thanks to @Lawrencemm for pointing this out) 2020-07-10 15:37:43 +02:00
Michele Caini
0ca5ea0150 test: minor changes 2020-07-10 15:09:40 +02:00
Michele Caini
11ca7c7b3e group: get around an issue with g++ 2020-07-09 19:20:09 +02:00
Michele Caini
8f6c47527d doc: added a note about ranges for views and groups (close #502) 2020-07-09 18:40:41 +02:00
Michele Caini
dd28882b27 group: optimized ranges 2020-07-09 18:18:07 +02:00
Michele Caini
1b93a449b2 view: improved view ranges 2020-07-09 18:09:38 +02:00
Michele Caini
7cf2ec09b7 group: added iterable object to visit entities and components at once 2020-07-09 16:58:26 +02:00
Michele Caini
4d1952a406 view: added iterable object to visit entities and components at once 2020-07-09 16:58:07 +02:00
Michele Caini
b8d25e2327 doc: typos 2020-07-08 18:07:26 +02:00
Michele Caini
89d7c7e572 handle: better API 2020-07-06 09:39:23 +02:00
Michele Caini
75b19230eb entity: make null_t public 2020-07-06 09:24:56 +02:00
Indiana Kernick
7889ca1ca7 Non-owning entt::handle (#513) 2020-07-04 18:00:44 +02:00
Michele Caini
cec1b932bd example: custom identifier (and some fixes for the purpose) 2020-07-02 16:56:49 +02:00
Michele Caini
2c7455ea2b benchmark: use entt::id_type instead of ENTT_ID_TYPE 2020-07-02 15:07:20 +02:00
Michele Caini
edc9cc9278 type_traits: removed ENTT_OPAQUE_TYPE 2020-07-01 18:41:20 +02:00
Michele Caini
51eafaeb4f doc: mention custom types for entity identifiers 2020-07-01 18:41:00 +02:00
Michele Caini
556373d331 registry: better support for integral entity identifiers (even if not recommended) 2020-07-01 18:39:34 +02:00
Michele Caini
804cfb7482 test: use entt::to_integral instead of std::underlying_type_t for entity identifiers 2020-07-01 17:17:33 +02:00
Michele Caini
143eae0729 test: avoid using underlying_type_t with entt_traits 2020-07-01 17:10:42 +02:00
Michele Caini
29d4846de7 entity: bind to_integral to entt_traits instead of a specific enum class 2020-07-01 16:28:56 +02:00
Michele Caini
306178f371 doc: minor changes 2020-07-01 16:06:08 +02:00
Michele Caini
371b541fbc entity: make entt_traits sfinae-friendly and avoid using std::underlying_type_t to define the entity traits types 2020-07-01 15:32:04 +02:00
Oortonaut
902658fd21 Properly case entity version for 64-bit support. (#516) 2020-07-01 10:51:26 +02:00
Michele Caini
0ca8dff974 test: code coverage 2020-06-30 17:50:36 +02:00
Michele Caini
a212b054e7 platform: added support file for android ndk r17 2020-06-30 16:47:27 +02:00
Michele Caini
cccd1baa2f meta: minor changes 2020-06-26 16:04:09 +02:00
Michele Caini
5dd25aed4d meta: assoc container's ::erase/::find accept also convertible keys 2020-06-26 14:59:35 +02:00
Michele Caini
6ddc725b75 meta: minor changes 2020-06-26 12:51:44 +02:00
Michele Caini
36ab7444a0 meta: removed some deprecated functions (semantics had changed, it was already a breaking change in itself) 2020-06-26 12:43:51 +02:00
Michele Caini
a8d004334a meta: minor changes 2020-06-26 12:24:28 +02:00
Michele Caini
900398a632 resource: added prefix resource_ to all classes 2020-06-25 23:37:50 +02:00
Michele Caini
f24bb8737d deprecate actor 2020-06-25 22:55:35 +02:00
Michele Caini
cb5e9b197a doc: added links to docsforge (close #510) 2020-06-24 09:44:54 +02:00
Michele Caini
450e20ae78 meta: minor changes 2020-06-23 11:31:04 +02:00
Michele Caini
5d42a76fe5 meta: added support for convertible types to meta containers ::insert functions 2020-06-23 10:55:40 +02:00
Michele Caini
c5075a3db0 doc: minor changes (see #510) 2020-06-23 08:49:17 +02:00
Michele Caini
ad5bb5198b meta: fixed key_only member function for meta associative containers 2020-06-22 17:02:45 +02:00
Michele Caini
d306bc4a9a test: code coverage 2020-06-22 12:47:10 +02:00
Michele Caini
5c3b956542 doc: fixed some problems with doxygen (see #510) 2020-06-22 12:11:36 +02:00
Michele Caini
ade8533f28 meta: dedicate iterators for different types of meta containers 2020-06-22 11:07:57 +02:00
Michele Caini
ad3413d6ad meta: added is_key_only_meta_associative_container[_v] to type traits 2020-06-22 10:19:06 +02:00
skypjack
f3d0e3f4dd test: fixed tests for meta containers 2020-06-22 09:32:00 +02:00
Michele Caini
6e2e030ba7 meta: updated documentation 2020-06-22 01:05:48 +02:00
Michele Caini
613f993638 core/type_traits: removed is_dereferenceable[_v] 2020-06-21 23:42:07 +02:00
Michele Caini
2566e3631b meta: support for pointer-like types 2020-06-21 23:39:26 +02:00
Michele Caini
4ad6c0a8a9 meta: meta_sequence_container_traits_t -> meta_sequence_container_traits 2020-06-21 23:13:20 +02:00
Michele Caini
0369ac450e meta: added meta sequence container resize + [[nodiscard]] here and there 2020-06-21 23:08:14 +02:00
Michele Caini
ab16680cc8 type_traits: removed container detectors 2020-06-20 01:20:22 +02:00
Michele Caini
8a344cd9b2 meta: meta container support review 2020-06-20 01:17:14 +02:00
Michele Caini
4e66fb4589 test: minor changes, code coverage 2020-06-19 11:52:47 +02:00
Michele Caini
0043e3d623 meta: breaking change, meta_any::operator* dereferences the internal pointer (if any) 2020-06-19 00:15:01 +02:00
Michele Caini
ed168015bf meta: review meta_handle 2020-06-18 18:49:52 +02:00
Michele Caini
1d450ef27e meta: deprecate meta_[any|handle]::operator*, use ::ref instead 2020-06-18 18:21:12 +02:00
Michele Caini
932e681d22 meta: get rid of meta_dtor_node 2020-06-18 16:44:04 +02:00
Michele Caini
032bcd9fbe meta: minor changes 2020-06-18 16:02:26 +02:00
Michele Caini
e113fa53a4 meta: split meta_storage from meta_any 2020-06-18 14:31:06 +02:00
Michele Caini
da212dc2a4 meta: added meta_type::is_dereferenceable 2020-06-18 11:34:44 +02:00
Michele Caini
d1c5a62a9d core: type_traits, added is_dereferenceable[_v] 2020-06-18 11:30:55 +02:00
Michele Caini
0c777e10e5 doc: meta, container support 2020-06-18 10:17:50 +02:00
Michele Caini
b919b172b1 *: suppress some warnings here and there 2020-06-16 23:36:31 +02:00
Michele Caini
5dd8d05114 meta: get around an issue of msvc 2020-06-16 23:29:50 +02:00
Michele Caini
3400b32015 meta: containers support (close #499) 2020-06-16 23:21:45 +02:00
Michele Caini
2e4becad60 type_traits: sequence/associative container traits 2020-06-16 23:18:55 +02:00
Michele Caini
3d485858d5 meta: get around a bug of gcc-7, meta factory has no longer only static members 2020-06-15 00:08:46 +02:00
Michele Caini
be93643808 view: non-const excluded types are always accepted (close #507) 2020-06-14 23:42:15 +02:00
Michele Caini
f704352bae type_traits: unpack_as_t/unpack_as_v 2020-06-14 23:28:35 +02:00
Michele Caini
6683b46b07 meta: factory<Type> has now only static functions 2020-06-14 17:32:28 +02:00
Michele Caini
a1fe458338 meta: removed dependency on <algorithm> from internal.hpp 2020-06-14 16:37:38 +02:00
Michele Caini
e6328e3207 meta: minor changes 2020-06-12 17:47:39 +02:00
Michele Caini
8b1f703397 doc: updated missing description 2020-06-12 16:18:12 +02:00
Michele Caini
583c8add7e meta: make meta_handle copyable 2020-06-12 11:42:05 +02:00
Michele Caini
0266cc8e99 meta: make instances meta handles all around the codebase 2020-06-12 11:36:13 +02:00
Michele Caini
fac4132cb1 meta: meta_type rank/extent 2020-06-12 10:10:43 +02:00
Michele Caini
bf3864b2da meta: arrays are no longer indexable via meta_type::set/get 2020-06-12 09:30:29 +02:00
Michele Caini
7c21042858 sparse_set: improved performance (see #506) - thanks @Kerndog73 2020-06-12 08:19:44 +02:00
Michele Caini
d0fd9e4618 meta: range_iterator are now part of ranges 2020-06-11 19:50:32 +02:00
Michele Caini
9b53230f83 meta: cleanup 2020-06-11 17:59:29 +02:00
Michele Caini
d814b7b11e test: code coverage 2020-06-11 17:03:45 +02:00
Michele Caini
9f5421d3d4 build system: solved an issue with codecov 2020-06-11 16:48:25 +02:00
Michele Caini
6b9e5db3bf meta: updated resolve function(s) 2020-06-11 15:40:16 +02:00
Michele Caini
9eac3faf3d meta: added meta_range and meta_iterator 2020-06-11 15:27:56 +02:00
Michele Caini
252de444fc test: meta, minor changes 2020-06-11 11:00:20 +02:00
Michele Caini
c29b9cc937 test: updated tests for meta 2020-06-11 10:46:40 +02:00
Michele Caini
6ac582a771 test: more on meta_type 2020-06-11 10:10:07 +02:00
Michele Caini
04b0c9f2cf test: more on meta_func 2020-06-11 09:55:49 +02:00
Michele Caini
6b2468f033 test: more on meta_data 2020-06-11 09:53:35 +02:00
Michele Caini
2737acb114 test: added meta_type 2020-06-11 09:45:55 +02:00
Michele Caini
d03e9c48c5 tests: minor changes 2020-06-11 09:01:33 +02:00
Michele Caini
08d9cfe82c test: added meta_func 2020-06-10 17:37:21 +02:00
Michele Caini
e8ea8f91c3 test: added meta_data 2020-06-10 17:22:48 +02:00
Michele Caini
e7cfa7fda5 test: added meta_ctor 2020-06-10 16:43:02 +02:00
Michele Caini
b0b504d002 test: added meta_conv 2020-06-10 15:59:12 +02:00
Michele Caini
1da07ba60b test: added meta_base 2020-06-10 15:51:10 +02:00
Michele Caini
cedebf8145 test: added meta_prop 2020-06-10 15:42:47 +02:00
Michele Caini
29832bb2c0 test: added meta_any 2020-06-10 15:32:30 +02:00
Michele Caini
320d815d60 test: added meta_basic 2020-06-10 15:05:26 +02:00
Michele Caini
9f18401581 meta: split fixture and tests 2020-06-10 14:56:01 +02:00
Michele Caini
b3a2f0e3a3 meta: internal range/iterator support 2020-06-10 11:34:45 +02:00
Michele Caini
c00dcd31d6 meta: small review 2020-06-09 16:41:12 +02:00
Michele Caini
b836be2c84 doc: minor changes 2020-06-09 16:13:47 +02:00
Michele Caini
f89c5cc072 doc: added section pool to entity.md (close #505) 2020-06-09 09:57:57 +02:00
Michele Caini
ab7fa56bb3 doc: updated documentation for groups and nested groups 2020-06-09 09:32:36 +02:00
Michele Caini
7e624159ee registry/group: pool<T>::super is no longer required 2020-06-09 00:55:48 +02:00
Michele Caini
857a791d68 registry: sort/sortable no longer requires pool<T>::super 2020-06-08 00:44:02 +02:00
Michele Caini
171463faf5 [[nodiscard]]: try to get around an issue with VS2017 (see #501) 2020-06-07 17:34:38 +02:00
Michele Caini
2cafb49ffe entity: [[nodiscard]] (close #501) 2020-06-07 00:51:45 +02:00
Michele Caini
ae12fed5fe meta: [[nodiscard]] (see #501) 2020-06-07 00:13:20 +02:00
Michele Caini
be5547de53 core: [[nodiscard]] (see #501) 2020-06-06 23:51:08 +02:00
Michele Caini
cac50ef566 locator: [[nodiscard]] (see #501) 2020-06-06 23:43:56 +02:00
Michele Caini
57a5736942 process: [[nodiscard]] (see #501) 2020-06-06 23:42:48 +02:00
Michele Caini
167eadf699 resource: [[nodiscard]] (see #501) 2020-06-06 23:39:56 +02:00
Michele Caini
5676e420a6 signal: [[nodiscard]] (see #501) 2020-06-06 23:36:31 +02:00
Michele Caini
f5edc9e973 doc: core, type_info<T>::name 2020-06-05 14:57:24 +02:00
Michele Caini
4a305e1568 type_info: added ::name 2020-06-05 00:32:15 +02:00
Michele Caini
748ab221dd delegate: renaming of exported types 2020-06-03 23:59:58 +02:00
Michele Caini
7d786cea8f test: pass ENTT_STANDALONE definition to all targets 2020-06-03 23:42:05 +02:00
Michele Caini
1bf734338d doc: suppress a couple of warnings from doxygen 2020-06-03 17:17:10 +02:00
Michele Caini
98df1d6004 config: type index based lookup as opt-in alternative (close #490) 2020-06-03 17:13:11 +02:00
Michele Caini
290e942f3e doc: updated documentation for meta 2020-06-01 19:38:07 +02:00
Michele Caini
46d54f7e01 factory: try to get around an issue of GCC 2020-05-31 17:23:56 +02:00
Michele Caini
16e1715d06 factory: extended ::data support (close #496) 2020-05-31 17:13:21 +02:00
Michele Caini
52faa1bec5 meta: allow read-only data registration in meta (close #496) 2020-05-29 00:54:39 +02:00
Michele Caini
c8a6465688 meta: reduce instantiations 2020-05-29 00:30:20 +02:00
Alex Ames
0273b7606e snapshot: components no longer need to be copyable (#498)
Replaced calls to std::as_const with std::move so that components can
be moved into place instead of copied when reading them in from a
snapshot.
2020-05-27 23:56:48 +02:00
Michele Caini
51022cb132 meta: reduce instantiations 2020-05-27 00:51:42 +02:00
Michele Caini
78f9d87ac3 test: suppress shadow warnings 2020-05-25 23:03:28 +02:00
Michele Caini
e57135eaab delegate: support for non-capturing lambda functions (see #495) 2020-05-25 22:59:02 +02:00
Michele Caini
5fbb663529 *: added meaningful messages (?) to static asserts (close #493) 2020-05-24 00:32:08 +02:00
Michele Caini
7db0f540bd dispatcher: enqueue works fine with aggregates now (close #491) 2020-05-23 00:40:42 +02:00
Michele Caini
c8f0afb775 test: ugly workaround for an ICE of VS2017 that fails to compile valid C++ code when combined with ENTT_API 2020-05-22 00:33:17 +02:00
Michele Caini
51a5815098 registry: suppress shadow warnings 2020-05-21 22:50:38 +02:00
Michele Caini
18bd2eb729 doc: removed references to patreon account 2020-05-21 08:44:24 +02:00
Michele Caini
f04fd61879 doc: added config section 2020-05-19 00:36:45 +02:00
Michele Caini
c1527cc4c8 doc: more details on the order of components and entities when iterating through pointers returned from raw/data (close #489) 2020-05-17 23:48:43 +02:00
Michele Caini
cf1c1ed126 group: const correctness for constructor arguments 2020-05-17 22:57:16 +02:00
Michele Caini
c4ba8f96e6 view: try to get around a bug in MSVC 2020-05-17 00:44:06 +02:00
Michele Caini
350884c627 view: const correctness for constructor arguments 2020-05-17 00:18:52 +02:00
Michele Caini
aa756f6d68 doc: minor changes 2020-05-17 00:12:43 +02:00
Michele Caini
1a77bf49f5 registry: const correctness 2020-05-16 00:52:28 +02:00
Michele Caini
1b509c56fe meta: cleanup 2020-05-16 00:52:23 +02:00
Joël Lamotte
038b10c74d Added build2 package info (#484) 2020-05-14 00:38:36 +02:00
Michele Caini
39baa59625 registry: remove_if_exists returns the number of components actually removed (close #483) 2020-05-13 00:20:44 +02:00
Michele Caini
3fc091ebb2 view: removed deprecated functions 2020-05-12 00:24:39 +02:00
Michele Caini
a557e133d3 group: removed deprecated functions 2020-05-12 00:18:42 +02:00
Michele Caini
7d4f10ccc6 registry: removed deprecated functions 2020-05-12 00:12:49 +02:00
Michele Caini
39a15bef12 snapshot: removed deprecated functions 2020-05-11 16:38:12 +02:00
Michele Caini
92c59f3ea1 registry: removed the dependency on the snapshot stuff 2020-05-11 16:38:12 +02:00
Michele Caini
226bd44e2c meta: removed deprecated functions 2020-05-11 16:38:12 +02:00
Michele Caini
78d43a49c6 observer: removed deprecated functions 2020-05-11 16:38:12 +02:00
Michele Caini
471651ac5a storage: removed deprecated functions 2020-05-11 16:38:12 +02:00
Michele Caini
89515b0e30 sparse set: removed deprecated functions 2020-05-11 16:38:12 +02:00
Michele Caini
1d61c0d970 build system: updated version, now working on v3.5.0 2020-05-11 16:38:12 +02:00
Michele Caini
35c3acbade doc: added a link to the discord server 2020-05-11 16:37:18 +02:00
Michele Caini
58a2c6a13a updated single include file 2020-05-10 16:14:27 +02:00
Michele Caini
bf0160adbd registry: removed useless check 2020-05-08 23:27:53 +02:00
Michele Caini
dfbc92dd3e test: code coverage 2020-05-08 23:17:36 +02:00
Michele Caini
85b0bbfd55 snapshot: suppress shadow warnings 2020-05-07 17:20:25 +02:00
Michele Caini
fb2a93dc05 snapshot: updated documentation 2020-05-07 16:25:51 +02:00
Michele Caini
4ac46bf19d snapshot: registry friendship is no longer required 2020-05-07 16:02:49 +02:00
Michele Caini
4d73adb540 snapshot: cleanup 2020-05-07 16:02:49 +02:00
Michele Caini
bdfeb1ae22 registry: destroy with suggested version 2020-05-07 16:02:49 +02:00
Michele Caini
3fc116ab53 minor changes 2020-05-07 16:02:49 +02:00
Michele Caini
8db61a38cc sparse set: review 2020-05-07 16:02:49 +02:00
Michele Caini
0a70979934 observer: deprecated .replace, use .update instead 2020-05-07 16:02:49 +02:00
Michele Caini
1a2ccdf991 Update README.md 2020-05-07 16:01:12 +02:00
Michele Caini
0adee56d76 meta: as_alias[_t] -> as_ref[_t] (see #479) 2020-04-30 23:59:17 +02:00
Michele Caini
fedd50efe4 meta: added meta_any::ref as an alias to meta_any operator* (close #479) 2020-04-30 23:53:02 +02:00
Michele Caini
d7de7dbe6b build system: minor changes (close #478) 2020-04-30 23:24:50 +02:00
Michele Caini
9fb8939efd meta: removed redundant assert 2020-04-30 14:28:54 +02:00
Michele Caini
fe8f671137 build system: USE_LIBCPP option is set to ON by default (see #478) 2020-04-30 14:28:34 +02:00
Michele Caini
1a4de1482b build system: minor changes (close #478) 2020-04-29 23:10:42 +02:00
Michele Caini
090a2595e1 config/type_id: minor changes 2020-04-29 01:05:17 +02:00
Michele Caini
89dc7f817f meta: added resolve_type utility 2020-04-25 17:36:57 +02:00
Michele Caini
fe0f26ce9c meta: workaround for an issue of clang 7 (close #472) 2020-04-25 16:48:21 +02:00
Michele Caini
11349629f4 meta: get around an issue of VS2017 2020-04-23 14:56:39 +02:00
Michele Caini
9a67652c0c meta: separate resolve.hpp file 2020-04-22 20:05:24 +02:00
Michele Caini
b35521dfcb meta: deprecated resolve by id, added entt::resolve_id 2020-04-21 18:32:35 +02:00
Michele Caini
9faf306d1e meta: added entt::resolve_if 2020-04-20 23:25:10 +02:00
Michele Caini
d8393dace6 meta: deprecated *::alias(), use ::id() instead 2020-04-20 22:34:30 +02:00
Michele Caini
692e5275a3 entity: the null entity works fine also with C++20 (close #467) 2020-04-20 22:34:30 +02:00
Michele Caini
1cfe517db8 meta: meta_type::id -> meta_type::type_id 2020-04-20 22:34:30 +02:00
Michele Caini
e99e1dc2ac meta: factory::alias -> factory::type (with type_info<T>::id as a default identifier) 2020-04-20 22:34:30 +02:00
Michele Caini
1bf4ebcabb suppress warnings for shadow parameters 2020-04-20 22:34:30 +02:00
Michele Caini
ec4b264868 meta: export also the meta_node class template (close #464) 2020-04-20 22:34:30 +02:00
Michele Caini
efb125b2d5 updated list of contributors 2020-04-20 22:34:16 +02:00
Elias Daler
1c0fdbed59 Fix typo in docs (s/comp/velocity) (#468) 2020-04-20 22:32:52 +02:00
Michele Caini
37bb10e564 doc: updated examples (close #463) 2020-04-17 00:23:04 +02:00
Michele Caini
1507d5d85f updated single include file (close #461) 2020-04-14 18:37:59 +02:00
Michele Caini
2a86acfc50 doc: updated documentation for the core part 2020-04-14 18:35:03 +02:00
Michele Caini
e0ee01b92e doc: fixed typo 2020-04-14 18:29:25 +02:00
Michele Caini
6006917622 storage: assert on requirements (see #458) 2020-04-09 19:42:45 +02:00
Michele Caini
4ffcf6bf3b meta: added the possibility to detach meta types from contexts 2020-04-09 00:26:02 +02:00
Michele Caini
49cde59c4e meta: minor changes 2020-04-08 23:45:48 +02:00
Michele Caini
ed7382995c registry: added ::remove_all to orphan entities (close #446) 2020-04-07 23:48:07 +02:00
Michele Caini
a7faab53b9 basic_continuous_loader: deprecated ::has, use ::contains instead 2020-04-07 00:00:57 +02:00
Michele Caini
a6aad25117 sparse_set/storage: deprecated ::destroy, use ::erase instead 2020-04-06 23:57:20 +02:00
Michele Caini
5f06084b19 sparse_set: deprecated ::has, use ::contains instead 2020-04-06 23:51:59 +02:00
Michele Caini
8151fbcb2e core: tag is no longer deprecated (close #457) 2020-04-06 23:21:17 +02:00
Michele Caini
5a8e46a6b8 doc: updated documentation for the resource module 2020-04-06 23:20:46 +02:00
Michele Caini
c4997c52e2 doc: updated documentation for the entity module 2020-04-06 23:20:28 +02:00
Michele Caini
ff12c22f50 test: cleanup 2020-04-05 23:36:00 +02:00
Michele Caini
ed7f09ab80 registry: updated tests (lib) 2020-04-05 23:32:10 +02:00
Michele Caini
f68941992a emitter: updated tests (lib) 2020-04-05 23:22:16 +02:00
Michele Caini
afcd9285e6 dispatcher: updated tests (lib) 2020-04-05 23:16:16 +02:00
Michele Caini
22f78d5b33 doc: updated documentation for making EnTT work nicely across boundaries 2020-04-05 22:58:07 +02:00
Michele Caini
5259142eb6 registry: use fast path if available, standard path otherwise 2020-04-05 22:07:35 +02:00
Michele Caini
dc403ce8ab emitter: use fast path if available, standard path otherwise 2020-04-05 22:07:23 +02:00
Michele Caini
a6fddd6a2c dispatcher: use fast path if available, standard path otherwise 2020-04-05 22:07:12 +02:00
Michele Caini
819cd623f9 multiple modules: minor changes 2020-04-05 22:04:57 +02:00
Michele Caini
f185494de3 type info: added has_type_index[_v] 2020-04-05 22:03:52 +02:00
Michele Caini
628a17ae72 config: fixed ENTT_IS_EMPTY macro definition 2020-04-03 00:49:47 +02:00
Michele Caini
08169b9180 emitter: reintroduced type_id for the internal pool 2020-04-03 00:22:01 +02:00
Michele Caini
1e79f2441c dispatcher: reintroduced type_id for the internal pool 2020-04-03 00:21:53 +02:00
Michele Caini
8680c0ba39 config: ENTT_DISABLE_ETO -> ENTT_NO_ETO 2020-04-02 18:21:42 +02:00
Michele Caini
8a78b0dbd6 registry: use only sequential indexes for component types now 2020-04-01 22:17:10 +02:00
Michele Caini
0232035e34 emitter: use only sequential indexes now 2020-04-01 21:27:59 +02:00
Michele Caini
74f3df83db dispatcher: use only sequential indexes now 2020-04-01 21:19:38 +02:00
Michele Caini
53fa0d2fe8 registry: ::assure sets a constraint on the type 2020-04-01 00:16:35 +02:00
Michele Caini
52aa9ab761 type_info: split type_info::index to type_index::value 2020-04-01 00:14:28 +02:00
Michele Caini
92cf6195b2 iterators: standard-ish names for better integration 2020-03-30 16:11:10 +02:00
Michele Caini
86a392991a test: type_info::index 2020-03-28 17:05:23 +01:00
Michele Caini
30d426d667 doc: updated core section 2020-03-28 17:01:04 +01:00
Michele Caini
5702c50680 type_info: added ::index to generate type indexes 2020-03-28 17:00:48 +01:00
Michele Caini
e38d2e156d doc: updated list of showcases 2020-03-27 00:25:30 +01:00
Michele Caini
dfc18619a2 build system: updated installation process (close #451) 2020-03-27 00:04:48 +01:00
Michele Caini
9e8f2c52a0 doc: updated section for on_update/on_replace (close #452) 2020-03-25 15:11:14 +01:00
Michele Caini
1c8f5b98f1 build system: updated installation process (close #451) 2020-03-25 00:56:43 +01:00
Michele Caini
972470ad42 benchmark: minor changes 2020-03-24 22:40:39 +01:00
Michele Caini
f7e3a055fb registry: minor changes 2020-03-21 23:35:45 +01:00
Michele Caini
34f05fb8dc doc: updated wiki for meta (close #448) 2020-03-21 16:56:29 +01:00
Michele Caini
709fd34264 registry/storage: ::insert supports all types of iterators 2020-03-21 16:48:31 +01:00
Michele Caini
b888757092 entity/*: iterators review 2020-03-20 23:53:43 +01:00
Michele Caini
0f42827047 entity/*: stop using deprecated functions internally 2020-03-20 16:50:04 +01:00
Michele Caini
e69d1556e1 config: renamed ENTT_ENABLE_ETO to ENTT_IS_EMPTY 2020-03-20 00:04:26 +01:00
Michele Caini
141fbf7472 type_traits: deprecated entt::tag because of the more general purpose alternative entt::integral_constant 2020-03-19 23:41:49 +01:00
Michele Caini
c9a3ae8149 type_traits: added shortcut entt::integral_constant 2020-03-19 23:38:10 +01:00
Michele Caini
e16a8d29ea links: added the Vim of game engines (close #447) 2020-03-19 16:05:31 +01:00
Michele Caini
fff50d0e50 registry: workaround for an issue with MSVC 2020-03-19 16:00:11 +01:00
Michele Caini
360734b447 doc: workaround for some idiosyncracies of doxygen 2020-03-19 00:49:49 +01:00
Michele Caini
7e5edad32b registry: workaround for an issue of gcc7 2020-03-19 00:33:14 +01:00
Michele Caini
fc47b47850 doc: updated doc for empty types 2020-03-18 23:59:44 +01:00
Michele Caini
c7de058e1d storage/registry: empty types are no longer a thing 2020-03-18 00:11:53 +01:00
Michele Caini
0fff3c905c view: deprecated ::less, ::each returns only non-empty types now 2020-03-16 00:30:33 +01:00
Michele Caini
2fcb055c43 group: deprecated ::less, ::each returns only non-empty types now 2020-03-15 23:50:02 +01:00
Michele Caini
97e0d63102 storage: consume args for empty types in all cases 2020-03-13 23:08:59 +01:00
Michele Caini
5e04f0accd registry: strict check on ::insert (see #438) 2020-03-13 00:02:05 +01:00
Michele Caini
16835e3928 registry: get_or_assign -> get_or_emplace 2020-03-12 23:41:58 +01:00
Michele Caini
22e0ef1354 doc: updated examples, wiki and inline documentation 2020-03-12 23:33:08 +01:00
Michele Caini
0141dc519c doc: added similar projects (close #443) 2020-03-11 17:57:36 +01:00
Michele Caini
9aadc30b94 registry: disambiguate calls to ::assign and ::assign_or_replace (close #438) 2020-03-11 16:19:41 +01:00
Michele Caini
23a73fcb7c doc: suppressed some warnings due to missing parameters 2020-03-11 15:36:14 +01:00
Michele Caini
9a3b585110 registry: disambiguate calls to pool_handler<T>::construct (see #438) 2020-03-11 14:34:47 +01:00
Michele Caini
09ee46860a sparse_set: disambiguate calls to ::construct (see #438) 2020-03-11 00:07:41 +01:00
Michele Caini
d8f289182d storage: disambiguate calls to ::construct (see #438) 2020-03-11 00:05:04 +01:00
Michele Caini
dc8fa2153b registry: on_replace becomes on_update 2020-03-09 14:46:38 +01:00
Michele Caini
32fb335832 registry: added ::patch, reintroduced ::replace from arguments (close #437) 2020-03-09 14:34:28 +01:00
Michele Caini
58885854f1 doc: added a warning to registry::replace 2020-03-08 23:36:18 +01:00
Michele Caini
3e87788541 registry: ::replace always returns the component, no matter what 2020-03-08 16:42:17 +01:00
Michele Caini
5746df4d74 doc: added a note on registry::assign 2020-03-08 15:54:07 +01:00
Michele Caini
71d86c44e0 registry: cleanup 2020-03-08 00:56:00 +01:00
Michele Caini
c5e50289e1 workflow: unlock deploy to homebrew-entt (close #397) 2020-03-07 23:26:47 +01:00
Michele Caini
e62f1edada registry: minor changes 2020-03-07 23:26:39 +01:00
Michele Caini
50e8db28b8 minor changes all over the codebase (final) 2020-03-07 00:41:21 +01:00
Michele Caini
ef7c572018 core: define entt::id_type alias for ENTT_ID_TYPE (close #416) 2020-03-07 00:41:21 +01:00
Michele Caini
1e962754cc entity module: added utility.hpp, cleaned up fwd.hpp 2020-03-07 00:41:21 +01:00
Michele Caini
0240453b07 registry: review context variables 2020-03-07 00:41:21 +01:00
Michele Caini
38a80a95f2 registry: reduce instantiations 2020-03-07 00:41:21 +01:00
Michele Caini
b5e411d251 registry: removed deprecated functions 2020-03-07 00:41:21 +01:00
Michele Caini
71a623276e registry: removed deprecated overload for replace 2020-03-07 00:41:21 +01:00
Michele Caini
1e76703144 meta: removed deprecated functions 2020-03-07 00:41:21 +01:00
Michele Caini
6ffaf11226 helper: added a shortcut to invoke members on components from callbacks (close #385) 2020-03-07 00:41:21 +01:00
Michele Caini
fc0caec1a4 build system: updated version, now working on v3.4.0 2020-03-07 00:41:21 +01:00
Michele Caini
043f9a5025 updated single include file 2020-03-07 00:41:15 +01:00
Michele Caini
822264a65e workflow: --dry-run for the deploy.yml debut (see #397) 2020-03-07 00:30:24 +01:00
Michele Caini
8e9a6a4f06 registry: fixed a bug that affects late group initialization (close #440) 2020-03-07 00:30:21 +01:00
Michele Caini
76f3909ec9 workflow: update homebrew-entt (see #397) 2020-03-07 00:30:19 +01:00
Michele Caini
23e839b40e build system: updated install process (close #421) 2020-03-07 00:30:16 +01:00
Michele Caini
6a560fc7bf observer: use any<T...> rather than a fold expression with has<T> 2020-03-07 00:30:08 +01:00
Michele Caini
709d1c93a4 registry: fixed a bug that affects late group initialization (close #436) 2020-03-07 00:29:57 +01:00
Michele Caini
8d4b5f4bb7 sparse_set: remove copy ctor/assignment operator (use range-construct instead) 2020-03-07 00:11:30 +01:00
Paul Gruenbacher
9eb5a85e9e doc: update clone example to handle empty types (#441) 2020-03-07 00:09:19 +01:00
Paul Gruenbacher
e7521445e9 doc: update stamp example (#442) 2020-03-07 00:09:15 +01:00
Michele Caini
bb050e2660 actor: (has<T>(e) && ...) -> has<T...>(e) 2020-03-07 00:07:56 +01:00
Michele Caini
bc3b0eb491 links: added references to Chrysalis (project and blog post) 2020-03-07 00:06:39 +01:00
Michele Caini
7cea05d376 doc: updated documentation for snapshot archives (close #431) 2020-03-07 00:06:32 +01:00
Michele Caini
b8a3bdf6b5 build system: minor changes 2020-03-07 00:06:25 +01:00
Michele Caini
638b6dba17 build system: updated version, now working on v3.3.2 2020-03-06 23:56:55 +01:00
Michele Caini
50ba8c6c39 updated single include file 2020-02-28 23:27:20 +01:00
Michele Caini
94d15ebbef config: being empty isn't enough for ETO, type must be default constructible 2020-02-28 23:18:12 +01:00
Michele Caini
e150882231 doc: udpated doc (see #431) 2020-02-28 23:18:09 +01:00
Michele Caini
80a659c90c doc: typo 2020-02-28 23:18:03 +01:00
Michele Caini
17d96427ea registry: assign_or_replace works also with aggregates now (close #429) 2020-02-28 23:17:58 +01:00
Michele Caini
7fdda788af registry: minor changes (close #424) 2020-02-28 23:17:53 +01:00
Ezekiel Warren
182adbd9d9 Re-added bazel support (#430) 2020-02-28 23:17:45 +01:00
Michele Caini
4931c9cd9b build system: updated version, now working on v3.3.1 2020-02-28 23:17:24 +01:00
Michele Caini
a112409735 updated single include file (close #425) 2020-02-23 16:54:02 +01:00
262 changed files with 123357 additions and 29102 deletions

41
.clang-format Normal file
View File

@@ -0,0 +1,41 @@
BasedOnStyle: llvm
---
AccessModifierOffset: -4
AlignEscapedNewlines: DontAlign
AllowShortBlocksOnASingleLine: Empty
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeTernaryOperators: true
ColumnLimit: 0
DerivePointerAlignment: false
IncludeCategories:
- Regex: '<[[:alnum:]_]+>'
Priority: 1
- Regex: '<(gtest|gmock)/'
Priority: 2
- Regex: '<[[:alnum:]_./]+>'
Priority: 3
- Regex: '<entt/'
Priority: 4
- Regex: '.*'
Priority: 5
IndentPPDirectives: AfterHash
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
PointerAlignment: Right
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: After
SpaceBeforeCaseColon: false
SpaceBeforeCtorInitializerColon: false
SpaceBeforeInheritanceColon: false
SpaceBeforeParens: Never
SpaceBeforeRangeBasedForLoopColon: false
Standard: Latest
TabWidth: 4
UseTab: Never

8
.github/FUNDING.yml vendored
View File

@@ -1,12 +1,4 @@
# These are supported funding model platforms
github: skypjack
patreon: skypjack
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: https://www.paypal.me/skypjack

55
.github/workflows/analyzer.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: analyzer
on:
push:
branches:
- master
- wip
jobs:
iwyu:
timeout-minutes: 30
env:
IWYU: 0.18
LLVM: 14
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v2
- name: Install llvm/clang
# see: https://apt.llvm.org/
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-$LLVM main"
sudo apt update
sudo apt remove -y "llvm*"
sudo apt remove -y "libclang-dev*"
sudo apt remove -y "clang*"
sudo apt install -y llvm-$LLVM-dev
sudo apt install -y libclang-$LLVM-dev
sudo apt install -y clang-$LLVM
- name: Compile iwyu
# see: https://github.com/include-what-you-use/include-what-you-use
working-directory: build
run: |
git clone https://github.com/include-what-you-use/include-what-you-use.git --branch $IWYU --depth 1
mkdir include-what-you-use/build
cd include-what-you-use/build
cmake -DCMAKE_C_COMPILER=clang-$LLVM -DCMAKE_CXX_COMPILER=clang++-$LLVM -DCMAKE_INSTALL_PREFIX=./ ..
make -j4
bin/include-what-you-use --version
- name: Compile tests
working-directory: build
run: |
export PATH=$PATH:${GITHUB_WORKSPACE}/build/include-what-you-use/build/bin
cmake -DENTT_BUILD_TESTING=ON \
-DENTT_BUILD_BENCHMARK=ON \
-DENTT_BUILD_EXAMPLE=ON \
-DENTT_BUILD_LIB=ON \
-DENTT_BUILD_SNAPSHOT=ON \
-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-Xiwyu;--mapping_file=${GITHUB_WORKSPACE}/entt.imp;-Xiwyu;--no_fwd_decls;-Xiwyu;--verbose=1" ..
make -j4

View File

@@ -5,71 +5,165 @@ on: [push, pull_request]
jobs:
linux:
timeout-minutes: 10
timeout-minutes: 15
strategy:
matrix:
compiler: [g++, clang++]
compiler:
- pkg: g++-7
exe: g++-7
- pkg: g++-8
exe: g++-8
- pkg: g++-9
exe: g++-9
- pkg: g++-10
exe: g++-10
- pkg: clang-8
exe: clang++-8
- pkg: clang-9
exe: clang++-9
- pkg: clang-10
exe: clang++-10
- pkg: clang-11
exe: clang++-11
- pkg: clang-12
exe: clang++-12
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Install compiler
run: |
sudo apt update
sudo apt install -y ${{ matrix.compiler.pkg }}
- name: Compile tests
working-directory: build
env:
CXX: ${{ matrix.compiler.exe }}
run: |
cmake -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 30 -C Debug -j4
linux-extra:
timeout-minutes: 15
strategy:
matrix:
compiler: [g++, clang++]
id_type: ["std::uint32_t", "std::uint64_t"]
cxx_std: [cxx_std_17, cxx_std_20]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Compile tests
working-directory: build
env:
CXX: ${{ matrix.compiler }}
run: |
cmake -DBUILD_TESTING=ON -DBUILD_LIB=ON ..
cmake -DENTT_BUILD_TESTING=ON -DENTT_CXX_STD=${{ matrix.cxx_std }} -DENTT_ID_TYPE=${{ matrix.id_type }} ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 5 -C Debug -j4
run: ctest --timeout 30 -C Debug -j4
windows:
timeout-minutes: 10
timeout-minutes: 15
strategy:
matrix:
os: [windows-latest, windows-2016]
toolset: [clang-cl, default]
toolset: [default, v141, v142, clang-cl]
include:
- toolset: v141
toolset_option: -T"v141"
- toolset: v142
toolset_option: -T"v142"
- toolset: clang-cl
toolset_option: -T"ClangCl"
exclude:
- os: windows-2016
toolset: clang-cl
runs-on: ${{ matrix.os }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Compile tests
working-directory: build
run: |
cmake -DBUILD_TESTING=ON -DBUILD_LIB=ON ${{ matrix.toolset_option }} ..
cmake -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON ${{ matrix.toolset_option }} ..
cmake --build . -j 4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 5 -C Debug -j4
run: ctest --timeout 30 -C Debug -j4
macos:
timeout-minutes: 10
runs-on: macOS-latest
windows-extra:
timeout-minutes: 15
strategy:
matrix:
id_type: ["std::uint32_t", "std::uint64_t"]
cxx_std: [cxx_std_17, cxx_std_20]
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Compile tests
working-directory: build
run: |
cmake -DBUILD_TESTING=ON -DBUILD_LIB=ON ..
cmake -DENTT_BUILD_TESTING=ON -DENTT_CXX_STD=${{ matrix.cxx_std }} -DENTT_ID_TYPE=${{ matrix.id_type }} ..
cmake --build . -j 4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 30 -C Debug -j4
macos:
timeout-minutes: 15
runs-on: macOS-latest
steps:
- uses: actions/checkout@v2
- name: Compile tests
working-directory: build
run: |
cmake -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 5 -C Debug -j4
run: ctest --timeout 30 -C Debug -j4
macos-extra:
timeout-minutes: 15
strategy:
matrix:
id_type: ["std::uint32_t", "std::uint64_t"]
cxx_std: [cxx_std_17, cxx_std_20]
runs-on: macOS-latest
steps:
- uses: actions/checkout@v2
- name: Compile tests
working-directory: build
run: |
cmake -DENTT_BUILD_TESTING=ON -DENTT_CXX_STD=${{ matrix.cxx_std }} -DENTT_ID_TYPE=${{ matrix.id_type }} ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 30 -C Debug -j4

View File

@@ -5,29 +5,34 @@ on: [push, pull_request]
jobs:
codecov:
timeout-minutes: 10
timeout-minutes: 15
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Compile tests
working-directory: build
env:
CXXFLAGS: "-O0 --coverage -fno-inline -fno-inline-small-functions -fno-default-inline"
CXXFLAGS: "--coverage -fno-inline"
CXX: g++
run: |
cmake -DBUILD_TESTING=ON -DBUILD_LIB=ON ..
cmake -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 5 -C Debug -j4
- name: Upload coverage to Codecov
run: ctest --timeout 30 -C Debug -j4
- name: Collect data
working-directory: build
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: |
wget https://codecov.io/bash -O codecov
chmod +x codecov
./codecov -t $CODECOV_TOKEN -B $GITHUB_REF -s test/
sudo apt install lcov
lcov -c -d . -o coverage.info
lcov -l coverage.info
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: build/coverage.info
name: EnTT
fail_ci_if_error: true

39
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: deploy
on:
release:
types: published
jobs:
homebrew-entt:
timeout-minutes: 5
runs-on: ubuntu-latest
env:
GH_REPO: homebrew-entt
FORMULA: entt.rb
steps:
- uses: actions/checkout@v2
- name: Clone repository
working-directory: build
env:
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
run: git clone https://$GITHUB_ACTOR:$PERSONAL_ACCESS_TOKEN@github.com/$GITHUB_ACTOR/$GH_REPO.git
- name: Prepare formula
working-directory: build
run: |
cd $GH_REPO
curl "https://github.com/${{ github.repository }}/archive/${{ github.ref }}.tar.gz" --location --fail --silent --show-error --output archive.tar.gz
sed -i -e '/url/s/".*"/"'$(echo "https://github.com/${{ github.repository }}/archive/${{ github.ref }}.tar.gz" | sed -e 's/[\/&]/\\&/g')'"/' $FORMULA
sed -i -e '/sha256/s/".*"/"'$(openssl sha256 archive.tar.gz | cut -d " " -f 2)'"/' $FORMULA
- name: Update remote
working-directory: build
run: |
cd $GH_REPO
git config --local user.email "action@github.com"
git config --local user.name "$GITHUB_ACTOR"
git add $FORMULA
git commit -m "Update to ${{ github.ref }}"
git push origin master

31
.github/workflows/sanitizer.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: sanitizer
on: [push, pull_request]
jobs:
clang:
timeout-minutes: 15
strategy:
matrix:
compiler: [clang++]
id_type: ["std::uint32_t", "std::uint64_t"]
cxx_std: [cxx_std_17, cxx_std_20]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Compile tests
working-directory: build
env:
CXX: ${{ matrix.compiler }}
run: |
cmake -DENTT_USE_SANITIZER=ON -DENTT_BUILD_TESTING=ON -DENTT_BUILD_LIB=ON -DENTT_BUILD_EXAMPLE=ON -DENTT_CXX_STD=${{ matrix.cxx_std }} -DENTT_ID_TYPE=${{ matrix.id_type }} ..
make -j4
- name: Run tests
working-directory: build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest --timeout 30 -C Debug -j4

3
.gitignore vendored
View File

@@ -5,6 +5,9 @@ conan/test_package/build
*.user
.idea
.vscode
.vs
CMakeSettings.json
cpp.hint
# Bazel
/bazel-*

12
AUTHORS
View File

@@ -4,17 +4,23 @@ skypjack
# Contributors
alexames
BenediktConze
bjadamson
ceeac
ColinH
corystegel
Croydon
cschreib
cugone
dbacchet
dBagrat
djarek
DNKpp
DonKult
drglove
eliasdaler
erez-o
eugeneko
gale83
ghost
@@ -22,16 +28,21 @@ grdowns
Green-Sky
Innokentiy-Alaytsev
Kerndog73
Koward
Lawrencemm
markand
mhammerc
Milerius
Minimonium
morbo84
m-waka
netpoetica
NixAJ
Oortonaut
Paolo-Oliverio
pgruenbacher
prowolf
Qix-
stefanofiorentino
suVrik
szunhammer
@@ -39,6 +50,7 @@ The5-1
vblanco20-1
willtunnels
WizardIke
WoLfulus
w1th0utnam3
xissburg
zaucy

14
BUILD.bazel Normal file
View File

@@ -0,0 +1,14 @@
_msvc_copts = ["/std:c++17"]
_gcc_copts = ["-std=c++17"]
cc_library(
name = "entt",
visibility = ["//visibility:public"],
strip_include_prefix = "src",
hdrs = glob(["src/**/*.h", "src/**/*.hpp"]),
copts = select({
"@bazel_tools//src/conditions:windows": _msvc_copts,
"@bazel_tools//src/conditions:windows_msvc": _msvc_copts,
"//conditions:default": _gcc_copts,
}),
)

View File

@@ -4,14 +4,6 @@
cmake_minimum_required(VERSION 3.12.4)
#
# Building in-tree is not allowed (we take care of your craziness).
#
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the source code and call cmake from there. Thank you.")
endif()
#
# Read project version
#
@@ -30,49 +22,82 @@ project(
VERSION ${ENTT_VERSION}
DESCRIPTION "Gaming meets modern C++ - a fast and reliable entity-component system (ECS) and much more"
HOMEPAGE_URL "https://github.com/skypjack/entt"
LANGUAGES CXX
LANGUAGES C CXX
)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
message("*")
message("* ${PROJECT_NAME} v${PROJECT_VERSION} (${CMAKE_BUILD_TYPE})")
message("* Copyright (c) 2017-2020 Michele Caini <michele.caini@gmail.com>")
message("*")
message(VERBOSE "*")
message(VERBOSE "* ${PROJECT_NAME} v${PROJECT_VERSION} (${CMAKE_BUILD_TYPE})")
message(VERBOSE "* Copyright (c) 2017-2022 Michele Caini <michele.caini@gmail.com>")
message(VERBOSE "*")
option(USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if availbale." ON)
option(USE_ASAN "Use address sanitizer by adding -fsanitize=address -fno-omit-frame-pointer flags" OFF)
#
# CMake stuff
#
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
#
# Compiler stuff
#
if(NOT WIN32 AND USE_LIBCPP)
include(CheckCXXSourceCompiles)
include(CMakePushCheckState)
option(ENTT_USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if available." OFF)
option(ENTT_USE_SANITIZER "Enable sanitizers by adding -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined flags if available." OFF)
cmake_push_check_state()
if(ENTT_USE_LIBCPP)
if(NOT WIN32)
include(CheckCXXSourceCompiles)
include(CMakePushCheckState)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libc++")
cmake_push_check_state()
check_cxx_source_compiles("
#include<type_traits>
int main() { return std::is_same_v<int, char>; }
" HAS_LIBCPP)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libc++")
if(NOT HAS_LIBCPP)
message(WARNING "The option USE_LIBCPP is set (by default) but libc++ is not available. The flag will not be added to the target.")
check_cxx_source_compiles("
#include<type_traits>
int main() { return std::is_same_v<int, char>; }
" ENTT_HAS_LIBCPP)
cmake_pop_check_state()
endif()
cmake_pop_check_state()
if(NOT ENTT_HAS_LIBCPP)
message(VERBOSE "The option ENTT_USE_LIBCPP is set but libc++ is not available. The flag will not be added to the target.")
endif()
endif()
if(ENTT_USE_SANITIZER)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
set(ENTT_HAS_SANITIZER TRUE CACHE BOOL "" FORCE)
mark_as_advanced(ENTT_HAS_SANITIZER)
endif()
if(NOT ENTT_HAS_SANITIZER)
message(VERBOSE "The option ENTT_USE_SANITIZER is set but sanitizer support is not available. The flags will not be added to the target.")
endif()
endif()
#
# Add EnTT target
#
option(ENTT_INCLUDE_HEADERS "Add all EnTT headers to the EnTT target." OFF)
option(ENTT_INCLUDE_NATVIS "Add EnTT natvis files to the EnTT target." OFF)
if(ENTT_INCLUDE_NATVIS)
if(MSVC)
set(ENTT_HAS_NATVIS TRUE CACHE BOOL "" FORCE)
mark_as_advanced(ENTT_HAS_NATVIS)
endif()
if(NOT ENTT_HAS_NATVIS)
message(VERBOSE "The option ENTT_INCLUDE_NATVIS is set but natvis files are not supported. They will not be added to the target.")
endif()
endif()
include(GNUInstallDirs)
add_library(EnTT INTERFACE)
@@ -81,96 +106,206 @@ add_library(EnTT::EnTT ALIAS EnTT)
target_include_directories(
EnTT
INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_definitions(
EnTT
INTERFACE
$<$<AND:$<CONFIG:Debug>,$<NOT:$<CXX_COMPILER_ID:MSVC>>>:DEBUG>
$<$<AND:$<CONFIG:Release>,$<NOT:$<CXX_COMPILER_ID:MSVC>>>:RELEASE>
)
target_compile_features(EnTT INTERFACE cxx_std_17)
if(USE_ASAN)
target_compile_options(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
target_link_libraries(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer>)
if(ENTT_INCLUDE_HEADERS)
target_sources(
EnTT
INTERFACE
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/config/config.h>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/config/macro.h>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/config/version.h>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/container/dense_map.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/container/dense_set.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/container/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/algorithm.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/any.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/attribute.h>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/compressed_pair.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/enum.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/family.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/hashed_string.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/ident.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/iterator.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/memory.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/monostate.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/tuple.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/type_info.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/type_traits.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/core/utility.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/component.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/entity.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/group.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/handle.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/helper.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/observer.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/organizer.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/registry.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/runtime_view.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/snapshot.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/sparse_set.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/storage.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/storage_mixin.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/view.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/adjacency_matrix.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/dot.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/flow.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/graph/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/locator/locator.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/adl_pointer.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/container.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/context.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/factory.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/meta.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/node.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/pointer.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/policy.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/range.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/resolve.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/template.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/type_traits.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/meta/utility.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/platform/android-ndk-r17.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/poly/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/poly/poly.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/process/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/process/process.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/process/scheduler.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/cache.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/loader.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/resource.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/delegate.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/dispatcher.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/emitter.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/fwd.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/sigh.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entt.hpp>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/fwd.hpp>
)
endif()
if(HAS_LIBCPP)
if(ENTT_HAS_NATVIS)
target_sources(
EnTT
INTERFACE
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/config.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/container.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/core.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/entity.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/graph.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/locator.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/meta.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/platform.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/poly.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/process.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/resource.natvis>
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/natvis/entt/signal.natvis>
)
endif()
if(ENTT_HAS_SANITIZER)
target_compile_options(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>)
target_link_libraries(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>)
endif()
if(ENTT_HAS_LIBCPP)
target_compile_options(EnTT BEFORE INTERFACE -stdlib=libc++)
endif()
target_compile_features(EnTT INTERFACE cxx_std_17)
#
# Install pkg-config file
#
include(JoinPaths)
set(EnTT_PKGCONFIG ${CMAKE_CURRENT_BINARY_DIR}/entt.pc)
join_paths(EnTT_PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
configure_file(
${EnTT_SOURCE_DIR}/cmake/in/entt.pc.in
${EnTT_PKGCONFIG}
@ONLY
)
install(
FILES ${EnTT_PKGCONFIG}
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
#
# Install EnTT
#
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(CUSTOM_INSTALL_CONFIGDIR cmake)
else()
set(CUSTOM_INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/entt)
endif()
install(DIRECTORY src/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS EnTT EXPORT EnTTTargets)
export(EXPORT EnTTTargets FILE ${EnTT_BINARY_DIR}/EnTTTargets.cmake)
install(
EXPORT EnTTTargets
FILE EnTTTargets.cmake
DESTINATION ${CUSTOM_INSTALL_CONFIGDIR}
NAMESPACE EnTT::
)
#
# Build tree package config file
#
configure_file(cmake/in/EnTTBuildConfig.cmake.in EnTTConfig.cmake @ONLY)
include(CMakePackageConfigHelpers)
#
# Install tree package config file
#
configure_package_config_file(
cmake/in/EnTTConfig.cmake.in
${CUSTOM_INSTALL_CONFIGDIR}/EnTTConfig.cmake
INSTALL_DESTINATION ${CUSTOM_INSTALL_CONFIGDIR}
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
install(
TARGETS EnTT
EXPORT EnTTTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
write_basic_package_version_file(
${EnTT_BINARY_DIR}/EnTTConfigVersion.cmake
EnTTConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
configure_package_config_file(
${EnTT_SOURCE_DIR}/cmake/in/EnTTConfig.cmake.in
EnTTConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
)
export(
EXPORT EnTTTargets
FILE ${CMAKE_CURRENT_BINARY_DIR}/EnTTTargets.cmake
NAMESPACE EnTT::
)
install(
EXPORT EnTTTargets
FILE EnTTTargets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
NAMESPACE EnTT::
)
install(
FILES
${EnTT_BINARY_DIR}/${CUSTOM_INSTALL_CONFIGDIR}/EnTTConfig.cmake
${EnTT_BINARY_DIR}/EnTTConfigVersion.cmake
DESTINATION ${CUSTOM_INSTALL_CONFIGDIR}
${PROJECT_BINARY_DIR}/EnTTConfig.cmake
${PROJECT_BINARY_DIR}/EnTTConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
)
install(DIRECTORY src/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
export(PACKAGE EnTT)
#
# Tests
#
option(BUILD_TESTING "Enable testing with ctest." OFF)
option(ENTT_BUILD_TESTING "Enable building tests." OFF)
if(BUILD_TESTING)
option(FIND_GTEST_PACKAGE "Enable finding gtest package." OFF)
option(BUILD_BENCHMARK "Build benchmark." OFF)
option(BUILD_LIB "Build lib example." OFF)
option(BUILD_SNAPSHOT "Build snapshot example." OFF)
if(ENTT_BUILD_TESTING)
option(ENTT_FIND_GTEST_PACKAGE "Enable finding gtest package." OFF)
option(ENTT_BUILD_BENCHMARK "Build benchmark." OFF)
option(ENTT_BUILD_EXAMPLE "Build examples." OFF)
option(ENTT_BUILD_LIB "Build lib tests." OFF)
option(ENTT_BUILD_SNAPSHOT "Build snapshot test with Cereal." OFF)
set(ENTT_ID_TYPE std::uint32_t CACHE STRING "Type of identifiers to use for the tests")
set(ENTT_CXX_STD cxx_std_17 CACHE STRING "C++ standard revision to use for the tests")
include(CTest)
enable_testing()
add_subdirectory(test)
endif()
@@ -179,30 +314,12 @@ endif()
# Documentation
#
option(BUILD_DOCS "Enable building with documentation." OFF)
option(ENTT_BUILD_DOCS "Enable building with documentation." OFF)
if(BUILD_DOCS)
if(ENTT_BUILD_DOCS)
find_package(Doxygen 1.8)
if(DOXYGEN_FOUND)
add_subdirectory(docs)
endif()
endif()
#
# AOB
#
set(
AOB_SOURCES
.github/workflows/build.yml
.github/workflows/coverage.yml
.github/FUNDING.yml
AUTHORS
CONTRIBUTING.md
LICENSE
README.md
TODO
)
add_custom_target(aob SOURCES ${AOB_SOURCES})

View File

@@ -1,7 +1,7 @@
# Contributing
First of all, thank you very much for taking the time to contribute to the
`EnTT` framework.<br/>
`EnTT` library.<br/>
How to do it mostly depends on the type of contribution:
* If you have a question, **please** ensure there isn't already an answer for
@@ -28,7 +28,7 @@ How to do it mostly depends on the type of contribution:
* If you found a bug and you wrote a patch to fix it, open a new
[pull request](https://github.com/skypjack/entt/pulls) with your code.
**Please**, add some tests to avoid regressions in future if possible, it
would be really appreciated. Note that the `EnTT` framework has a
would be really appreciated. Note that the `EnTT` library has a
[coverage at 100%](https://coveralls.io/github/skypjack/entt?branch=master)
(at least it was at 100% at the time I wrote this file) and this is the reason
for which you can be confident with using it in a production environment.

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2017-2020 Michele Caini
Copyright (c) 2017-2022 Michele Caini, author of EnTT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

339
README.md
View File

@@ -1,23 +1,27 @@
![EnTT: Gaming meets modern C++](https://user-images.githubusercontent.com/1812216/42513718-ee6e98d0-8457-11e8-9baf-8d83f61a3097.png)
![EnTT: Gaming meets modern C++](https://user-images.githubusercontent.com/1812216/103550016-90752280-4ea8-11eb-8667-12ed2219e137.png)
<!--
@cond TURN_OFF_DOXYGEN
-->
[![GitHub version](https://badge.fury.io/gh/skypjack%2Fentt.svg)](https://github.com/skypjack/entt/releases)
[![Build Status](https://github.com/skypjack/entt/workflows/build/badge.svg)](https://github.com/skypjack/entt/actions)
[![Coverage](https://codecov.io/gh/skypjack/entt/branch/master/graph/badge.svg)](https://codecov.io/gh/skypjack/entt)
[![Try online](https://img.shields.io/badge/try-online-brightgreen)](https://godbolt.org/z/v8txVr)
[![Try online](https://img.shields.io/badge/try-online-brightgreen)](https://godbolt.org/z/zxW73f)
[![Documentation](https://img.shields.io/badge/docs-docsforge-blue)](http://entt.docsforge.com/)
[![Gitter chat](https://badges.gitter.im/skypjack/entt.png)](https://gitter.im/skypjack/entt)
[![Discord channel](https://img.shields.io/discord/707607951396962417?logo=discord)](https://discord.gg/5BjPWBd)
[![Donate](https://img.shields.io/badge/donate-paypal-blue.svg)](https://www.paypal.me/skypjack)
[![Patreon](https://img.shields.io/badge/become-patron-red.svg)](https://www.patreon.com/bePatron?c=1772573)
> `EnTT` has been a dream so far, we haven't found a single bug to date and it's
> super easy to work with
>
> -- Every EnTT User Ever
`EnTT` is a header-only, tiny and easy to use library for game programming and
much more written in **modern C++**, mainly known for its innovative
**entity-component-system (ECS)** model.<br/>
much more written in **modern C++**.<br/>
[Among others](https://github.com/skypjack/entt/wiki/EnTT-in-Action), it's used
in [**Minecraft**](https://minecraft.net/en-us/attribution/) by Mojang and the
[**ArcGIS Runtime SDKs**](https://developers.arcgis.com/arcgis-runtime/) by
Esri.<br/>
in [**Minecraft**](https://minecraft.net/en-us/attribution/) by Mojang, the
[**ArcGIS Runtime SDKs**](https://developers.arcgis.com/arcgis-runtime/) by Esri
and the amazing [**Ragdoll**](https://ragdolldynamics.com/).<br/>
If you don't see your project in the list, please open an issue, submit a PR or
add the [#entt](https://github.com/topics/entt) tag to your _topics_! :+1:
@@ -25,22 +29,21 @@ add the [#entt](https://github.com/topics/entt) tag to your _topics_! :+1:
Do you want to **keep up with changes** or do you have a **question** that
doesn't require you to open an issue?<br/>
Join the [gitter channel](https://gitter.im/skypjack/entt) and meet other users
like you. The more we are, the better for everyone.
Join the [gitter channel](https://gitter.im/skypjack/entt) and the
[discord server](https://discord.gg/5BjPWBd), meet other users like you. The
more we are, the better for everyone.<br/>
Don't forget to check the
[FAQs](https://github.com/skypjack/entt/wiki/Frequently-Asked-Questions) and the
[wiki](https://github.com/skypjack/entt/wiki) too. Your answers may already be
there.
Wondering why your **debug build** is so slow on Windows or how to represent a
**hierarchy** with components?<br/>
Check out the
[FAQ](https://github.com/skypjack/entt/wiki/Frequently-Asked-Questions) and the
[wiki](https://github.com/skypjack/entt/wiki) if you have these or other doubts,
your answers may already be there.
Do you want to support `EnTT`? Consider becoming a
[**sponsor**](https://github.com/users/skypjack/sponsorship).
Many thanks to [these people](https://skypjack.github.io/sponsorship/) and
**special** thanks to:
If you use `EnTT` and you want to say thanks or support the project, please
**consider becoming a
[sponsor](https://github.com/users/skypjack/sponsorship)**.<br/>
You can help me make the difference.
[Many thanks](https://skypjack.github.io/sponsorship/) to those who supported me
and still support me today.
[![mojang](https://user-images.githubusercontent.com/1812216/106253145-67ca1980-6217-11eb-9c0b-d93561b37098.png)](https://mojang.com)
[![imgly](https://user-images.githubusercontent.com/1812216/106253726-271ed000-6218-11eb-98e0-c9c681925770.png)](https://img.ly/)
# Table of Contents
@@ -48,16 +51,17 @@ and still support me today.
* [Code Example](#code-example)
* [Motivation](#motivation)
* [Performance](#performance)
* [Build Instructions](#build-instructions)
* [Integration](#integration)
* [Requirements](#requirements)
* [Library](#library)
* [Documentation](#documentation)
* [Tests](#tests)
* [Packaging Tools](#packaging-tools)
* [CMake](#cmake)
* [Natvis support](#natvis-support)
* [Packaging Tools](#packaging-tools)
* [pkg-config](#pkg-config)
* [Documentation](#documentation)
* [Tests](#tests)
* [EnTT in Action](#entt-in-action)
* [Contributors](#contributors)
* [License](#license)
* [Support](#support)
<!--
@endcond TURN_OFF_DOXYGEN
-->
@@ -75,41 +79,42 @@ This project started off as a pure entity-component system. Over time the
codebase has grown as more and more classes and functionalities were added.<br/>
Here is a brief, yet incomplete list of what it offers today:
* Statically generated integer **identifiers** for types (assigned either at
compile-time or at runtime).
* A `constexpr` utility for human readable **resource names**.
* A minimal **configuration system** built using the monostate pattern.
* An incredibly fast **entity-component system** based on sparse sets, with its
own _pay for what you use_ policy to adjust performance and memory usage
according to the users' requirements.
* Built-in **RTTI system** mostly similar to the standard one.
* A `constexpr` utility for human-readable **resource names**.
* Minimal **configuration system** built using the monostate pattern.
* Incredibly fast **entity-component system** with its own _pay for what you
use_ policy, unconstrained component types with optional pointer stability and
hooks for storage customization.
* Views and groups to iterate entities and components and allow different access
patterns, from **perfect SoA** to fully random.
* A lot of **facilities** built on top of the entity-component system to help
the users and avoid reinventing the wheel (dependencies, snapshot, actor
class, support for **reactive systems** and so on).
the users and avoid reinventing the wheel.
* General purpose **execution graph builder** for optimal scheduling.
* The smallest and most basic implementation of a **service locator** ever seen.
* A built-in, non-intrusive and macro-free runtime **reflection system**.
* **Static polymorphism** made simple and within everyone's reach.
* A few homemade containers, like a sparse set based **hash map**.
* A **cooperative scheduler** for processes of any type.
* All that is needed for **resource management** (cache, loaders, handles).
* Delegates, **signal handlers** (with built-in support for collectors) and a
tiny event dispatcher for immediate and delayed events to integrate in loops.
* Delegates, **signal handlers** and a tiny event dispatcher.
* A general purpose **event emitter** as a CRTP idiom based class template.
* And **much more**! Check out the
[**wiki**](https://github.com/skypjack/entt/wiki).
Consider this list a work in progress as well as the project. The whole API is
fully documented in-code for those who are brave enough to read it.
fully documented in-code for those who are brave enough to read it.<br/>
Please, do note that all tools are also DLL-friendly now and run smoothly across
boundaries.
Currently, `EnTT` is tested on Linux, Microsoft Windows and OSX. It has proven
to work also on both Android and iOS.<br/>
Most likely it won't be problematic on other systems as well, but it hasn't been
sufficiently tested so far.
One thing known to most is that `EnTT` is also used in **Minecraft**.<br/>
Given that the game is available literally everywhere, I can confidently say
that the library has been sufficiently tested on every platform that can come to
mind.
## Code Example
```cpp
#include <entt/entt.hpp>
#include <cstdint>
struct position {
float x;
@@ -122,52 +127,43 @@ struct velocity {
};
void update(entt::registry &registry) {
auto view = registry.view<position, velocity>();
auto view = registry.view<const position, velocity>();
for(auto entity: view) {
// gets only the components that are going to be used ...
// use a callback
view.each([](const auto &pos, auto &vel) { /* ... */ });
auto &vel = view.get<velocity>(entity);
vel.dx = 0.;
vel.dy = 0.;
// use an extended callback
view.each([](const auto entity, const auto &pos, auto &vel) { /* ... */ });
// use a range-for
for(auto [entity, pos, vel]: view.each()) {
// ...
}
}
void update(std::uint64_t dt, entt::registry &registry) {
registry.view<position, velocity>().each([dt](auto &pos, auto &vel) {
// gets all the components of the view at once ...
pos.x += vel.dx * dt;
pos.y += vel.dy * dt;
// use forward iterators and get only the components of interest
for(auto entity: view) {
auto &vel = view.get<velocity>(entity);
// ...
});
}
}
int main() {
entt::registry registry;
std::uint64_t dt = 16;
for(auto i = 0; i < 10; ++i) {
auto entity = registry.create();
registry.assign<position>(entity, i * 1.f, i * 1.f);
if(i % 2 == 0) { registry.assign<velocity>(entity, i * .1f, i * .1f); }
for(auto i = 0u; i < 10u; ++i) {
const auto entity = registry.create();
registry.emplace<position>(entity, i * 1.f, i * 1.f);
if(i % 2 == 0) { registry.emplace<velocity>(entity, i * .1f, i * .1f); }
}
update(dt, registry);
update(registry);
// ...
}
```
## Motivation
I started developing `EnTT` for the _wrong_ reason: my goal was to design an
entity-component system to beat another well known open source solution both in
entity-component system to beat another well known open source library both in
terms of performance and possibly memory usage.<br/>
In the end, I did it, but it wasn't very satisfying. Actually it wasn't
satisfying at all. The fastest and nothing more, fairly little indeed. When I
@@ -189,8 +185,8 @@ reasons.
If you are interested, you can compile the `benchmark` test in release mode (to
enable compiler optimizations, otherwise it would make little sense) by setting
the `BUILD_BENCHMARK` option of `CMake` to `ON`, then evaluate yourself whether
you're satisfied with the results or not.
the `ENTT_BUILD_BENCHMARK` option of `CMake` to `ON`, then evaluate yourself
whether you're satisfied with the results or not.
Honestly I got tired of updating the README file whenever there is an
improvement.<br/>
@@ -210,21 +206,7 @@ new features, mainly for fun.<br/>
If you want to contribute and/or have suggestions, feel free to make a PR or
open an issue to discuss your idea.
# Build Instructions
## Requirements
To be able to use `EnTT`, users must provide a full-featured compiler that
supports at least C++17.<br/>
The requirements below are mandatory to compile the tests and to extract the
documentation:
* `CMake` version 3.7 or later.
* `Doxygen` version 1.8 or later.
If you are looking for a C++14 version of `EnTT`, check out the git tag `cpp14`.
## Library
# Integration
`EnTT` is a header-only library. This means that including the `entt.hpp` header
is enough to include the library as a whole and use it. For those who are
@@ -245,48 +227,41 @@ Use the line below to include only the entity-component system instead:
Then pass the proper `-I` argument to the compiler to add the `src` directory to
the include paths.
## Documentation
## Requirements
The documentation is based on [doxygen](http://www.doxygen.nl/).
To build it:
To be able to use `EnTT`, users must provide a full-featured compiler that
supports at least C++17.<br/>
The requirements below are mandatory to compile the tests and to extract the
documentation:
$ cd build
$ cmake .. -DBUILD_DOCS=ON
$ make
* `CMake` version 3.7 or later.
* `Doxygen` version 1.8 or later.
The API reference will be created in HTML format within the directory
`build/docs/html`. To navigate it with your favorite browser:
Alternatively, [Bazel](https://bazel.build) is also supported as a build system
(credits to [zaucy](https://github.com/zaucy) who offered to maintain it).<br/>
In the documentation below I'll still refer to `CMake`, this being the official
build system of the library.
$ cd build
$ your_favorite_browser docs/html/index.html
## CMake
<!--
@cond TURN_OFF_DOXYGEN
-->
It's also available [online](https://skypjack.github.io/entt/) for the latest
version, that is the last stable tag.<br/>
Moreover, there exists a [wiki](https://github.com/skypjack/entt/wiki) dedicated
to the project where users can find all related documentation pages.
<!--
@endcond TURN_OFF_DOXYGEN
-->
To use `EnTT` from a `CMake` project, just link an existing target to the
`EnTT::EnTT` alias.<br/>
The library offers everything you need for locating (as in `find_package`),
embedding (as in `add_subdirectory`), fetching (as in `FetchContent`) or using
it in many of the ways that you can think of and that involve `CMake`.<br/>
Covering all possible cases would require a treaty and not a simple README file,
but I'm confident that anyone reading this section also knows what it's about
and can use `EnTT` from a `CMake` project without problems.
## Tests
## Natvis support
To compile and run the tests, `EnTT` requires *googletest*.<br/>
`cmake` will download and compile the library before compiling anything else.
In order to build the tests, set the CMake option `BUILD_TESTING` to `ON`.
When using `CMake`, just enable the option `ENTT_INCLUDE_NATVIS` and enjoy
it.<br/>
Otherwise, most of the tools are covered via Natvis and all files can be found
in the `natvis` directory, divided by module.<br/>
If you spot errors or have suggestions, any contribution is welcome!
To build the most basic set of tests:
* `$ cd build`
* `$ cmake -DBUILD_TESTING=ON ..`
* `$ make`
* `$ make test`
Note that benchmarks are not part of this set.
# Packaging Tools
## Packaging Tools
`EnTT` is available for some of the most known packaging tools. In particular:
@@ -305,6 +280,12 @@ Note that benchmarks are not part of this set.
$ vcpkg install entt
```
Or you can use the `experimental` feature to test the latest changes:
```
vcpkg install entt[experimental] --head
```
The `EnTT` port in `vcpkg` is kept up to date by Microsoft team members and
community contributors.<br/>
If the version is out of date, please
@@ -319,7 +300,84 @@ Note that benchmarks are not part of this set.
brew install skypjack/entt/entt
```
Consider this list a work in progress and help me to make it longer.
* [`build2`](https://build2.org), build toolchain for developing and packaging C
and C++ code.<br/>
In order to use the [`entt`](https://cppget.org/entt) package in a `build2`
project, add the following line or a similar one to the `manifest` file:
```
depends: entt ^3.0.0
```
Also check that the configuration refers to a valid repository, so that the
package can be found by `build2`:
* [`cppget.org`](https://cppget.org), the open-source community central
repository, accessible as `https://pkg.cppget.org/1/stable`.
* [Package source repository](https://github.com/build2-packaging/entt):
accessible as either `https://github.com/build2-packaging/entt.git` or
`ssh://git@github.com/build2-packaging/entt.git`.
Feel free to [report issues](https://github.com/build2-packaging/entt) with
this package.
Both can be used with `bpkg add-repo` or added in a project
`repositories.manifest`. See the official
[documentation](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-repositories)
for more details.
Consider this list a work in progress and help me to make it longer if you like.
## pkg-config
`EnTT` also supports `pkg-config` (for some definition of _supports_ at least).
A suitable file called `entt.pc` is generated and installed in a proper
directory when running `CMake`.<br/>
This should also make it easier to use with tools such as `Meson` or similar.
# Documentation
The documentation is based on [doxygen](http://www.doxygen.nl/). To build it:
$ cd build
$ cmake .. -DENTT_BUILD_DOCS=ON
$ make
The API reference will be created in HTML format within the directory
`build/docs/html`. To navigate it with your favorite browser:
$ cd build
$ your_favorite_browser docs/html/index.html
<!--
@cond TURN_OFF_DOXYGEN
-->
The same version is also available [online](https://skypjack.github.io/entt/)
for the latest release, that is the last stable tag. If you are looking for
something more pleasing to the eye, consider reading the nice-looking version
available on [docsforge](https://entt.docsforge.com/): same documentation, much
more pleasant to read.<br/>
Moreover, there exists a [wiki](https://github.com/skypjack/entt/wiki) dedicated
to the project where users can find all related documentation pages.
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Tests
To compile and run the tests, `EnTT` requires *googletest*.<br/>
`cmake` will download and compile the library before compiling anything else.
In order to build the tests, set the `CMake` option `ENTT_BUILD_TESTING` to
`ON`.
To build the most basic set of tests:
* `$ cd build`
* `$ cmake -DENTT_BUILD_TESTING=ON ..`
* `$ make`
* `$ make test`
Note that benchmarks are not part of this set.
<!--
@cond TURN_OFF_DOXYGEN
@@ -341,18 +399,14 @@ open an issue or a PR and I'll be glad to add them to the list.
# Contributors
`EnTT` was written initially as a faster alternative to other well known and
open source entity-component systems. Nowadays this library is moving its first
steps. Much more will come in the future and hopefully I'm going to work on it
for a long time.<br/>
Requests for features, PR, suggestions ad feedback are highly appreciated.
Requests for features, PRs, suggestions ad feedback are highly appreciated.
If you find you can help me and want to contribute to the project with your
experience or you do want to get part of the project for some other reasons,
feel free to contact me directly (you can find the mail in the
If you find you can help and want to contribute to the project with your
experience or you do want to get part of the project for some other reason, feel
free to contact me directly (you can find the mail in the
[profile](https://github.com/skypjack)).<br/>
I can't promise that each and every contribution will be accepted, but I can
assure that I'll do my best to take them all seriously.
assure that I'll do my best to take them all as soon as possible.
If you decide to participate, please see the guidelines for
[contributing](CONTRIBUTING.md) before to create issues or pull
@@ -366,25 +420,12 @@ know who has participated so far.
# License
Code and documentation Copyright (c) 2017-2020 Michele Caini.<br/>
Logo Copyright (c) 2018-2020 Richard Caseres.
Code and documentation Copyright (c) 2017-2022 Michele Caini.<br/>
Colorful logo Copyright (c) 2018-2021 Richard Caseres.
Code released under
[the MIT license](https://github.com/skypjack/entt/blob/master/LICENSE).
[the MIT license](https://github.com/skypjack/entt/blob/master/LICENSE).<br/>
Documentation released under
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).<br/>
Logo released under
All logos released under
[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
<!--
@cond TURN_OFF_DOXYGEN
-->
# Support
If you want to support this project, you can
[offer me](https://github.com/users/skypjack/sponsorship) an espresso.<br/>
If you find that it's not enough, feel free to
[help me](https://www.paypal.me/skypjack) the way you prefer.
<!--
@endcond TURN_OFF_DOXYGEN
-->

47
TODO
View File

@@ -1,28 +1,27 @@
* long term feature: shared_ptr less locator and resource cache
* custom allocators and EnTT allocator-aware in general (long term feature, I don't actually need it at the moment) - see #22
* debugging tools (#60): the issue online already contains interesting tips on this, look at it
* work stealing job system (see #100) + mt scheduler based on const awareness for types
* meta: sort of meta view based on meta stuff to iterate entities, void * and meta info objects (remove runtime views, welcome reflection)
* add opaque input iterators to views and groups that return tuples <entity, T &...> (proxy), multi-pass guaranteed
* allow to replace std:: with custom implementations
* custom (decoupled) pools ==> N-buffering, shared components, multi-model, hibitsets, and so on
* add examples (and credits) from @alanjfs :)
* static reflection, hint: template<> meta_type_t<Type>: meta_descriptor<name, func..., props..., etc...> (see #342)
* observer: user defined filters (eg .replace<T, &function> or .group<T, U, &func>)
* use underlying_type as entity type within pools and registry? it would make different registries work together flawlessy
* can we write a bool conv func for entt::entity that silently compares it to null?
* reset... reset everywhere...
* is it possible to make 0 the entity null?
* document undocumented parts (entt::overload and a few others)
* any-of rule for views/groups (eg entity has A and any of B/C/D)
- get -> all, exclude -> none
* review prepare after clone and the others have been removed
* remove copy-ctor/op from sparse set and storage (it doesn't make much sense)
* WIP:
- deprecate snapshot, loader, ...
- provide documentation to describe alternatives
EXAMPLES
* filter on runtime values/variables (not only types)
* support to polymorphic types (see #859)
* WIP: snapshot rework/deprecation
- remove snapshot/loader from registry, make them external (faster) tools
- deprecate snapshot classes, update documentation to describe alternatives
DOC:
* storage<void>
* custom storage/view
* examples (and credits) from @alanjfs :)
* update entity doc when the storage based model is in place
TODO (high prio):
* remove the static storage from the const assure in the registry
WIP:
* get rid of observers, storage based views made them pointless - document alternatives
* add storage getter for filters to views and groups
* exploit the tombstone mechanism to allow enabling/disabling entities (see bump, compact and clear for further details)
* basic_storage::bind for cross-registry setups (see and remove todo from entity_copy.cpp)
* process scheduler: reviews, use free lists internally
* dedicated entity storage, in-place O(1) release/destroy for non-orphaned entities, out-of-sync model
* entity-only and exclude-only views (both solved with entity storage and storage<void>)
* custom allocators all over (registry, ...)
* add test for maximum number of entities reached
* deprecate non-owning groups in favor of owning views and view packs, introduce lazy owning views

1
WORKSPACE Normal file
View File

@@ -0,0 +1 @@
workspace(name = "com_github_skypjack_entt")

View File

@@ -1,6 +0,0 @@
set(ENTT_VERSION "@PROJECT_VERSION@")
set(ENTT_INCLUDE_DIRS "@CMAKE_CURRENT_SOURCE_DIR@/src")
if(NOT CMAKE_VERSION VERSION_LESS "3.0")
include("${CMAKE_CURRENT_LIST_DIR}/EnTTTargets.cmake")
endif()

View File

@@ -1,11 +1,5 @@
set(ENTT_VERSION "@PROJECT_VERSION@")
@PACKAGE_INIT@
set_and_check(ENTT_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
if(NOT CMAKE_VERSION VERSION_LESS "3.0")
include("${CMAKE_CURRENT_LIST_DIR}/EnTTTargets.cmake")
endif()
set(EnTT_VERSION "@PROJECT_VERSION@")
include("${CMAKE_CURRENT_LIST_DIR}/EnTTTargets.cmake")
check_required_components("@PROJECT_NAME@")

8
cmake/in/entt.pc.in Normal file
View File

@@ -0,0 +1,8 @@
prefix=@CMAKE_INSTALL_PREFIX@
includedir=@EnTT_PKGCONFIG_INCLUDEDIR@
Name: EnTT
Description: Gaming meets modern C++
Url: https://github.com/skypjack/entt
Version: @ENTT_VERSION@
Cflags: -I${includedir}

View File

@@ -0,0 +1,23 @@
# This module provides function for joining paths
# known from most languages
#
# SPDX-License-Identifier: (MIT OR CC0-1.0)
# Copyright 2020 Jan Tojnar
# https://github.com/jtojnar/cmake-snips
#
# Modelled after Pythons os.path.join
# https://docs.python.org/3.7/library/os.path.html#os.path.join
# Windows not supported
function(join_paths joined_path first_path_segment)
set(temp_path "${first_path_segment}")
foreach(current_segment IN LISTS ARGN)
if(NOT ("${current_segment}" STREQUAL ""))
if(IS_ABSOLUTE "${current_segment}")
set(temp_path "${current_segment}")
else()
set(temp_path "${temp_path}/${current_segment}")
endif()
endif()
endforeach()
set(${joined_path} "${temp_path}" PARENT_SCOPE)
endfunction()

View File

@@ -43,8 +43,8 @@ int main() {
for(auto i = 0; i < 10; ++i) {
auto entity = registry.create();
registry.assign<position>(entity, i * 1.f, i * 1.f);
if(i % 2 == 0) { registry.assign<velocity>(entity, i * .1f, i * .1f); }
registry.emplace<position>(entity, i * 1.f, i * 1.f);
if(i % 2 == 0) { registry.emplace<velocity>(entity, i * .1f, i * .1f); }
}
update(dt, registry);

View File

@@ -9,28 +9,29 @@ set(DOXY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
configure_file(doxy.in doxy.cfg @ONLY)
set(
DOC_SOURCES
dox/extra.dox
md/core.md
md/entity.md
md/faq.md
md/lib.md
md/links.md
md/locator.md
md/meta.md
md/process.md
md/resource.md
md/signal.md
doxy.in
)
add_custom_target(
docs ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.cfg
WORKING_DIRECTORY ${EnTT_SOURCE_DIR}
VERBATIM
SOURCES ${DOC_SOURCES}
SOURCES
dox/extra.dox
md/config.md
md/container.md
md/core.md
md/entity.md
md/faq.md
md/lib.md
md/links.md
md/locator.md
md/meta.md
md/poly.md
md/process.md
md/reference.md
md/resource.md
md/signal.md
md/unreal.md
doxy.in
)
install(

View File

@@ -1,4 +1,4 @@
# Doxyfile 1.8.16
# Doxyfile 1.9.4
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -12,6 +12,15 @@
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
#
# Note:
#
# Use doxygen to compare the used configuration file with the template
# configuration file:
# doxygen -x [configFile]
# Use doxygen to compare the used configuration file with the template
# configuration file without replacing the environment variables:
# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
# Project related configuration options
@@ -60,16 +69,28 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY = @DOXY_OUTPUT_DIRECTORY@
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
# sub-directories (in 2 levels) under the output directory of each output format
# and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
# Controls the number of sub-directories that will be created when
# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
# level increment doubles the number of directories, resulting in 4096
# directories at level 8 which is the default and also the maximum value. The
# sub-directories are organized in 2 levels, the first level always has a fixed
# numer of 16 directories.
# Minimum value: 0, maximum value: 8, default value: 8.
# This tag requires that the tag CREATE_SUBDIRS is set to YES.
CREATE_SUBDIRS_LEVEL = 8
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
@@ -81,26 +102,18 @@ ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
# English messages), Korean, Korean-en (Korean with English messages), Latvian,
# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
# Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all generated output in the proper direction.
# Possible values are: None, LTR, RTL and Context.
# The default value is: None.
OUTPUT_TEXT_DIRECTION = None
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
@@ -217,6 +230,14 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
# By default Python docstrings are displayed as preformatted text and doxygen's
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
# doxygen's special commands can be used and the contents of the docstring
# documentation blocks is shown as doxygen documentation.
# The default value is: YES.
PYTHON_DOCSTRING = YES
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
@@ -240,25 +261,19 @@ TAB_SIZE = 4
# the documentation. An alias has the form:
# name=value
# For example adding
# "sideeffect=@par Side Effects:\n"
# "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines (in the resulting output). You can put ^^ in the value part of an
# alias to insert a newline as if a physical newline was in the original file.
# When you need a literal { or } or , in the value part of an alias you have to
# escape them by means of a backslash (\), this can lead to conflicts with the
# commands \{ and \} for these it is advised to use the version @{ and @} or use
# a double escape (\\{ and \\})
# "Side Effects:". Note that you cannot put \n's in the value part of an alias
# to insert newlines (in the resulting output). You can put ^^ in the value part
# of an alias to insert a newline as if a physical newline was in the original
# file. When you need a literal { or } or , in the value part of an alias you
# have to escape them by means of a backslash (\), this can lead to conflicts
# with the commands \{ and \} for these it is advised to use the version @{ and
# @} or use a double escape (\\{ and \\})
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
@@ -299,19 +314,22 @@ OPTIMIZE_OUTPUT_SLICE = NO
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
# tries to guess whether the code is fixed or free formatted code, this is the
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
# .inc files as Fortran files (default is PHP), and .f files as C (default is
# Fortran), use: inc=Fortran f=C.
# default for Fortran type files). For instance to make doxygen treat .inc files
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
# use: inc=Fortran f=C.
#
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
# the files are not read by doxygen. When specifying no_extension you should add
# * to the FILE_PATTERNS.
#
# Note see also the list of default file extension mappings.
EXTENSION_MAPPING =
@@ -445,6 +463,19 @@ TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
# during processing. When set to 0 doxygen will based this on the number of
# cores available in the system. You can set it explicitly to a value larger
# than 0 to get more control over the balance between CPU load and processing
# speed. At this moment only the input processing can be done using multiple
# threads. Since this is still an experimental feature the default is set to 1,
# which effectively disables parallel processing. Please report any issues you
# encounter. Generating dot graphs in parallel is controlled by the
# DOT_NUM_THREADS setting.
# Minimum value: 0, maximum value: 32, default value: 1.
NUM_PROC_THREADS = 1
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -508,6 +539,13 @@ EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
# If this flag is set to YES, the name of an unnamed parameter in a declaration
# will be determined by the corresponding definition. By default unnamed
# parameters remain unnamed in the output.
# The default value is: YES.
RESOLVE_UNNAMED_PARAMS = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
@@ -525,8 +563,8 @@ HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# declarations. If set to NO, these declarations will be included in the
# documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
@@ -545,11 +583,18 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# (including Cygwin) ands Mac users are advised to set this option to NO.
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
# able to match the capabilities of the underlying filesystem. In case the
# filesystem is case sensitive (i.e. it supports files in the same directory
# whose names only differ in casing), the option must be set to YES to properly
# deal with such files in case they appear in the input. For filesystems that
# are not case sensitive the option should be set to NO to properly deal with
# output files written for symbols that only differ in casing, such as for two
# classes, one named CLASS and the other named Class, and to also support
# references to files without having to specify the exact matching casing. On
# Windows (including Cygwin) and MacOS, users should typically set this option
# to NO, whereas on Linux or other Unix flavors it should typically be set to
# YES.
# The default value is: system dependent.
CASE_SENSE_NAMES = YES
@@ -568,6 +613,12 @@ HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
# will show which file needs to be included to use the class.
# The default value is: YES.
SHOW_HEADERFILE = YES
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
@@ -725,7 +776,8 @@ FILE_VERSION_FILTER =
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file.
# will be used as the name of the layout file. See also section "Changing the
# layout of pages" for information.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
@@ -771,24 +823,35 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
# in a documented function, or documenting parameters that don't exist or using
# markup commands wrongly.
# potential errors in the documentation, such as documenting some parameters in
# a documented function twice, or documenting parameters that don't exist or
# using markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
# function parameter documentation. If set to NO, doxygen will accept that some
# parameters have no documentation without warning.
# The default value is: YES.
WARN_IF_INCOMPLETE_DOC = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation. If
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
# value. If set to NO, doxygen will only warn about wrong parameter
# documentation, but not about the absence of documentation. If EXTRACT_ALL is
# set to YES then this flag will automatically be disabled. See also
# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.
WARN_NO_PARAMDOC = YES
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
# at the end of the doxygen process doxygen will return with a non-zero status.
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
# The default value is: NO.
WARN_AS_ERROR = NO
@@ -799,13 +862,27 @@ WARN_AS_ERROR = NO
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
# In the $text part of the WARN_FORMAT command it is possible that a reference
# to a more specific place is given. To make it easier to jump to this place
# (outside of doxygen) the user can define a custom "cut" / "paste" string.
# Example:
# WARN_LINE_FORMAT = "'vi $file +$line'"
# See also: WARN_FORMAT
# The default value is: at line $line of file $file.
WARN_LINE_FORMAT = "at line $line of file $file"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
# error (stderr). In case the file specified cannot be opened for writing the
# warning and error messages are written to standard error. When as file - is
# specified the warning and error messages are written to standard output
# (stdout).
WARN_LOGFILE =
@@ -826,8 +903,8 @@ INPUT = @DOXY_SOURCE_DIRECTORY@ \
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
# possible encodings.
# documentation (see:
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
@@ -840,11 +917,15 @@ INPUT_ENCODING = UTF-8
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# Note the list of default checked file patterns might differ from the list of
# default file extension mappings.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.h \
*.hpp \
@@ -886,7 +967,7 @@ EXCLUDE_PATTERNS =
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
# ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
@@ -1062,16 +1143,24 @@ USE_HTAGS = NO
VERBATIM_HEADERS = YES
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
# cost of reduced performance. This can be particularly helpful with template
# rich C++ code for which doxygen's built-in parser lacks the necessary type
# information.
# clang parser (see:
# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
# performance. This can be particularly helpful with template rich C++ code for
# which doxygen's built-in parser lacks the necessary type information.
# Note: The availability of this option depends on whether or not doxygen was
# generated with the -Duse_libclang=ON option for CMake.
# The default value is: NO.
CLANG_ASSISTED_PARSING = NO
# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
# tag is set to YES then doxygen will add the directory of each input to the
# include path.
# The default value is: YES.
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
CLANG_ADD_INC_PATHS = YES
# If clang assisted parsing is enabled you can provide the compiler with command
# line options that you would normally use when invoking the compiler. Note that
# the include paths will already be set by doxygen for the files and directories
@@ -1081,10 +1170,13 @@ CLANG_ASSISTED_PARSING = NO
CLANG_OPTIONS =
# If clang assisted parsing is enabled you can provide the clang parser with the
# path to the compilation database (see:
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
# were built. This is equivalent to specifying the "-p" option to a clang tool,
# such as clang-check. These options will then be passed to the parser.
# path to the directory containing a file called compile_commands.json. This
# file is the compilation database (see:
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
# options used when the source files were built. This is equivalent to
# specifying the -p option to a clang tool, such as clang-check. These options
# will then be passed to the parser. Any options specified with CLANG_OPTIONS
# will be added as well.
# Note: The availability of this option depends on whether or not doxygen was
# generated with the -Duse_libclang=ON option for CMake.
@@ -1101,13 +1193,6 @@ CLANG_DATABASE_PATH =
ALPHABETICAL_INDEX = YES
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
@@ -1207,7 +1292,7 @@ HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# this color. Hue is specified as an angle on a color-wheel, see
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
@@ -1217,7 +1302,7 @@ HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
# in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1246,9 +1331,9 @@ HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that
# are dynamically created via Javascript. If disabled, the navigation index will
# are dynamically created via JavaScript. If disabled, the navigation index will
# consists of multiple levels of tabs that are statically embedded in every HTML
# page. Disable this option to support browsers that do not have Javascript,
# page. Disable this option to support browsers that do not have JavaScript,
# like the Qt help browser.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1278,10 +1363,11 @@ HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# environment (see:
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
# create a documentation set, doxygen will generate a Makefile in the HTML
# output directory. Running make will produce the docset in that directory and
# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
# genXcode/_index.html for more information.
@@ -1298,6 +1384,13 @@ GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag determines the URL of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDURL =
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
@@ -1323,8 +1416,12 @@ DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
# on Windows. In the beginning of 2021 Microsoft took the original page, with
# a.o. the download links, offline the HTML help workshop was already many years
# in maintenance mode). You can download the HTML help workshop from the web
# archives at Installation executable (see:
# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@@ -1354,7 +1451,7 @@ CHM_FILE =
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1399,7 +1496,8 @@ QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1407,8 +1505,8 @@ QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
# folders).
# Folders (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1416,16 +1514,16 @@ QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
# filters).
# Filters (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
# filters).
# Filters (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
@@ -1437,9 +1535,9 @@ QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# The QHG_LOCATION tag can be used to specify the location (absolute path
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
# run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
@@ -1482,16 +1580,28 @@ DISABLE_INDEX = NO
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# further fine tune the look of the index (see "Fine-tuning the output"). As an
# example, the default style sheet generated by doxygen has an example that
# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
# Since the tree basically has the same information as the tab index, you could
# consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
# area (value NO) or if it should extend to the full height of the window (value
# YES). Setting this to YES gives a layout similar to
# https://docs.readthedocs.io with more room for contents, but less room for the
# project logo, title, and description. If either GENERATE_TREEVIEW or
# DISABLE_INDEX is set to NO, this option has no effect.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
FULL_SIDEBAR = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
@@ -1516,6 +1626,24 @@ TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
# addresses.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
OBFUSCATE_EMAILS = YES
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
# the HTML output. These images will generally look nicer at scaled resolutions.
# Possible values are: png (the default) and svg (looks nicer but requires the
# pdf2svg or inkscape tool).
# The default value is: png.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FORMULA_FORMAT = png
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
@@ -1536,8 +1664,14 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details.
FORMULA_MACROFILE =
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# https://www.mathjax.org) which uses client side Javascript for the rendering
# https://www.mathjax.org) which uses client side JavaScript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
@@ -1547,11 +1681,29 @@ FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
# Note that the different versions of MathJax have different requirements with
# regards to the different settings, so it is possible that also other MathJax
# settings have to be changed when switching between the different MathJax
# versions.
# Possible values are: MathJax_2 and MathJax_3.
# The default value is: MathJax_2.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_VERSION = MathJax_2
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/latest/output.html) for more details.
# the MathJax output. For more details about the output format see MathJax
# version 2 (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
# (see:
# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# compatibility. This is the name for Mathjax version 2, for MathJax version 3
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
# is the name for Mathjax version 3, for MathJax version 2 this will be
# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
@@ -1564,22 +1716,29 @@ MATHJAX_FORMAT = HTML-CSS
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment.
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
# MathJax from https://www.mathjax.org before deployment. The default value is:
# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# for MathJax version 2 (see
# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# For example for MathJax version 3 (see
# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
# (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
@@ -1607,7 +1766,7 @@ MATHJAX_CODEFILE =
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
# implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
@@ -1626,7 +1785,8 @@ SERVER_BASED_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/).
# Xapian (see:
# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
@@ -1639,8 +1799,9 @@ EXTERNAL_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/). See the section "External Indexing and
# Searching" for details.
# Xapian (see:
# https://xapian.org/). See the section "External Indexing and Searching" for
# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
@@ -1749,29 +1910,31 @@ PAPER_TYPE = a4
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
# chapter. If it is left blank doxygen will generate a standard header. See
# section "Doxygen usage" for information on how to let doxygen write the
# default header to a separate file.
# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
# the generated LaTeX document. The header should contain everything until the
# first chapter. If it is left blank doxygen will generate a standard header. It
# is highly recommended to start with a default header using
# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
# and then modify the file new_header.tex. See also section "Doxygen usage" for
# information on how to generate the default header that doxygen normally uses.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
# string, for the replacement values of the other commands the user is referred
# to HTML_HEADER.
# Note: Only use a user-defined header if you know what you are doing!
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. The following
# commands have a special meaning inside the header (and footer): For a
# description of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer. See
# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
# the generated LaTeX document. The footer should contain everything after the
# last chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# special commands can be used inside the footer. See also section "Doxygen
# usage" for information on how to generate the default footer that doxygen
# normally uses. Note: Only use a user-defined footer if you know what you are
# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
@@ -1804,9 +1967,11 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
# files. Set this option to YES, to get a higher quality PDF documentation.
#
# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1814,8 +1979,7 @@ USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
# if errors occur, instead of asking the user for help. This option is also used
# when generating formulas in HTML.
# if errors occur, instead of asking the user for help.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1828,16 +1992,6 @@ LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
# code with syntax highlighting in the LaTeX output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
@@ -1918,16 +2072,6 @@ RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
@@ -2024,15 +2168,6 @@ GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
@@ -2100,7 +2235,7 @@ ENABLE_PREPROCESSING = YES
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = NO
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
@@ -2119,7 +2254,8 @@ SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor.
# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
@@ -2211,15 +2347,6 @@ EXTERNAL_PAGES = YES
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = YES
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
@@ -2238,7 +2365,7 @@ HIDE_UNDOC_RELATIONS = YES
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: YES.
# The default value is: NO.
HAVE_DOT = YES
@@ -2276,11 +2403,14 @@ DOT_FONTSIZE = 10
DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
# graph for each documented class showing the direct and indirect inheritance
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
# to TEXT the direct and indirect inheritance relations will be shown as texts /
# links.
# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
@@ -2294,7 +2424,8 @@ CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies.
# groups, showing the direct groups dependencies. See also the chapter Grouping
# in the manual.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2317,10 +2448,32 @@ UML_LOOK = NO
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
# tag is set to YES, doxygen will add type and arguments for attributes and
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
# will not generate fields with class member information in the UML graphs. The
# class diagrams will look similar to the default class diagrams but using UML
# notation for the relationships.
# Possible values are: NO, YES and NONE.
# The default value is: NO.
# This tag requires that the tag UML_LOOK is set to YES.
DOT_UML_DETAILS = NO
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
# to display on a single line. If the actual line length exceeds this threshold
# significantly it will wrapped across multiple lines. Some heuristics are apply
# to avoid ugly line breaks.
# Minimum value: 0, maximum value: 1000, default value: 17.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_WRAP_THRESHOLD = 17
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
@@ -2387,6 +2540,13 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
# of child directories generated in directory dependency graphs by dot.
# Minimum value: 1, maximum value: 25, default value: 1.
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
DIR_GRAPH_MAX_DEPTH = 1
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see:
@@ -2394,9 +2554,7 @@ DIRECTORY_GRAPH = YES
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png.
@@ -2442,10 +2600,10 @@ MSCFILE_DIRS =
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
# path where java can find the plantuml.jar file or to the filename of jar file
# to be used. If left blank, it is assumed PlantUML is not used or called during
# a preprocessing step. Doxygen will generate a warning when it encounters a
# \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH =
@@ -2507,14 +2665,18 @@ DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
#
# Note: This setting is not only used for dot files but also for msc temporary
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES

121
docs/md/config.md Normal file
View File

@@ -0,0 +1,121 @@
# Crash Course: configuration
<!--
@cond TURN_OFF_DOXYGEN
-->
# Table of Contents
* [Introduction](#introduction)
* [Definitions](#definitions)
* [ENTT_NOEXCEPTION](#entt_noexception)
* [ENTT_USE_ATOMIC](#entt_use_atomic)
* [ENTT_ID_TYPE](#entt_id_type)
* [ENTT_SPARSE_PAGE](#entt_sparse_page)
* [ENTT_PACKED_PAGE](#entt_packed_page)
* [ENTT_ASSERT](#entt_assert)
* [ENTT_ASSERT_CONSTEXPR](#entt_assert_constexpr)
* [ENTT_DISABLE_ASSERT](#entt_disable_assert)
* [ENTT_NO_ETO](#entt_no_eto)
* [ENTT_STANDARD_CPP](#entt_standard_cpp)
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction
`EnTT` has become almost completely customizable over time, in many
respects. These variables are just one of the many ways to customize how it
works.<br/>
In the vast majority of cases, users will have no interest in changing the
default parameters. For all other cases, the list of possible configurations
with which it's possible to adjust the behavior of the library at runtime can be
found below.
# Definitions
All options are intended as parameters to the compiler (or user-defined macros
within the compilation units, if preferred).<br/>
Each parameter can result in internal library definitions. It's not recommended
to try to also modify these definitions, since there is no guarantee that they
will remain stable over time unlike the options below.
## ENTT_NOEXCEPTION
Define this variable without assigning any value to it to turn off exception
handling in `EnTT`.<br/>
This is roughly equivalent to setting the compiler flag `-fno-exceptions` but is
also limited to this library only.
## ENTT_USE_ATOMIC
In general, `EnTT` doesn't offer primitives to support multi-threading. Many of
the features can be split over multiple threads without any explicit control and
the user is the one who knows if a synchronization point is required.<br/>
However, some features aren't easily accessible to users and are made
thread-safe by means of this definition.
## ENTT_ID_TYPE
`entt::id_type` is directly controlled by this definition and widely used within
the library.<br/>
By default, its type is `std::uint32_t`. However, users can define a different
default type if necessary.
## ENTT_SPARSE_PAGE
It's known that the ECS module of `EnTT` is based on _sparse sets_. What is less
known perhaps is that the sparse arrays are paged to reduce memory usage.<br/>
Default size of pages (that is, the number of elements they contain) is 4096 but
users can adjust it if appropriate. In all case, the chosen value **must** be a
power of 2.
## ENTT_PACKED_PAGE
As it happens with sparse arrays, packed arrays are also paginated. However, in
this case the aim isn't to reduce memory usage but to have pointer stability
upon component creation.<br/>
Default size of pages (that is, the number of elements they contain) is 1024 but
users can adjust it if appropriate. In all case, the chosen value **must** be a
power of 2.
## ENTT_ASSERT
For performance reasons, `EnTT` doesn't use exceptions or any other control
structures. In fact, it offers many features that result in undefined behavior
if not used correctly.<br/>
To get around this, the library relies on a lot of asserts for the purpose of
detecting errors in debug builds. By default, it uses `assert` internally. Users
are allowed to overwrite its behavior by setting this variable.
### ENTT_ASSERT_CONSTEXPR
Usually, an assert within a `constexpr` function isn't a big deal. However, in
case of extreme customizations, it might be useful to differentiate.<br/>
For this purpose, `EnTT` introduces an admittedly badly named variable to make
the job easier in this regard. By default, this variable forwards its arguments
to `ENTT_ASSERT`.
### ENTT_DISABLE_ASSERT
Assertions may in turn affect performance to an extent when enabled. Whether
`ENTT_ASSERT` and `ENTT_ASSERT_CONSTEXPR` are redefined or not, all asserts can
be disabled at once by means of this definition.<br/>
Note that `ENTT_DISABLE_ASSERT` takes precedence over the redefinition of the
other variables and is therefore meant to disable all controls no matter what.
## ENTT_NO_ETO
In order to reduce memory consumption and increase performance, empty types are
never instantiated nor stored by the ECS module of `EnTT`.<br/>
Use this variable to treat these types like all others and therefore to create a
dedicated storage for them.
## ENTT_STANDARD_CPP
`EnTT` mixes non-standard language features with others that are perfectly
compliant to offer some of its functionalities.<br/>
This definition prevents the library from using non-standard techniques, that
is, functionalities that aren't fully compliant with the standard C++.<br/>
While there are no known portability issues at the time of this writing, this
should make the library fully portable anyway if needed.

67
docs/md/container.md Normal file
View File

@@ -0,0 +1,67 @@
# Crash Course: containers
<!--
@cond TURN_OFF_DOXYGEN
-->
# Table of Contents
* [Introduction](#introduction)
* [Containers](#containers)
* [Dense map](#dense-map)
* [Dense set](#dense-set)
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction
The standard C++ library offers a wide range of containers and it's really
difficult to do better (although it's very easy to do worse, as many examples
available online demonstrate).<br/>
`EnTT` doesn't try in any way to replace what is offered by the standard. Quite
the opposite, given the widespread use that is made of standard containers.<br/>
However, the library also tries to fill a gap in features and functionality by
making available some containers initially developed for internal use.
This section of the library is likely to grow larger over time. However, for the
moment it's quite small and mainly aimed at satisfying some internal needs.<br/>
For all containers made available, full test coverage and stability over time is
guaranteed as usual.
# Containers
## Dense map
The dense map made available in `EnTT` is a hash map that aims to return a
packed array of elements, so as to reduce the number of jumps in memory during
iterations.<br/>
The implementation is based on _sparse sets_ and each bucket is identified by an
implicit list within the packed array itself.
The interface is very close to its counterpart in the standard library, that is,
`std::unordered_map`.<br/>
However, both local and non-local iterators returned by a dense map belong to
the input iterator category although they respectively model the concepts of a
_forward iterator_ type and a _random access iterator_ type.<br/>
This is because they return a pair of references rather than a reference to a
pair. In other words, dense maps return a so called _proxy iterator_ the value
type of which is:
* `std::pair<const Key &, Type &>` for non-const iterator types.
* `std::pair<const Key &, const Type &>` for const iterator types.
This is quite different from what any standard library map returns and should be
taken into account when looking for a drop-in replacement.
## Dense set
The dense set made available in `EnTT` is a hash set that aims to return a
packed array of elements, so as to reduce the number of jumps in memory during
iterations.<br/>
The implementation is based on _sparse sets_ and each bucket is identified by an
implicit list within the packed array itself.
The interface is in all respects similar to its counterpart in the standard
library, that is, `std::unordered_set`.<br/>
Therefore, there is no need to go into the API description.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,18 +13,20 @@
* [Warning C4307: integral constant overflow](#warning-C4307-integral-constant-overflow)
* [Warning C4003: the min, the max and the macro](#warning-C4003-the-min-the-max-and-the-macro)
* [The standard and the non-copyable types](#the-standard-and-the-non-copyable-types)
* [Which functions trigger which signals](#which-functions-trigger-which-signals)
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction
This is a constantly updated section where I'll try to put the answers to the
This is a constantly updated section where I'm trying to put the answers to the
most frequently asked questions.<br/>
If you don't find your answer here, there are two cases: nobody has done it yet
or this section needs updating. In both cases, try to
[open a new issue](https://github.com/skypjack/entt/issues/new) or enter the
[gitter channel](https://gitter.im/skypjack/entt) and ask your question.
or this section needs updating. In both cases, you can
[open a new issue](https://github.com/skypjack/entt/issues/new) or enter either
the [gitter channel](https://gitter.im/skypjack/entt) or the
[discord server](https://discord.gg/5BjPWBd) to ask for help.<br/>
Probably someone already has an answer for you and we can then integrate this
part of the documentation.
@@ -44,14 +46,14 @@ lot, achieving good results in many cases.
First of all, there are two things to do in a Windows project:
* Disable the [`/JMC`](https://docs.microsoft.com/cpp/build/reference/jmc)
option (_Just My Code_ debugging), available starting in Visual Studio 2017
option (_Just My Code_ debugging), available starting with Visual Studio 2017
version 15.8.
* Set the [`_ITERATOR_DEBUG_LEVEL`](https://docs.microsoft.com/cpp/standard-library/iterator-debug-level)
macro to 0. This will disable checked iterators and iterator debugging.
Moreover, the macro `ENTT_ASSERT` should be redefined to disable internal checks
made by `EnTT` in debug:
Moreover, set the `ENTT_DISABLE_ASSERT` variable or redefine the `ENTT_ASSERT`
macro to disable internal debug checks in `EnTT`:
```cpp
#define ENTT_ASSERT(...) ((void)0)
@@ -60,70 +62,52 @@ made by `EnTT` in debug:
These asserts are introduced to help the users but they require to access to the
underlying containers and therefore risk ruining the performance in some cases.
With these changes, debug performance should increase enough for most cases. If
you want something more, you can can also switch to an optimization level `O0`
or preferably `O1`.
With these changes, debug performance should increase enough in most cases. If
you want something more, you can also switch to an optimization level `O0` or
preferably `O1`.
## How can I represent hierarchies with my components?
This is one of the first questions that anyone makes when starting to work with
the entity-component-system architectural pattern.<br/>
There are several approaches to the problem and whats the best one depends
mainly on the real problem one is facing. In all cases, how to do it doesn't
strictly depend on the library in use, but the latter can certainly allow or
not different techniques depending on how the data are laid out.
There are several approaches to the problem and the best one depends mainly on
the real problem one is facing. In all cases, how to do it doesn't strictly
depend on the library in use, but the latter certainly allows or not different
techniques depending on how the data are laid out.
I tried to describe some of the techniques that fit well with the model of
`EnTT`. [Here](https://skypjack.github.io/2019-06-25-ecs-baf-part-4/) is the
first post of a series that tries to explore the problem. More will probably
come in future.
Long story short, you can always define a tree where the nodes expose implicit
lists of children by means of the following type:
```cpp
struct relationship {
std::size_t children{};
entt::entity first{entt::null};
entt::entity prev{entt::null};
entt::entity next{entt::null};
entt::entity parent{entt::null};
// ... other data members ...
};
```
The sort functionalities of `EnTT`, the groups and all the other features of the
library can help then to get the best in terms of data locality and therefore
performance from this component.
I tried to describe some of the approaches that fit well with the model of
`EnTT`. [This](https://skypjack.github.io/2019-06-25-ecs-baf-part-4/) is the
first post of a series that tries to _explore_ the problem. More will probably
come in future.<br/>
In addition, `EnTT` also offers the possibility to create stable storage types
and therefore have pointer stability for one, all or some components. This is by
far the most convenient solution when it comes to creating hierarchies and
whatnot. See the documentation for the ECS part of the library and in particular
what concerns the `component_traits` class for further details.
## Custom entity identifiers: yay or nay?
Custom entity identifiers are definitely a good idea in two cases at least:
* If `std::uint32_t` isn't large enough as an underlying type.
* If `std::uint32_t` isn't large enough for your purposes, since this is the
underlying type of `entt::entity`.
* If you want to avoid conflicts when using multiple registries.
These identifiers are nothing more than enum classes with some salt.<br/>
To simplify the creation of new identifiers, `EnTT` provides the macro
`ENTT_OPAQUE_TYPE` that accepts two arguments:
* The name you want to give to the new identifier (watch out for namespaces).
* The underlying type to use (either `std::uint16_t`, `std::uint32_t`
or `std::uint64_t`).
In fact, this is the definition of `entt::entity`:
Identifiers can be defined through enum classes and class types that define an
`entity_type` member of type `std::uint32_t` or `std::uint64_t`.<br/>
In fact, this is a definition equivalent to that of `entt::entity`:
```cpp
ENTT_OPAQUE_TYPE(entity, std::uint32_t)
enum class entity: std::uint32_t {};
```
The use of this macro is highly recommended, so as not to run into problems if
the requirements for the identifiers should change in the future.
There is no limit to the number of identifiers that can be defined.
## Warning C4307: integral constant overflow
According to [this](https://github.com/skypjack/entt/issues/121) issue, using a
hashed string under VS could generate a warning.<br/>
hashed string under VS (toolset v141) could generate a warning.<br/>
First of all, I want to reassure you: it's expected and harmless. However, it
can be annoying.
@@ -132,7 +116,7 @@ here is a workaround in the form of a macro:
```cpp
#if defined(_MSC_VER)
#define HS(str) __pragma(warning(suppress:4307)) entt::hashed_string{str}\
#define HS(str) __pragma(warning(suppress:4307)) entt::hashed_string{str}
#else
#define HS(str) entt::hashed_string{str}
#endif
@@ -154,7 +138,7 @@ errors during compilation.
It's a pretty big problem but fortunately it's not a problem of `EnTT` and there
is a fairly simple solution to it.<br/>
It consists in defining the `NOMINMAX` macro before to include any other header
It consists in defining the `NOMINMAX` macro before including any other header
so as to get rid of the extra definitions:
```cpp
@@ -167,15 +151,14 @@ more details.
## The standard and the non-copyable types
`EnTT` uses internally the trait `std::is_copy_constructible_v` to check if a
component is actually copyable. This trait doesn't check if an object can
actually be copied but only verifies if there is a copy constructor
available.<br/>
This can lead to surprising results due to some idiosyncrasies of the standard
mainly related to the need to guarantee backward compatibility.
component is actually copyable. However, this trait doesn't really check whether
a type is actually copyable. Instead, it just checks that a suitable copy
constructor and copy operator exist.<br/>
This can lead to surprising results due to some idiosyncrasies of the standard.
For example, `std::vector` defines a copy constructor no matter if its value
type is copyable or not. As a result, `std::is_copy_constructible_v` is true
for the following specialization:
For example, `std::vector` defines a copy constructor that is conditionally
enabled depending on whether the value type is copyable or not. As a result,
`std::is_copy_constructible_v` returns true for the following specialization:
```cpp
struct type {
@@ -183,18 +166,50 @@ struct type {
};
```
When trying to assign an instance of this type to an entity in the ECS part,
this may trigger a compilation error because we cannot really make a copy of
it.<br/>
As a workaround, users can mark the type explicitly as non-copyable:
However, the copy constructor is effectively disabled upon specialization.
Therefore, trying to assign an instance of this type to an entity may trigger a
compilation error.<br/>
As a workaround, users can mark the type explicitly as non-copyable. This also
suppresses the implicit generation of the move constructor and operator, which
will therefore have to be defaulted accordingly:
```cpp
struct type {
type(const type &) = delete;
type(type &&) = default;
type & operator=(const type &) = delete;
type & operator=(type &&) = default;
std::vector<std::unique_ptr<action>> vec;
};
```
Unfortunately, this will also disable aggregate initialization.
Note that aggregate initialization is also disabled as a consequence.<br/>
Fortunately, this type of trick is quite rare. The bad news is that there is no
way to deal with it at the library level, this being due to the design of the
language. On the other hand, the fact that the language itself also offers a way
to mitigate the problem makes it manageable.
## Which functions trigger which signals
The `registry` class offers three signals that are emitted following specific
operations. Maybe not everyone knows what these operations are, though.<br/>
If this isn't clear, below you can find a _vademecum_ for this purpose:
* `on_created` is invoked when a component is first added (neither modified nor
replaced) to an entity.
* `on_update` is called whenever an existing component is modified or replaced.
* `on_destroyed` is called when a component is explicitly or implicitly removed
from an entity.
Among the most controversial functions can be found `emplace_or_replace` and
`destroy`. However, following the above rules, it's quite simple to know what
will happen.<br/>
In the first case, `on_created` is invoked if the entity has not the component,
otherwise the latter is replaced and therefore `on_update` is triggered. As for
the second case, components are removed from their entities and thus freed when
they are recycled. It means that `on_destroyed` is triggered for every component
owned by the entity that is destroyed.

299
docs/md/graph.md Normal file
View File

@@ -0,0 +1,299 @@
# Crash Course: graph
<!--
@cond TURN_OFF_DOXYGEN
-->
# Table of Contents
* [Introduction](#introduction)
* [Data structures](#data-structures)
* [Adjacency matrix](#adjacency-matrix)
* [Graphviz dot language](#graphviz-dot-language)
* [Flow builder](#flow-builder)
* [Tasks and resources](#tasks-and-resources)
* [Fake resources and order of execution](#fake-resources-and-order-of-execution)
* [Sync points](#sync-points)
* [Execution graph](#execution-graph)
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction
`EnTT` doesn't aim to offer everything one needs to work with graphs. Therefore,
anyone looking for this in the _graph_ submodule will be disappointed.<br/>
Quite the opposite is true. This submodule is minimal and contains only the data
structures and algorithms strictly necessary for the development of some tools
such as the _flow builder_.
# Data structures
As anticipated in the introduction, the aim isn't to offer all possible data
structures suitable for representing and working with graphs. Many will likely
be added or refined over time, however I want to discourage anyone expecting
tight scheduling on the subject.<br/>
The data structures presented in this section are mainly useful for the
development and support of some tools which are also part of the same submodule.
## Adjacency matrix
The adjacency matrix is designed to represent either a directed or an undirected
graph:
```cpp
entt::adjacency_matrix<entt::directed_tag> adjacency_matrix{};
```
The `directed_tag` type _creates_ the graph as directed. There is also an
`undirected_tag` counterpart which creates it as undirected.<br/>
The interface deviates slightly from the typical double indexing of C and offers
an API that is perhaps more familiar to a C++ programmer. Therefore, the access
and modification of an element will take place via the `contains`, `insert` and
`erase` functions rather than a double call to an `operator[]`:
```cpp
if(adjacency_matrix.contains(0u, 1u)) {
adjacency_matrix.erase(0u, 1u);
} else {
adjacency_matrix.insert(0u, 1u);
}
```
Both `insert` and` erase` are idempotent functions which have no effect if the
element already exists or has already been deleted.<br/>
The first one returns an `std::pair` containing the iterator to the element and
a boolean value indicating whether the element has been inserted or was already
present. The second one instead returns the number of deleted elements (0 or 1).
An adjacency matrix must be initialized with the number of elements (vertices)
when constructing it but can also be resized later using the `resize` function:
```cpp
entt::adjacency_matrix<entt::directed_tag> adjacency_matrix{3u};
```
To visit all vertices, the class offers a function named `vertices` that returns
an iterable object suitable for the purpose:
```cpp
for(auto &&vertex: adjacency_matrix.vertices()) {
// ...
}
```
Note that the same result can be obtained with the following snippet, since the
vertices are unsigned integral values:
```cpp
for(auto last = adjacency_matrix.size(), pos = {}; pos < last; ++pos) {
// ...
}
```
As for visiting the edges, a few functions are available.<br/>
When the purpose is to visit all the edges of a given adjacency matrix, the
`edges` function returns an iterable object that can be used to get them as
pairs of vertices:
```cpp
for(auto [lhs, rhs]: adjacency_matrix.edges()) {
// ...
}
```
On the other hand, if the goal is to visit all the in- or out-edges of a given
vertex, the `in_edges` and `out_edges` functions are meant for that:
```cpp
for(auto [lhs, rhs]: adjacency_matrix.out_edges(3u)) {
// ...
}
```
As might be expected, these functions expect the vertex to visit (that is, to
return the in- or out-edges for) as an argument.<br/>
Finally, the adjacency matrix is an allocator-aware container and offers most of
the functionality one would expect from this type of containers, such as `clear`
or 'get_allocator` and so on.
## Graphviz dot language
As it's one of the most popular formats, the library offers minimal support for
converting a graph to a Graphviz dot snippet.<br/>
The simplest way is to pass both an output stream and a graph to the `dot`
function:
```cpp
std::ostringstream output{};
entt::dot(output, adjacency_matrix);
```
However, there is also the option of providing a callback to which the vertices
are passed and which can be used to add (`dot`) properties to the output from
time to time:
```cpp
std::ostringstream output{};
entt::dot(output, adjacency_matrix, [](auto &output, auto vertex) {
out << "label=\"v\"" << vertex << ",shape=\"box\"";
});
```
This second mode is particularly convenient when the user wants to associate
data managed externally to the graph being converted.
# Flow builder
A flow builder is used to create execution graphs from tasks and resources.<br/>
The implementation is as generic as possible and doesn't bind to any other part
of the library.
This class is designed as a sort of _state machine_ to which a specific task is
attached for which the resources accessed in read-only or read-write mode are
specified.<br/>
Most of the functions in the API also return the flow builder itself, according
to what is the common sense API when it comes to builder classes.
Once all tasks have been registered and resources assigned to them, an execution
graph in the form of an adjacency matrix is returned to the user.<br/>
This graph contains all the tasks assigned to the flow builder in the form of
_vertices_. The _vertex_ itself can be used as an index to get the identifier
passed during registration.
## Tasks and resources
Although these terms are used extensively in the documentation, the flow builder
has no real concept of tasks and resources.<br/>
This class works mainly with _identifiers_, that is, values of type `id_type`.
That is, both tasks and resources are identified by integral values.<br/>
This allows not to couple the class itself to the rest of the library or to any
particular data structure. On the other hand, it requires the user to keep track
of the association between identifiers and operations or actual data.
Once a flow builder has been created (which requires no constructor arguments),
the first thing to do is to bind a task. This will indicate to the builder who
intends to consume the resources that will be specified immediately after:
```cpp
entt::flow builder{};
builder.bind("task_1"_hs);
```
Note that the example uses the `EnTT` hashed string to generate an identifier
for the task.<br/>
Indeed, the use of `id_type` as an identifier type is not by accident. In fact,
it matches well with the internal hashed string class. Moreover, it's also the
same type returned by the hash function of the internal RTTI system, in case the
user wants to rely on that.<br/>
However, being an integral value, it leaves the user full freedom to rely on his
own tools if he deems it necessary.
Once a task has been associated with the flow builder, it can be assigned
read-only or read-write resources, as appropriate:
```cpp
builder
.bind("task_1"_hs)
.ro("resource_1"_hs)
.ro("resource_2"_hs)
.bind("task_2"_hs)
.rw("resource_2"_hs)
```
As mentioned, many functions return the builder itself and it's therefore easy
to concatenate the different calls.<br/>
Also in the case of resources, these are identified by numeric values of type
`id_type`. As above, the choice is not entirely random. This goes well with the
tools offered by the library while leaving room for maximum flexibility.
Finally, both the `ro` and` rw` functions also offer an overload that accepts a
pair of iterators, so that one can pass a range of resources in one go.
## Fake resources and order of execution
The flow builder doesn't offer the ability to specify when a task should execute
before or after another task.<br/>
In fact, the order of _registration_ on the resources also determines the order
in which the tasks are processed during the generation of the execution graph.
However, there is a way to force the execution order of two processes.<br/>
Briefly, since accessing a resource in opposite modes requires sequential rather
than parallel scheduling, it's possible to make use of fake resources to force
the order execution:
```cpp
builder
.bind("task_1"_hs)
.ro("resource_1"_hs)
.rw("fake"_hs)
.bind("task_2"_hs)
.ro("resource_2"_hs)
.ro("fake"_hs)
.bind("task_3"_hs)
.ro("resource_2"_hs)
.ro("fake"_hs)
```
This snippet forces the execution of `task_2` and `task_3` **after** `task_1`.
This is due to the fact that the latter sets a read-write requirement on a fake
resource that the other tasks also want to access in read-only mode.<br/>
Similarly, it's possible to force a task to run after a certain group:
```cpp
builder
.bind("task_1"_hs)
.ro("resource_1"_hs)
.ro("fake"_hs)
.bind("task_2"_hs)
.ro("resource_1"_hs)
.ro("fake"_hs)
.bind("task_3"_hs)
.ro("resource_2"_hs)
.rw("fake"_hs)
```
In this case, since there are a number of processes that want to read a specific
resource, they will do so in parallel by forcing `task_3` to run after all the
others tasks.
## Sync points
Sometimes it's useful to assign the role of _sync point_ to a node.<br/>
Whether it accesses new resources or is simply a watershed, the procedure for
assigning this role to a vertex is always the same: first it's tied to the flow
builder, then the `sync` function is invoked:
```cpp
builder.bind("sync_point"_hs).sync();
```
The choice to assign an _identity_ to this type of nodes lies in the fact that,
more often than not, they also perform operations on resources.<br/>
If this isn't the case, it will still be possible to create no-op vertices to
which empty tasks are assigned.
## Execution graph
Once both the resources and their consumers have been properly registered, the
purpose of this tool is to generate an execution graph that takes into account
all specified constraints to return the best scheduling for the vertices:
```cpp
entt::adjacency_matrix<entt::directed_tag> graph = builder.graph();
```
The search for the main vertices, that is those without in-edges, is usually the
first thing required:
```cpp
for(auto &&vertex: graph) {
if(auto in_edges = graph.in_edges(vertex); in_edges.begin() == in_edges.end()) {
// ...
}
}
```
Starting from them, using the other functions appropriately (such as `out_edges`
to retrieve the children of a given task or `edges` to access their identifiers)
it will be possible to instantiate an execution graph.

View File

@@ -5,80 +5,76 @@
-->
# Table of Contents
* [Introduction](#introduction)
* [The EnTT way](#the-entt-way)
* [Meta context](#meta-context)
* [Memory management](#memory-management)
* [Working across boundaries](#working-across-boundaries)
* [Smooth until proven otherwise](#smooth-until-proven-otherwise)
* [Meta context](#meta-context)
* [Memory management](#memory-management)
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction
# Working across boundaries
`EnTT` has historically had a limit when used across boundaries on Windows in
general and on GNU/Linux when default visibility was set to hidden. The
limitation was mainly due to a custom utility used to assign unique, sequential
identifiers to different types.<br/>
Fortunately, nowadays using `EnTT` across boundaries is straightforward. In
fact, everything just works transparently in almost all cases. There are only a
few exceptions, easy to deal with anyway.
identifiers with different types.<br/>
Fortunately, nowadays using `EnTT` across boundaries is much easier.
# The EnTT way
## Smooth until proven otherwise
Many classes in `EnTT` make extensive use of type erasure for their purposes.
This isn't a problem in itself (in fact, it's the basis of an API so convenient
This isn't a problem on itself (in fact, it's the basis of an API so convenient
to use). However, a way is needed to recognize the objects whose type has been
erased on the other side of a boundary.<br/>
The `type_info` class template is how identifiers are generated and thus made
available to the rest of the library.
The `type_hash` class template is how identifiers are generated and thus made
available to the rest of the library. In general, this class doesn't arouse much
interest. The only exception is when a conflict between identifiers occurs
(definitely uncommon though) or when the default solution proposed by `EnTT`
isn't suitable for the user's purposes.<br/>
The section dedicated to `type_info` contains all the details to get around the
issue in a concise and elegant way. Please refer to the specific documentation.
In general, this class doesn't arouse much interest. The only exception is in
case of conflicts between identifiers (definitely uncommon though) or where the
default solution proposed by `EnTT` isn't suitable for the user's purposes.<br/>
The section dedicated to this core class contains all the details to get around
the problem in a concise and elegant way. Please refer to the specific
documentation.
When working with linked libraries, compile definitions `ENTT_API_EXPORT` and
`ENTT_API_IMPORT` can be used where there is a need to import or export symbols,
so as to make everything work nicely across boundaries.<br/>
On the other hand, everything should run smoothly when working with plugins or
shared libraries that don't export any symbols.
# Meta context
For anyone who needs more details, the test suite contains multiple examples
covering the most common cases (see the `lib` directory for all details).<br/>
It goes without saying that it's impossible to cover **all** possible cases.
However, what is offered should hopefully serve as a basis for all of them.
## Meta context
The runtime reflection system deserves a special mention when it comes to using
it across boundaries.<br/>
Since it's linked to a static context to which the visible components are
attached and different contexts don't relate to each other, they must be
_shared_ to allow the use of meta types across boundaries.
Since it's linked already to a static context to which the elements are attached
and different contexts don't relate to each other, they must be _shared_ to
allow the use of meta types across boundaries.
Sharing a context is trivial though. First of all, the local one must be
acquired in the main space:
Fortunately, sharing a context is also trivial to do. First of all, the local
one is acquired in the main space:
```cpp
entt::meta_ctx ctx{};
auto handle = entt::locator<entt::meta_ctx>::handle();
```
Then, it must passed to the receiving space that will set it as its global
context, thus releasing the local one that remains available but is no longer
referred to by the runtime reflection system:
Then, it's passed to the receiving space that sets it as its default context,
thus discarding or storing aside the local one:
```cpp
entt::meta_ctx::bind(ctx);
entt::locator<entt::meta_ctx>::reset(handle);
```
From now on, both spaces will refer to the same context and on it will be
attached the new visible meta types, no matter where they are created.<br/>
A context can also be reset and then associated again locally as:
From now on, both spaces refer to the same context and on it are attached all
new meta types, no matter where they are created.<br/>
Note that resetting the main context doesn't also propagate changes across
boundaries. In other words, resetting a context results in the decoupling of the
two sides and therefore a divergence in the contents.
```cpp
entt::meta_ctx::bind{entt::meta_ctx{});
```
This is allowed because local and global contexts are separated. Therefore, it's
always possible to make the local context the current one again.
Before to release a context, all locally registered types should be reset to
avoid dangling references. Otherwise, if a type is accessed from another space
by name, there could be an attempt to address its parts that are no longer
available.
# Memory Management
## Memory Management
There is another subtle problem due to memory management that can lead to
headaches.<br/>

View File

@@ -3,8 +3,8 @@
`EnTT` is widely used in private and commercial applications. I cannot even
mention most of them because of some signatures I put on some documents time
ago. Fortunately, there are also people who took the time to implement open
source projects based on `EnTT` and did not hold back when it came to
documenting them.
source projects based on `EnTT` and didn't hold back when it came to documenting
them.
Below an incomplete list of games, applications and articles that can be used as
a reference. Where I put the word _apparently_ means that the use of `EnTT` is
@@ -17,10 +17,31 @@ I hope this list can grow much more in the future:
* [Minecraft](https://minecraft.net/en-us/attribution/) by
[Mojang](https://mojang.com/): of course, **that** Minecraft, see the
open source attributions page for more details.
* [Land of the Rair](https://github.com/LandOfTheRair/core2): the new backend
of [a retro-style MUD](https://rair.land/) for the new age.
* [Minecraft Earth](https://www.minecraft.net/en-us/about-earth) by
[Mojang](https://mojang.com/): an augmented reality game for mobile, that
lets users bring Minecraft into the real world.
* [Ember Sword](https://embersword.com/): a modern Free-to-Play MMORPG with a
player-driven economy, a classless combat system, and scarce, tradable
cosmetic collectibles.
* Apparently [Diablo II: Resurrected](https://diablo2.blizzard.com/) by
[Blizzard](https://www.blizzard.com/): monsters, heroes, items, spells, all
resurrected. Thanks unknown insider.
* [Apparently](https://www.youtube.com/watch?v=P8xvOA3ikrQ&t=1105s)
[Call of Duty: Vanguard](https://www.callofduty.com/vanguard) by
[Sledgehammer Games](https://www.sledgehammergames.com/): I can neither
confirm nor deny but there is a license I know in the credits.
* Apparently [D&D Dark Alliance](https://darkalliance.wizards.com) by
[Wizards of the Coast](https://company.wizards.com): your party, their
funeral.
* [TiltedOnline](https://github.com/tiltedphoques/TiltedOnline) by
[Tilted Phoques](https://github.com/tiltedphoques): Skyrim and Fallout 4 mod
to play online.
* [Antkeeper](https://github.com/antkeeper/antkeeper-source): an ant colony
simulation [game](https://antkeeper.com/).
* [Openblack](https://github.com/openblack/openblack): open source
reimplementation of the game _Black & White_ (2001).
* [Land of the Rair](https://github.com/LandOfTheRair/core2): the new backend
of [a retro-style MUD](https://rair.land/) for the new age.
* [Face Smash](https://play.google.com/store/apps/details?id=com.gamee.facesmash):
a game to play with your face.
* [EnTT Pacman](https://github.com/Kerndog73/EnTT-Pacman): an example of how
@@ -32,8 +53,8 @@ I hope this list can grow much more in the future:
* [The Machine](https://github.com/Kerndog73/The-Machine): a box pushing
puzzler with logic gates and other cool stuff.
[Check it out](https://indi-kernick.itch.io/the-machine-web-version).
* [EnttPong](https://github.com/reworks/EnttPong): an example of how to make
Pong with `EnTT`.
* [EnTTPong](https://github.com/DomRe/EnttPong): a basic game made to showcase
different parts of `EnTT` and C++17.
* [Randballs](https://github.com/gale93/randballs): simple `SFML` and `EnTT`
playground.
* [EnTT Tower Defense](https://github.com/Daivuk/tddod): a data oriented tower
@@ -52,22 +73,64 @@ I hope this list can grow much more in the future:
football game.
* [DungeonSlayer](https://github.com/alohaeee/DungeonSlayer): 2D game made
from scratch in C++.
* [3DGame](https://github.com/kwarkGorny/3DGame): 2.5D top-down space shooter.
* [Pulcher](https://github.com/AODQ/pulcher): 2D cross-platform game inspired
by Quake.
* [Destroid](https://github.com/tyrannicaltoucan/destroid): _one-bazillionth_
arcade game about shooting dirty rocks in space, inspired by Asteroids.
* [Wanderer](https://github.com/albin-johansson/wanderer): a 2D exploration
based indie game.
* [Spelunky® Classic remake](https://github.com/dbeef/spelunky-psp): a truly
multiplatform experience with a rewrite from scratch.
* [CubbyTower](https://github.com/utilForever/CubbyTower): a simple tower
defense game using C++ with Entity Component System (ECS).
* [Runeterra](https://github.com/utilForever/Runeterra): Legends of Runeterra
simulator using C++ with some reinforcement learning.
* [Black Sun](https://store.steampowered.com/app/1670930/Black_Sun/): fly your
space ship through a large 2D open world.
* [PokeMaster](https://github.com/utilForever/PokeMaster): Pokemon Battle
simulator using C++ with some reinforcement learning.
* [HomeHearth](https://youtu.be/GrEWl8npL9Y): choose your hero, protect the
town, before it's too late.
* [City Builder Game](https://github.com/PhiGei2000/CityBuilderGame): a simple
city-building game using C++ and OpenGL.
* [BattleSub](https://github.com/bfeldpw/battlesub): two player 2D submarine
game with some fluid dynamics.
* [Crimson Rush](https://github.com/WilKam01/LuaCGame): a dungeon-crawler and
rougelike inspired game about exploring and surviving as long as possible.
* [Space Fight](https://github.com/cholushkin/SpaceFight): one screen
multi-player arcade shooter game prototype.
* [Confetti Party](https://github.com/hexerei/entt-confetti): C++ sample
application as a starting point using `EnTT` and `SDL2`.
* Engines and the like:
* [Aether Engine](https://hadean.com/spatial-simulation/)
[v1.1+](https://docs.hadean.com/v1.1/Licenses/) by
[Hadean](https://hadean.com/): a library designed for spatially partitioning
agent-based simulations.
* [Fling Engine](https://github.com/flingengine/FlingEngine): a Vulkan game
engine with a focus on data oriented design.
* [NovusCore](https://github.com/novuscore/NovusCore): a modern take on World
of Warcraft emulation.
* [Chrysalis](https://github.com/ivanhawkes/Chrysalis): action RPG SDK for
CRYENGINE games.
* [LM-Engine](https://github.com/Lawrencemm/LM-Engine): the Vim of game
engines.
* [Edyn](https://github.com/xissburg/edyn): a real-time physics engine
organized as an ECS.
* [MushMachine](https://github.com/MadeOfJelly/MushMachine): engine...
vrooooommm.
* [Antara Gaming SDK](https://github.com/KomodoPlatform/antara-gaming-sdk):
the Komodo Gaming Software Development Kit.
* [XVP](https://ravingbots.com/xvp-expansive-vehicle-physics-for-unreal-engine/):
[_eXpansive Vehicle Physics_](https://github.com/raving-bots/xvp/wiki/Plugin-integration-guide)
plugin for Unreal Engine.
* [Apparently](https://teamwisp.github.io/credits/)
[Wisp](https://teamwisp.github.io/product/) by
[Team Wisp](https://teamwisp.github.io/): an advanced real-time ray tracing
renderer built for the demands of video game artists.
* [starlight](https://github.com/DomRe/starlight): game programming framework
using `Allegro`, `Lua` and modern C++.
* [Apparently](https://github.com/JosiahWI/qub3d-libdeps)
[Qub3d](https://qub3d.org/): because blocks should be open source.
* [shiva](https://github.com/Milerius/shiva): modern C++ engine with
modularity.
* [NovusCore](https://github.com/novuscore/NovusCore): a modern take on World
of Warcraft emulation.
* [ImGui/EnTT editor](https://github.com/Green-Sky/imgui_entt_entity_editor):
a drop-in, single-file entity editor for `EnTT` that uses `ImGui` as
graphical backend (with
@@ -76,11 +139,60 @@ I hope this list can grow much more in the future:
developed for educational purposes.
* [Lumos](https://github.com/jmorton06/Lumos): game engine written in C++
using OpenGL and Vulkan.
* [Silvanus](https://github.com/hobbyistmaker/silvanus): Silvanus Fusion 360
Box Generator.
* [Lina Engine](https://github.com/inanevin/LinaEngine): an open-source,
modular, tiny and fast C++ game engine, aimed to develop 3D desktop games.
* [Spike](https://github.com/FahimFuad/Spike): a powerful game engine which
can run on a toaster.
* [Helena Framework](https://github.com/NIKEA-SOFT/HelenaFramework): a modern
framework in C++17 for backend development.
* [Unity/EnTT](https://github.com/TongTungGiang/unity-entt): tech demo of a
native simulation layer using `EnTT` and `Unity` as a rendering engine.
* [OverEngine](https://github.com/OverShifted/OverEngine): an over-engineered
game engine.
* [Electro](https://github.com/Electro-Technologies/Electro): high performance
3D game engine with a high emphasis on rendering.
* [Kawaii](https://github.com/Mathieu-Lala/Kawaii_Engine): a modern data
oriented game engine.
* [Becketron](https://github.com/Doctor-Foxling/Becketron): a game engine
written mostly in C++.
* [Spatial Engine](https://github.com/luizgabriel/Spatial.Engine): a
cross-platform engine created on top of google's filament rendering engine.
* [Kaguya](https://github.com/KaiH0717/Kaguya): D3D12 Rendering Engine.
* [OpenAWE](https://github.com/OpenAWE-Project/OpenAWE): open implementation
of the Alan Wake Engine.
* [Nazara Engine](https://github.com/DigitalPulseSoftware/NazaraEngine): fast,
cross-platform, object-oriented API to help in daily developer life.
* [Billy Engine](https://github.com/billy4479/BillyEngine): some kind of a 2D
engine based on `SDL2` and `EnTT`.
* [Ducktape](https://github.com/DucktapeEngine/Ducktape): an open source C++
2D & 3D game engine that focuses on being fast and powerful.
* Articles and blog posts:
* Articles, videos and blog posts:
* [Some posts](https://skypjack.github.io/tags/#entt) on my personal
[blog](https://skypjack.github.io/) are about `EnTT`, for those who want to
know **more** on this project.
* [Game Engine series](https://www.youtube.com/c/TheChernoProject/videos) by
[The Cherno](https://github.com/TheCherno) (not only about `EnTT` but also
on the use of an ECS in general):
- [Intro to EnTT](https://www.youtube.com/watch?v=D4hz0wEB978).
- [Entities and Components](https://www.youtube.com/watch?v=-B1iu4QJTUc).
- [The ENTITY Class](https://www.youtube.com/watch?v=GfSzeAcsBb0).
- [Camera Systems](https://www.youtube.com/watch?v=ubZn7BlrnTU).
- [Scene Camera](https://www.youtube.com/watch?v=UKVFRRufKzo).
- [Native Scripting](https://www.youtube.com/watch?v=iIUhg88MK5M).
- [Native Scripting (now with virtual functions!)](https://www.youtube.com/watch?v=1cHEcrIn8IQ).
- [Scene Hierarchy Panel](https://www.youtube.com/watch?v=wziDnE8guvI).
- [Properties Panel](https://www.youtube.com/watch?v=NBpB0qscF3E).
- [Camera Component UI](https://www.youtube.com/watch?v=RIMt_6agUiU).
- [Drawing Component UI](https://www.youtube.com/watch?v=u3yq8s3KuSE).
- [Transform Component UI](https://www.youtube.com/watch?v=8JqcXYbzPJc).
- [Adding/Removing Entities and Components UI](https://www.youtube.com/watch?v=PsyGmsIgp9M).
- [Saving and Loading Scenes](https://www.youtube.com/watch?v=IEiOP7Y-Mbc).
- ... And so on.
[Check out](https://www.youtube.com/channel/UCQ-W1KE9EYfdxhL6S4twUNw) the
_Game Engine Series_ by The Cherno for more videos.
* [Space Battle: Huge edition](http://victor.madtriangles.com/code%20experiment/2018/06/11/post-ecs-battle-huge.html):
huge space battle built entirely from scratch.
* [Space Battle](https://github.com/vblanco20-1/ECS_SpaceBattle): huge space
@@ -91,25 +203,52 @@ I hope this list can grow much more in the future:
giant space battle.
* [Conan Adventures (SFML and EnTT in C++)](https://leinnan.github.io/blog/conan-adventuressfml-and-entt-in-c.html):
create projects in modern C++ using `SFML`, `EnTT`, `Conan` and `CMake`.
* [Adding EnTT ECS to Chrysalis](https://www.tauradius.com/post/adding-an-ecs-to-chrysalis/):
a blog entry (and its
[follow-up](https://www.tauradius.com/post/chrysalis-update-2020-08-02/))
about the integration of `EnTT` into `Chrysalis`, an action RPG SDK for
CRYENGINE games.
* [Creating Minecraft in One Week with C++ and Vulkan](https://vazgriz.com/189/creating-minecraft-in-one-week-with-c-and-vulkan/):
a crack at recreating Minecraft in one week using a custom C++ engine and
Vulkan ([code included](https://github.com/vazgriz/VoxelGame)).
* [Ability Creator](https://www.erichildebrand.net/blog/ability-creator-project-retrospect):
project retrospect by [Eric Hildebrand](https://www.erichildebrand.net/).
* [EnTT Entity Component System Gaming Library](https://gamefromscratch.com/entt-entity-component-system-gaming-library/):
`EnTT` on GameFromScratch.com.
* [Custom C++ server for UE5](https://youtu.be/fbXZVNCOvjM) optimized for
MMO(RPG)s and its [follow-up](https://youtu.be/yGlZeopx2hU) episode about
player bots and full external ECS: a series definitely worth looking at.
* Any Other Business:
* The [ArcGIS Runtime SDKs](https://developers.arcgis.com/arcgis-runtime/)
by [Esri](https://www.esri.com/): they use `EnTT` for the internal ECS and
the cross platform C++ rendering engine. The SDKs are utilized by a lot of
* [ArcGIS Runtime SDKs](https://developers.arcgis.com/arcgis-runtime/) by
[Esri](https://www.esri.com/): they use `EnTT` for the internal ECS and the
cross platform C++ rendering engine. The SDKs are utilized by a lot of
enterprise custom apps, as well as by Esri for its own public applications
such as
[Explorer](https://play.google.com/store/apps/details?id=com.esri.explorer),
[Collector](https://play.google.com/store/apps/details?id=com.esri.arcgis.collector)
and
[Navigator](https://play.google.com/store/apps/details?id=com.esri.navigator).
* [Sequentity](https://github.com/alanjfs/sequentity): A MIDI-like
sequencer/tracker for C++ and `ImGui` (with `Magnum` and `EnTT`).
* [FASTSUITE Edition 2](https://www.fastsuite.com/en_EN/fastsuite/fastsuite-edition-2.html)
by [Cenit](http://www.cenit.com/en_EN/about-us/overview.html): they use
`EnTT` to drive their simulation, that is, the communication between robot
controller emulator and renderer.
* [Ragdoll](https://ragdolldynamics.com/): real-time physics for Autodesk Maya
2020.
* [Project Lagrange](https://github.com/adobe/lagrange): a robust geometry
processing library by [Adobe](https://github.com/adobe).
* [AtomicDEX](https://github.com/KomodoPlatform/atomicDEX-Desktop): a secure
wallet and non-custodial decentralized exchange rolled into one application.
* [Apparently](https://www.linkedin.com/in/skypjack/)
[NIO](https://www.nio.io/): there was a collaboration to make some changes
to `EnTT`, at the time used for internal projects.
* [Apparently](https://www.linkedin.com/jobs/view/architekt-c%2B%2B-at-tieto-1219512333/)
[Tieto](https://www.tieto.com/): they published a job post where `EnTT` was
listed on their software stack.
* [Sequentity](https://github.com/alanjfs/sequentity): A MIDI-like
sequencer/tracker for C++ and `ImGui` (with `Magnum` and `EnTT`).
* [EnTT meets Sol2](https://github.com/skaarj1989/entt-meets-sol2): freely
available examples of how to combine `EnTT` and `Sol2`.
* [Godot meets EnTT](https://github.com/portaloffreedom/godot_entt_example/):
a simple example on how to use `EnTT` within
[`Godot`](https://godotengine.org/).

View File

@@ -7,69 +7,82 @@
* [Introduction](#introduction)
* [Service locator](#service-locator)
* [Opaque handles](#opaque-handles)
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction
Usually service locators are tightly bound to the services they expose and it's
hard to define a general purpose solution. This template based implementation
tries to fill the gap and to get rid of the burden of defining a different
specific locator for each application.<br/>
This class is tiny, partially unsafe and thus risky to use. Moreover it doesn't
fit probably most of the scenarios in which a service locator is required. Look
at it as a small tool that can sometimes be useful if users know how to handle
it.
Usually, service locators are tightly bound to the services they expose and it's
hard to define a general purpose solution.<br/>
This tiny class tries to fill the gap and gets rid of the burden of defining a
different specific locator for each application.
# Service locator
The API is straightforward. The basic idea is that services are implemented by
means of interfaces and rely on polymorphism.<br/>
The locator is instantiated with the base type of the service if any and a
concrete implementation is provided along with all the parameters required to
initialize it. As an example:
The service locator API tries to mimic that of `std::optional` and adds some
extra functionalities on top of it such as allocator support.<br/>
There are a couple of functions to set up a service, namely `emplace` and
`allocate_emplace`:
```cpp
// the service has no base type, a locator is used to treat it as a kind of singleton
entt::service_locator<my_service>::set(params...);
// sets up an opaque service
entt::service_locator<audio_interface>::set<audio_implementation>(params...);
// resets (destroys) the service
entt::service_locator<audio_interface>::reset();
entt::locator<interface>::emplace<service>(argument);
entt::locator<interface>::allocate_emplace<service>(allocator, argument);
```
The locator can also be queried to know if an active service is currently set
and to retrieve it if necessary (either as a pointer or as a reference):
The difference is that the latter expects an allocator as the first argument and
uses it to allocate the service itself.<br/>
Once a service is set up, it's retrieved using the `value` function:
```cpp
// no service currently set
auto empty = entt::service_locator<audio_interface>::empty();
// gets a (possibly empty) shared pointer to the service ...
std::shared_ptr<audio_interface> ptr = entt::service_locator<audio_interface>::get();
// ... or a reference, but it's undefined behaviour if the service isn't set yet
audio_interface &ref = entt::service_locator<audio_interface>::ref();
interface &service = entt::locator<interface>::value();
```
A common use is to wrap the different locators in a container class, creating
aliases for the various services:
Since the service may not be set (and therefore this function may result in an
undefined behavior), the `has_value` and `value_or` functions are also available
to test a service locator and to get a fallback service in case there is none:
```cpp
struct locator {
using camera = entt::service_locator<camera_interface>;
using audio = entt::service_locator<audio_interface>;
// ...
};
// ...
void init() {
locator::camera::set<camera_null>();
locator::audio::set<audio_implementation>(params...);
if(entt::locator<interface>::has_value()) {
// ...
}
interface &service = entt::locator<interface>::value_or<fallback_impl>(argument);
```
All arguments are used only if necessary, that is, if a service doesn't already
exist and therefore the fallback service is constructed and returned. In all
other cases, they are discarded.<br/>
Finally, to reset a service, use the `reset` function.
## Opaque handles
Sometimes it's useful to _transfer_ a copy of a service to another locator. For
example, when working across boundaries it's common to _share_ a service with a
dynamically loaded module.<br/>
Options aren't much in this case. Among these is the possibility of _exporting_
services and assigning them to a different locator.
This is what the `handle` and `reset` functions are meant for.<br/>
The former returns an opaque object useful for _exporting_ (or rather, obtaining
a reference to) a service. The latter also accepts an optional argument to a
handle which then allows users to reset a service by initializing it with an
opaque handle:
```cpp
auto handle = entt::locator<interface>::handle();
entt::locator<interface>::reset(handle);
```
It's worth noting that it's possible to get handles for uninitialized services
and use them with other locators. Of course, all a user will get is to have an
uninitialized service elsewhere as well.
Note that exporting a service allows users to _share_ the object currently set
in a locator. Replacing it won't replace the element even where a service has
been configured with a handle to the previous item.<br/>
In other words, if an audio service is replaced with a null object to silence an
application and the original service was shared, this operation won't propagate
to the other locators. Therefore, a module that share the ownership of the
original audio service is still able to emit sounds.

File diff suppressed because it is too large Load Diff

359
docs/md/poly.md Normal file
View File

@@ -0,0 +1,359 @@
# Crash Course: poly
<!--
@cond TURN_OFF_DOXYGEN
-->
# Table of Contents
* [Introduction](#introduction)
* [Other libraries](#other-libraries)
* [Concept and implementation](#concept-and-implementation)
* [Deduced interface](#deduced-interface)
* [Defined interface](#defined-interface)
* [Fulfill a concept](#fulfill-a-concept)
* [Inheritance](#inheritance)
* [Static polymorphism in the wild](#static-polymorphism-in-the-wild)
* [Storage size and alignment requirement](#storage-size-and-alignment-requirement)
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction
Static polymorphism is a very powerful tool in C++, albeit sometimes cumbersome
to obtain.<br/>
This module aims to make it simple and easy to use.
The library allows to define _concepts_ as interfaces to fulfill with concrete
classes without having to inherit from a common base.<br/>
This is, among others, one of the advantages of static polymorphism in general
and of a generic wrapper like that offered by the `poly` class template in
particular.<br/>
What users get is an object that can be passed around as such and not through a
reference or a pointer, as happens when it comes to working with dynamic
polymorphism.
Since the `poly` class template makes use of `entt::any` internally, it also
supports most of its feature. Among the most important, the possibility to
create aliases to existing and thus unmanaged objects. This allows users to
exploit the static polymorphism while maintaining ownership of objects.<br/>
Likewise, the `poly` class template also benefits from the small buffer
optimization offered by the `entt::any` class and therefore minimizes the number
of allocations, avoiding them altogether where possible.
## Other libraries
There are some very interesting libraries regarding static polymorphism.<br/>
Among all, the two that I prefer are:
* [`dyno`](https://github.com/ldionne/dyno): runtime polymorphism done right.
* [`Poly`](https://github.com/facebook/folly/blob/master/folly/docs/Poly.md):
a class template that makes it easy to define a type-erasing polymorphic
object wrapper.
The former is admittedly an experimental library, with many interesting ideas.
I've some doubts about the usefulness of some feature in real world projects,
but perhaps my lack of experience comes into play here. In my opinion, its only
flaw is the API which I find slightly more cumbersome than other solutions.<br/>
The latter was undoubtedly a source of inspiration for this module, although I
opted for different choices in the implementation of both the final API and some
feature.
Either way, the authors are gurus of the C++ community, people I only have to
learn from.
# Concept and implementation
The first thing to do to create a _type-erasing polymorphic object wrapper_ (to
use the terminology introduced by Eric Niebler) is to define a _concept_ that
types will have to adhere to.<br/>
For this purpose, the library offers a single class that supports both deduced
and fully defined interfaces. Although having interfaces deduced automatically
is convenient and allows users to write less code in most cases, this has some
limitations and it's therefore useful to be able to get around the deduction by
providing a custom definition for the static virtual table.
Once the interface is defined, it will be sufficient to provide a generic
implementation to fulfill the concept.<br/>
Also in this case, the library allows customizations based on types or families
of types, so as to be able to go beyond the generic case where necessary.
## Deduced interface
This is how a concept with a deduced interface is introduced:
```cpp
struct Drawable: entt::type_list<> {
template<typename Base>
struct type: Base {
void draw() { this->template invoke<0>(*this); }
};
// ...
};
```
It's recognizable by the fact that it inherits from an empty type list.<br/>
Functions can also be const, accept any number of parameters and return a type
other than `void`:
```cpp
struct Drawable: entt::type_list<> {
template<typename Base>
struct type: Base {
bool draw(int pt) const { return this->template invoke<0>(*this, pt); }
};
// ...
};
```
In this case, all parameters must be passed to `invoke` after the reference to
`this` and the return value is whatever the internal call returns.<br/>
As for `invoke`, this is a name that is injected into the _concept_ through
`Base`, from which one must necessarily inherit. Since it's also a dependent
name, the `this-> template` form is unfortunately necessary due to the rules of
the language. However, there exists also an alternative that goes through an
external call:
```cpp
struct Drawable: entt::type_list<> {
template<typename Base>
struct type: Base {
void draw() const { entt::poly_call<0>(*this); }
};
// ...
};
```
Once the _concept_ is defined, users must provide a generic implementation of it
in order to tell the system how any type can satisfy its requirements. This is
done via an alias template within the concept itself.<br/>
The index passed as a template parameter to either `invoke` or `poly_call`
refers to how this alias is defined.
## Defined interface
A fully defined concept is no different to one for which the interface is
deduced, with the only difference that the list of types is not empty this time:
```cpp
struct Drawable: entt::type_list<void()> {
template<typename Base>
struct type: Base {
void draw() { entt::poly_call<0>(*this); }
};
// ...
};
```
Again, parameters and return values other than `void` are allowed. Also, the
function type must be const when the method to bind to it is const:
```cpp
struct Drawable: entt::type_list<bool(int) const> {
template<typename Base>
struct type: Base {
bool draw(int pt) const { return entt::poly_call<0>(*this, pt); }
};
// ...
};
```
Why should a user fully define a concept if the function types are the same as
the deduced ones?<br>
Because, in fact, this is exactly the limitation that can be worked around by
manually defining the static virtual table.
When things are deduced, there is an implicit constraint.<br/>
If the concept exposes a member function called `draw` with function type
`void()`, a concept can be satisfied:
* Either by a class that exposes a member function with the same name and the
same signature.
* Or through a lambda that makes use of existing member functions from the
interface itself.
In other words, it's not possible to make use of functions not belonging to the
interface, even if they are present in the types that fulfill the concept.<br/>
Similarly, it's not possible to deduce a function in the static virtual table
with a function type different from that of the associated member function in
the interface itself.
Explicitly defining a static virtual table suppresses the deduction step and
allows maximum flexibility when providing the implementation for a concept.
## Fulfill a concept
The `impl` alias template of a concept is used to define how it's fulfilled:
```cpp
struct Drawable: entt::type_list<> {
// ...
template<typename Type>
using impl = entt::value_list<&Type::draw>;
};
```
In this case, it's stated that the `draw` method of a generic type will be
enough to satisfy the requirements of the `Drawable` concept.<br/>
Both member functions and free functions are supported to fulfill concepts:
```cpp
template<typename Type>
void print(Type &self) { self.print(); }
struct Drawable: entt::type_list<void()> {
// ...
template<typename Type>
using impl = entt::value_list<&print<Type>>;
};
```
Likewise, as long as the parameter types and return type support conversions to
and from those of the function type referenced in the static virtual table, the
actual implementation may differ in its function type since it's erased
internally.<br/>
Moreover, the `self` parameter isn't strictly required by the system and can be
left out for free functions if not required.
Refer to the inline documentation for more details.
# Inheritance
_Concept inheritance_ is straightforward due to how poly looks like in `EnTT`.
Therefore, it's quite easy to build hierarchies of concepts if necessary.<br/>
The only constraint is that all concepts in a hierarchy must belong to the same
_family_, that is, they must be either all deduced or all defined.
For a deduced concept, inheritance is achieved in a few steps:
```cpp
struct DrawableAndErasable: entt::type_list<> {
template<typename Base>
struct type: typename Drawable::template type<Base> {
static constexpr auto base = std::tuple_size_v<typename entt::poly_vtable<Drawable>::type>;
void erase() { entt::poly_call<base + 0>(*this); }
};
template<typename Type>
using impl = entt::value_list_cat_t<
typename Drawable::impl<Type>,
entt::value_list<&Type::erase>
>;
};
```
The static virtual table is empty and must remain so.<br/>
On the other hand, `type` no longer inherits from `Base` and instead forwards
its template parameter to the type exposed by the _base class_. Internally, the
size of the static virtual table of the base class is used as an offset for the
local indexes.<br/>
Finally, by means of the `value_list_cat_t` utility, the implementation consists
in appending the new functions to the previous list.
As for a defined concept instead, also the list of types must be extended, in a
similar way to what is shown for the implementation of the above concept.<br/>
To do this, it's useful to declare a function that allows to convert a _concept_
into its underlying `type_list` object:
```cpp
template<typename... Type>
entt::type_list<Type...> as_type_list(const entt::type_list<Type...> &);
```
The definition isn't strictly required, since the function will only be used
through a `decltype` as it follows:
```cpp
struct DrawableAndErasable: entt::type_list_cat_t<
decltype(as_type_list(std::declval<Drawable>())),
entt::type_list<void()>
> {
// ...
};
```
Similar to above, `type_list_cat_t` is used to concatenate the underlying static
virtual table with the new function types.<br/>
Everything else is the same as already shown instead.
# Static polymorphism in the wild
Once the _concept_ and implementation have been introduced, it will be possible
to use the `poly` class template to contain instances that meet the
requirements:
```cpp
using drawable = entt::poly<Drawable>;
struct circle {
void draw() { /* ... */ }
};
struct square {
void draw() { /* ... */ }
};
// ...
drawable instance{circle{}};
instance->draw();
instance = square{};
instance->draw();
```
The `poly` class template offers a wide range of constructors, from the default
one (which will return an uninitialized `poly` object) to the copy and move
constructors, as well as the ability to create objects in-place.<br/>
Among others, there is also a constructor that allows users to wrap unmanaged
objects in a `poly` instance (either const or non-const ones):
```cpp
circle shape;
drawable instance{std::in_place_type<circle &>, shape};
```
Similarly, it's possible to create non-owning copies of `poly` from an existing
object:
```cpp
drawable other = instance.as_ref();
```
In both cases, although the interface of the `poly` object doesn't change, it
won't construct any element or take care of destroying the referenced objects.
Note also how the underlying concept is accessed via a call to `operator->` and
not directly as `instance.draw()`.<br/>
This allows users to decouple the API of the wrapper from that of the concept.
Therefore, where `instance.data()` will invoke the `data` member function of the
poly object, `instance->data()` will map directly to the functionality exposed
by the underlying concept.
# Storage size and alignment requirement
Under the hood, the `poly` class template makes use of `entt::any`. Therefore,
it can take advantage of the possibility of defining at compile-time the size of
the storage suitable for the small buffer optimization as well as the alignment
requirements:
```cpp
entt::basic_poly<Drawable, sizeof(double[4]), alignof(double[4])>
```
The default size is `sizeof(double[2])`, which seems like a good compromise
between a buffer that is too large and one unable to hold anything larger than
an integer. The alignment requirement is optional instead and by default such
that it's the most stringent (the largest) for any object whose size is at most
equal to the one provided.<br/>
It's worth noting that providing a size of 0 (which is an accepted value in all
respects) will force the system to dynamically allocate the contained objects in
all cases.

View File

@@ -28,9 +28,9 @@ A typical process must inherit from the `process` class template that stays true
to the CRTP idiom. Moreover, derived classes must specify what's the intended
type for elapsed times.
A process should expose publicly the following member functions whether
required (note that it isn't required to define a function unless the derived
class wants to _override_ the default behavior):
A process should expose publicly the following member functions whether needed
(note that it isn't required to define a function unless the derived class wants
to _override_ the default behavior):
* `void update(Delta, void *);`
@@ -98,7 +98,7 @@ private:
Lambdas and functors can't be used directly with a scheduler for they are not
properly defined processes with managed life cycles.<br/>
This class helps in filling the gap and turning lambdas and functors into
full featured processes usable by a scheduler.
full-featured processes usable by a scheduler.
The function call operator has a signature similar to the one of the `update`
function of a process but for the fact that it receives two extra arguments to

75
docs/md/reference.md Normal file
View File

@@ -0,0 +1,75 @@
# Similar projects
There are many projects similar to `EnTT`, both open source and not.<br/>
Some even borrowed some ideas from this library and expressed them in different
languages.<br/>
Others developed different architectures from scratch and therefore offer
alternative solutions with their pros and cons.
Below an incomplete list of those that I've come across so far.<br/>
If some terms or designs aren't clear, I recommend referring to the
[_ECS Back and Forth_](https://skypjack.github.io/tags/#ecs) series for all the
details.
I hope this list can grow much more in the future:
* C:
* [destral_ecs](https://github.com/roig/destral_ecs): a single-file ECS based
on sparse sets.
* [Diana](https://github.com/discoloda/Diana): an ECS that uses sparse sets to
keep track of entities in systems.
* [Flecs](https://github.com/SanderMertens/flecs): a multithreaded archetype
ECS based on semi-contiguous arrays rather than chunks.
* [lent](https://github.com/nem0/lent): the Donald Trump of the ECS libraries.
* C++:
* [decs](https://github.com/vblanco20-1/decs): a chunk based archetype ECS.
* [ecst](https://github.com/SuperV1234/ecst): a multithreaded compile-time
ECS that uses sparse sets to keep track of entities in systems.
* [EntityX](https://github.com/alecthomas/entityx): a bitset based ECS that
uses a single large matrix of components indexed with entities.
* [Gaia-ECS](https://github.com/richardbiely/gaia-ecs): a chunk based
archetype ECS.
* [Polypropylene](https://github.com/pmbittner/Polypropylene): a hybrid
solution between an ECS and dynamic mixins.
* C#
* [Entitas](https://github.com/sschmid/Entitas-CSharp): the ECS framework for
C# and Unity, where _reactive systems_ were invented.
* [LeoECS](https://github.com/Leopotam/ecs): simple lightweight C# Entity
Component System framework.
* [Svelto.ECS](https://github.com/sebas77/Svelto.ECS): a very interesting
platform agnostic and table based ECS framework.
* Go:
* [gecs](https://github.com/tutumagi/gecs): a sparse sets based ECS inspired
by `EnTT`.
* Javascript:
* [\@javelin/ecs](https://github.com/3mcd/javelin/tree/master/packages/ecs):
an archetype ECS in TypeScript.
* [ecsy](https://github.com/MozillaReality/ecsy): I haven't had the time to
investigate the underlying design of `ecsy` but it looks cool anyway.
* Perl:
* [Game::Entities](https://gitlab.com/jjatria/perl-game-entities): a simple
entity registry for ECS designs inspired by `EnTT`.
* Raku:
* [Game::Entities](https://gitlab.com/jjatria/raku-game-entities): a simple
entity registry for ECS designs inspired by `EnTT`.
* Rust:
* [Legion](https://github.com/TomGillen/legion): a chunk based archetype ECS.
* [Shipyard](https://github.com/leudz/shipyard): it borrows some ideas from
`EnTT` and offers a sparse sets based ECS with grouping functionalities.
* [Sparsey](https://github.com/LechintanTudor/sparsey): sparse set based ECS
written in Rust.
* [Specs](https://github.com/amethyst/specs): a parallel ECS based mainly on
hierarchical bitsets that allows different types of storage as needed.
* Zig
* [zig-ecs](https://github.com/prime31/zig-ecs): a _zig-ification_ of `EnTT`.
If you know of other resources out there that can be of interest for the reader,
feel free to open an issue or a PR and I'll be glad to add them to this page.

View File

@@ -7,231 +7,185 @@
* [Introduction](#introduction)
* [The resource, the loader and the cache](#the-resource-the-loader-and-the-cache)
* [Resource handle](#resource-handle)
* [Loaders](#loader)
* [The cache class](#the-cache)
<!--
@endcond TURN_OFF_DOXYGEN
-->
# Introduction
Resource management is usually one of the most critical part of a software like
a game. Solutions are often tuned to the particular application. There exist
several approaches and all of them are perfectly fine as long as they fit the
Resource management is usually one of the most critical parts of a game.
Solutions are often tuned to the particular application. There exist several
approaches and all of them are perfectly fine as long as they fit the
requirements of the piece of software in which they are used.<br/>
Examples are loading everything on start, loading on request, predictive
loading, and so on.
`EnTT` doesn't pretend to offer a _one-fits-all_ solution for the different
cases. Instead, it offers a minimal and perhaps trivial cache that can be useful
most of the time during prototyping and sometimes even in a production
environment.<br/>
For those interested in the subject, the plan is to improve it considerably over
time in terms of performance, memory usage and functionalities. Hoping to make
it, of course, one step at a time.
cases.<br/>
Instead, the library comes with a minimal, general purpose resource cache that
might be useful in many cases.
# The resource, the loader and the cache
There are three main actors in the model: the resource, the loader and the
cache.
The _resource_ is whatever users want it to be. An image, a video, an audio,
whatever. There are no limits.<br/>
As a minimal example:
Resource, loader and cache are the three main actors for the purpose.<br/>
The _resource_ is an image, an audio, a video or any other type:
```cpp
struct my_resource { const int value; };
```
A _loader_ is a class the aim of which is to load a specific resource. It has to
inherit directly from the dedicated base class as in the following example:
The _loader_ is a callable type the aim of which is to load a specific resource:
```cpp
struct my_loader final: entt::loader<my_loader, my_resource> {
// ...
};
```
struct my_loader final {
using result_type = std::shared_ptr<my_resource>;
Where `my_resource` is the type of resources it creates.<br/>
A resource loader must also expose a public const member function named `load`
that accepts a variable number of arguments and returns a shared pointer to a
resource.<br/>
As an example:
```cpp
struct my_loader: entt::loader<my_loader, my_resource> {
std::shared_ptr<my_resource> load(int value) const {
result_type operator()(int value) const {
// ...
return std::shared_ptr<my_resource>(new my_resource{ value });
return std::make_shared<my_resource>(value);
}
};
```
In general, resource loaders should not have a state or retain data of any type.
They should let the cache manage their resources instead.<br/>
As a side note, base class and CRTP idiom aren't strictly required with the
current implementation. One could argue that a cache can easily work with
loaders of any type. However, future changes won't be breaking ones by forcing
the use of a base class today and that's why the model is already in its place.
Its function operator can accept any arguments and should return a value of the
declared result type (`std::shared_ptr<my_resource>` in the example).<br/>
A loader can also overload its function call operator to make it possible to
construct the same or another resource from different lists of arguments.
Finally, a cache is a specialization of a class template tailored to a specific
resource:
resource and (optionally) a loader:
```cpp
using my_cache = entt::cache<my_resource>;
using my_cache = entt::resource_cache<my_resource, my_loader>;
// ...
my_cache cache{};
```
The idea is to create different caches for different types of resources and to
manage each one independently in the most appropriate way.<br/>
The class is designed to create different caches for different resource types
and to manage each one independently in the most appropriate way.<br/>
As a (very) trivial example, audio tracks can survive in most of the scenes of
an application while meshes can be associated with a single scene and then
discarded when users leave it.
an application while meshes can be associated with a single scene only, then
discarded when a player leaves it.
A cache offers a set of basic functionalities to query its internal state and to
_organize_ it:
## Resource handle
Resources aren't returned directly to the caller. Instead, they are wrapped in a
_resource handle_, an instance of the `entt::resource` class template.<br/>
For those who know the _flyweight design pattern_ already, that's exactly what
it is. To all others, this is the time to brush up on some notions instead.
A shared pointer could have been used as a resource handle. In fact, the default
implementation mostly maps the interface of its standard counterpart and only
adds a few things on top of it.<br/>
However, the handle in `EnTT` is designed as a standalone class template. This
is due to the fact that specializing a class in the standard library is often
undefined behavior while having the ability to specialize the handle for one,
more or all resource types could help over time.
## Loaders
A loader is responsible for _loading_ resources (quite obviously).<br/>
By default, it's just a callable object that forwards its arguments to the
resource itself. That is, a _passthrough type_. All the work is demanded to the
constructor(s) of the resource itself.<br/>
Loaders also are fully customizable as expected.
A custom loader is a class with at least one function call operator and a member
type named `result_type`.<br/>
The loader isn't required to return a resource handle. As long as `return_type`
is suitable for constructing a handle, that's fine.
When using the default handle, it expects a resource type which is convertible
to or suitable for constructing an `std::shared_ptr<Type>` (where `Type` is the
actual resource type).<br/>
In other terms, the loader should return shared pointers to the given resource
type. However, this isn't mandatory. Users can easily get around this constraint
by specializing both the handle and the loader.
A cache forwards all its arguments to the loader if required. This means that
loaders can also support tag dispatching to offer different loading policies:
```cpp
// gets the number of resources managed by a cache
const auto size = cache.size();
struct my_loader {
using result_type = std::shared_ptr<my_resource>;
// checks if a cache contains at least a valid resource
const auto empty = cache.empty();
struct from_disk_tag{};
struct from_network_tag{};
// clears a cache and discards its content
cache.clear();
template<typename Args>
result_type operator()(from_disk_tag, Args&&... args) {
// ...
return std::make_shared<my_resource>(std::forward<Args>(args)...);
}
template<typename Args>
result_type operator()(from_network_tag, Args&&... args) {
// ...
return std::make_shared<my_resource>(std::forward<Args>(args)...);
}
}
```
Besides these member functions, a cache contains what is needed to load, use and
discard resources of the given type.<br/>
Before to explore this part of the interface, it makes sense to mention how
resources are identified. The type of the identifiers to use is defined as:
This makes the whole loading logic quite flexible and easy to extend over time.
## The cache class
The cache is the class that is asked to _connect the dots_.<br/>
It loads the resources, stores them aside and returns handles as needed:
```cpp
entt::cache<resource>::id_type
entt::resource_cache<my_resource, my_loader> cache{};
```
Where `id_type` is an alias for `entt::hashed_string::hash_type`. Therefore,
resource identifiers are created explicitly as in the following example:
Under the hood, a cache is nothing more than a map where the key value has type
`entt::id_type` while the mapped value is whatever type its loader returns.<br/>
For this reason, it offers most of the functionalities a user would expect from
a map, such as `empty` or `size` and so on. Similarly, it's an iterable type
that also supports indexing by resource id:
```cpp
constexpr auto identifier = entt::cache<resource>::id_type{"my/resource/identifier"_hs};
// this is equivalent to the following
constexpr auto hs = entt::hashed_string{"my/resource/identifier"};
```
for(auto [id, res]: cache) {
// ...
}
The class `hashed_string` is described in a dedicated section, so I won't go in
details here.
Resources are loaded and thus stored in a cache through the `load` member
function. It accepts the loader to use as a template parameter, the resource
identifier and the parameters used to construct the resource as arguments:
```cpp
// uses the identifier declared above
cache.load<my_loader>(identifier, 0);
// uses a const char * directly as an identifier
cache.load<my_loader>("another/identifier"_hs, 42);
```
The function returns a handle to the resource, whether it already exists or is
loaded. In case the loader returns an invalid pointer, the handle is invalid as
well and therefore it can be easily used with an `if` statement:
```cpp
if(auto handle = cache.load<my_loader>("another/identifier"_hs, 42); handle) {
if(entt::resource<my_resource> res = cache["resource/id"_hs]; res) {
// ...
}
```
Before trying to load a resource, the `contains` member function can be used to
know if a cache already contains a specific resource:
Please, refer to the inline documentation for all the details about the other
functions (such as `contains` or `erase`).
Set aside the part of the API that this class _shares_ with a map, it also adds
something on top of it in order to address the most common requirements of a
resource cache.<br/>
In particular, it doesn't have an `emplace` member function which is replaced by
`load` and `force_load` instead (where the former loads a new resource only if
not present while the second triggers a forced loading in any case):
```cpp
auto exists = cache.contains("my/identifier"_hs);
auto ret = cache.load("resource/id"_hs);
// true only if the resource was not already present
const bool loaded = ret.second;
// takes the resource handle pointed to by the returned iterator
entt::resource<my_resource> res = ret.first->second;
```
There exists also a member function to use to force a reload of an already
existing resource if needed:
Note that the hashed string is used for convenience in the example above.<br/>
Resource identifiers are nothing more than integral values. Therefore, plain
numbers as well as non-class enum value are accepted.
```cpp
auto handle = cache.reload<my_loader>("another/identifier"_hs, 42);
```
As above, the function returns a handle to the resource that is invalid in case
of errors. The `reload` member function is a kind of alias of the following
snippet:
```cpp
cache.discard(identifier);
cache.load<my_loader>(identifier, 42);
```
Where the `discard` member function is used to get rid of a resource if loaded.
In case the cache doesn't contain a resource for the given identifier, `discard`
does nothing and returns immediately.
So far, so good. Resources are finally loaded and stored within the cache.<br/>
They are returned to users in the form of handles. To get one of them later on:
```cpp
auto handle = cache.handle("my/identifier"_hs);
```
The idea behind a handle is the same of the flyweight pattern. In other terms,
resources aren't copied around. Instead, instances are shared between handles.
Users of a resource own a handle that guarantees that a resource isn't destroyed
until all the handles are destroyed, even if the resource itself is removed from
the cache.<br/>
Handles are tiny objects both movable and copyable. They return the contained
resource as a const reference on request:
* By means of the `get` member function:
```cpp
const auto &resource = handle.get();
```
* Using the proper cast operator:
```cpp
const auto &resource = handle;
```
* Through the dereference operator:
```cpp
const auto &resource = *handle;
```
The resource can also be accessed directly using the arrow operator if required:
```cpp
auto value = handle->value;
```
To test if a handle is still valid, the cast operator to `bool` allows users to
use it in a guard:
```cpp
if(handle) {
// ...
}
```
Finally, in case there is the need to load a resource and thus to get a handle
without storing the resource itself in the cache, users can rely on the `temp`
member function template.<br/>
The declaration is similar to that of `load`, a (possibly invalid) handle for
the resource is returned also in this case:
```cpp
if(auto handle = cache.temp<my_loader>(42); handle) {
// ...
}
```
Do not forget to test the handle for validity. Otherwise, getting a reference to
the resource it points may result in undefined behavior.
It's worth mentioning that the iterators of a cache as well as its indexing
operators return resource handles rather than instances of the mapped type.<br/>
Since the cache has no control over the loader and a resource isn't required to
also be convertible to bool, these handles can be invalid. This usually means an
error in the user logic but it may also be an _expected_ event.<br/>
It's therefore recommended to verify handles validity with a check in debug (for
example, when loading) or an appropriate logic in retail.

View File

@@ -7,8 +7,11 @@
* [Introduction](#introduction)
* [Delegate](#delegate)
* [Runtime arguments](#runtime-arguments)
* [Lambda support](#lambda-support)
* [Signals](#signals)
* [Event dispatcher](#event-dispatcher)
* [Named queues](#named-queues)
* [Event emitter](#event-emitter)
<!--
@endcond TURN_OFF_DOXYGEN
@@ -16,27 +19,27 @@
# Introduction
Signals are usually a core part of games and software architectures in
general.<br/>
Roughly speaking, they help to decouple the various parts of a system while
allowing them to communicate with each other somehow.
Signals are more often than not a core part of games and software architectures
in general.<br/>
They help to decouple the various parts of a system while allowing them to
communicate with each other somehow.
The so called _modern C++_ comes with a tool that can be useful in these terms,
The so called _modern C++_ comes with a tool that can be useful in this regard,
the `std::function`. As an example, it can be used to create delegates.<br/>
However, there is no guarantee that an `std::function` does not perform
However, there is no guarantee that an `std::function` doesn't perform
allocations under the hood and this could be problematic sometimes. Furthermore,
it solves a problem but may not adapt well to other requirements that may arise
from time to time.
In case that the flexibility and power of an `std::function` isn't required or
if the price to pay for them is too high,` EnTT` offers a complete set of
if the price to pay for them is too high, `EnTT` offers a complete set of
lightweight classes to solve the same and many other problems.
# Delegate
A delegate can be used as a general purpose invoker with no memory overhead for
free functions and members provided along with an instance on which to invoke
them.<br/>
free functions and member functions provided along with an instance on which to
invoke them.<br/>
It doesn't claim to be a drop-in replacement for an `std::function`, so don't
expect to use it whenever an `std::function` fits well. That said, it's most
likely even a better fit than an `std::function` in a lot of cases, so expect to
@@ -49,21 +52,19 @@ delegates:
entt::delegate<int(int)> delegate{};
```
All what is needed to create an instance is to specify the type of the function
the delegate will _contain_, that is the signature of the free function or the
member one wants to assign to it.
What is needed to create an instance is to specify the type of the function the
delegate _accepts_, that is the signature of the functions it models.<br/>
However, attempting to use an empty delegate by invoking its function call
operator results in undefined behavior or most likely a crash.
Attempting to use an empty delegate by invoking its function call operator
results in undefined behavior or most likely a crash. Before to use a delegate,
it must be initialized.<br/>
There exists a bunch of overloads of the `connect` member function to do that.
As an example of use:
There exist a few overloads of the `connect` member function to initialize a
delegate:
```cpp
int f(int i) { return i; }
struct my_struct {
int f(const int &i) { return i }
int f(const int &i) const { return i; }
};
// bind a free function to the delegate
@@ -74,7 +75,7 @@ my_struct instance;
delegate.connect<&my_struct::f>(instance);
```
The delegate class accepts also data members, if needed. In this case, the
The delegate class also accepts data members, if needed. In this case, the
function type of the delegate is such that the parameter list is empty and the
value of the data member is at least convertible to the return type.
@@ -91,14 +92,11 @@ delegate.connect<&g>(c);
delegate(42);
```
The function `g` will be invoked with a reference to `c` and `42`. However, the
The function `g` is invoked with a reference to `c` and `42`. However, the
function type of the delegate is still `void(int)`. This is also the signature
of its function call operator.
Another interesting aspect of the delegate class is that it accepts also
functions with a list of parameters that is shorter than that of the function
type used to specialize the delegate itself.<br/>
The following code is therefore perfectly valid:
of its function call operator.<br/>
Another interesting aspect of the delegate class is that it accepts functions
with a list of parameters that is shorter than that of its function type:
```cpp
void g() { /* ... */ }
@@ -137,17 +135,17 @@ already shown in the examples above:
auto ret = delegate(42);
```
In all cases, the listeners don't have to strictly follow the signature of the
In all cases, listeners don't have to strictly follow the signature of the
delegate. As long as a listener can be invoked with the given arguments to yield
a result that is convertible to the given result type, everything works just
fine.
As a side note, note that members of a class may or may not be associated with
instances. If they are not, the first argument of the function type must be that
of the class on which the members operate and an instance of this class must
obviously be passed when invoking the delegate:
As a side note, members of classes may or may not be associated with instances.
If they are not, the first argument of the function type must be that of the
class on which the members operate and an instance of this class must obviously
be passed when invoking the delegate:
```
```cpp
entt::delegate<void(my_struct &, int)> delegate;
delegate.connect<&my_struct::f>();
@@ -155,11 +153,84 @@ my_struct instance;
delegate(instance, 42);
```
In this case, it's not possible to deduce the function type since the first
In this case, it's not possible to _deduce_ the function type since the first
argument doesn't necessarily have to be a reference (for example, it can be a
pointer, as well as a const reference).<br/>
Therefore, the function type must be declared explicitly for unbound members.
## Runtime arguments
The `delegate` class is meant to be used primarily with template arguments.
However, as a consequence of its design, it also offers minimal support for
runtime arguments.<br/>
When used like this, some features aren't supported though. In particular:
* Curried functions aren't accepted.
* Functions with an argument list that differs from that of the delegate aren't
supported.
* Return type and types of arguments **must** coincide with those of the
delegate and _being at least convertible_ isn't enough anymore.
Moreover, for a given function type `Ret(Args...)`, the signature of the
functions connected at runtime must necessarily be `Ret(const void *, Args...)`.
Runtime arguments can be passed both to the constructor of a delegate and to the
`connect` member function. An optional parameter is also accepted in both cases.
This argument is used to pass arbitrary user data back and forth as a
`const void *` upon invocation.<br/>
To connect a function to a delegate _in the hard way_:
```cpp
int func(const void *ptr, int i) { return *static_cast<const int *>(ptr) * i; }
const int value = 42;
// use the constructor ...
entt::delegate delegate{&func, &value};
// ... or the connect member function
delegate.connect(&func, &value);
```
The type of the delegate is deduced from the function if possible. In this case,
since the first argument is an implementation detail, the deduced function type
is `int(int)`.<br/>
Invoking a delegate built in this way follows the same rules as previously
explained.
## Lambda support
In general, the `delegate` class doesn't fully support lambda functions in all
their nuances. The reason is pretty simple: a `delegate` isn't a drop-in
replacement for an `std::function`. Instead, it tries to overcome the problems
with the latter.<br/>
That being said, non-capturing lambda functions are supported, even though some
features aren't available in this case.
This is a logical consequence of the support for connecting functions at
runtime. Therefore, lambda functions undergo the same rules and
limitations.<br/>
In fact, since non-capturing lambda functions decay to pointers to functions,
they can be used with a `delegate` as if they were _normal functions_ with
optional payload:
```cpp
my_struct instance;
// use the constructor ...
entt::delegate delegate{+[](const void *ptr, int value) {
return static_cast<const my_struct *>(ptr)->f(value);
}, &instance};
// ... or the connect member function
delegate.connect([](const void *ptr, int value) {
return static_cast<const my_struct *>(ptr)->f(value);
}, &instance);
```
As above, the first parameter (`const void *`) isn't part of the function type
of the delegate and is used to dispatch arbitrary user data back and forth. In
other terms, the function type of the delegate above is `int(int)`.
# Signals
Signal handlers work with references to classes, function pointers and pointers
@@ -171,16 +242,17 @@ Signals make use of delegates internally and therefore they undergo the same
rules and offer similar functionalities. It may be a good idea to consult the
documentation of the `delegate` class for further information.
A signal handler can be used as a private data member without exposing any
_publish_ functionality to the clients of a class. The basic idea is to impose a
clear separation between the signal itself and the `sink` class, that is a tool
to be used to connect and disconnect listeners on the fly.
A signal handler is can be used as a private data member without exposing any
_publish_ functionality to the clients of a class.<br/>
The basic idea is to impose a clear separation between the signal itself and the
`sink` class, that is a tool to be used to connect and disconnect listeners on
the fly.
The API of a signal handler is straightforward. If a collector is supplied to
the signal when something is published, all the values returned by the listeners
can be literally _collected_ and used later by the caller. Otherwise, the class
the signal when something is published, all the values returned by its listeners
are literally _collected_ and used later by the caller. Otherwise, the class
works just like a plain signal that emits events from time to time.<br/>
To create instances of signal handlers it is sufficient to provide the type of
To create instances of signal handlers it's sufficient to provide the type of
function to which they refer:
```cpp
@@ -224,13 +296,13 @@ sink.disconnect(instance);
sink.disconnect();
```
As shown above, the listeners don't have to strictly follow the signature of the
As shown above, listeners don't have to strictly follow the signature of the
signal. As long as a listener can be invoked with the given arguments to yield a
result that is convertible to the given return type, everything works just
fine.<br/>
It's also possible to connect a listener before other listeners already
contained by the signal. The `before` function returns a `sink` object correctly
initialized for the purpose that can be used to connect one or more listeners in
It's also possible to connect a listener before other elements already contained
by the signal. The `before` function returns a `sink` object that is correctly
initialized for the purpose and can be used to connect one or more listeners in
order and in the desired position:
```cpp
@@ -239,20 +311,19 @@ sink.before<&foo>().connect<&listener::bar>(instance);
In all cases, the `connect` member function returns by default a `connection`
object to be used as an alternative to break a connection by means of its
`release` member function. A `scoped_connection` can also be created from a
connection. In this case, the link is broken automatically as soon as the object
goes out of scope.
`release` member function.<br/>
A `scoped_connection` can also be created from a connection. In this case, the
link is broken automatically as soon as the object goes out of scope.
Once listeners are attached (or even if there are no listeners at all), events
and data in general can be published through a signal by means of the `publish`
and data in general are published through a signal by means of the `publish`
member function:
```cpp
signal.publish(42, 'c');
```
To collect data, the `collect` member function should be used instead. Below is
a minimal example to show how to use it:
To collect data, the `collect` member function is used instead:
```cpp
int f() { return 0; }
@@ -286,7 +357,7 @@ case:
struct my_collector {
std::vector<int> vec{};
bool operator()(int v) noexcept {
bool operator()(int v) {
vec.push_back(v);
return true;
}
@@ -300,23 +371,20 @@ signal.collect(std::ref(collector));
# Event dispatcher
The event dispatcher class is designed so as to be used in a loop. It allows
users both to trigger immediate events or to queue events to be published all
together once per tick.<br/>
This class shares part of its API with the one of the signal handler, but it
doesn't require that all the types of events are specified when declared:
The event dispatcher class allows users to trigger immediate events or to queue
and publish them all together later.<br/>
This class lazily instantiates its queues. Therefore, it's not necessary to
_announce_ the event types in advance:
```cpp
// define a general purpose dispatcher
entt::dispatcher dispatcher{};
```
In order to register an instance of a class to a dispatcher, its type must
expose one or more member functions the arguments of which are such that
`const E &` can be converted to them for each type of event `E`, no matter what
the return value is.<br/>
The name of the member function aimed to receive the event must be provided to
the `connect` member function of the sink in charge for the specific event:
A listener registered with a dispatcher is such that its type offers one or more
member functions that take arguments of type `Event &` for any type of event,
regardless of the return value.<br/>
These functions are linked directly via `connect` to a _sink_:
```cpp
struct an_event { int value; };
@@ -334,8 +402,10 @@ dispatcher.sink<an_event>().connect<&listener::receive>(listener);
dispatcher.sink<another_event>().connect<&listener::method>(listener);
```
The `disconnect` member function follows the same pattern and can be used to
remove one listener at a time or all of them at once:
Note that connecting listeners within event handlers can result in undefined
behavior.<br/>
The `disconnect` member function is used to remove one listener at a time or all
of them at once:
```cpp
dispatcher.sink<an_event>().disconnect<&listener::receive>(listener);
@@ -343,14 +413,10 @@ dispatcher.sink<another_event>().disconnect(listener);
```
The `trigger` member function serves the purpose of sending an immediate event
to all the listeners registered so far. It offers a convenient approach that
relieves users from having to create the event itself. Instead, it's enough to
specify the type of event and provide all the parameters required to construct
it.<br/>
As an example:
to all the listeners registered so far:
```cpp
dispatcher.trigger<an_event>(42);
dispatcher.trigger(an_event{42});
dispatcher.trigger<another_event>();
```
@@ -359,20 +425,18 @@ method can be used to push around urgent messages like an _is terminating_
notification on a mobile app.
On the other hand, the `enqueue` member function queues messages together and
allows to maintain control over the moment they are sent to listeners. The
signature of this method is more or less the same of `trigger`:
helps to maintain control over the moment they are sent to listeners:
```cpp
dispatcher.enqueue<an_event>(42);
dispatcher.enqueue<another_event>();
dispatcher.enqueue(another_event{});
```
Events are stored aside until the `update` member function is invoked, then all
the messages that are still pending are sent to the listeners at once:
Events are stored aside until the `update` member function is invoked:
```cpp
// emits all the events of the given type at once
dispatcher.update<my_event>();
dispatcher.update<an_event>();
// emits all the events queued so far at once
dispatcher.update();
@@ -381,6 +445,30 @@ dispatcher.update();
This way users can embed the dispatcher in a loop and literally dispatch events
once per tick to their systems.
## Named queues
All queues within a dispatcher are associated by default with an event type and
then retrieved from it.<br/>
However, it's possible to create queues with different _names_ (and therefore
also multiple queues for a single type). In fact, more or less all functions
also take an additional parameter. As an example:
```cpp
dispatcher.sink<an_event>("custom"_hs).connect<&listener::receive>(listener);
```
In this case, the term _name_ is misused as these are actual numeric identifiers
of type `id_type`.<br/>
An exception to this rule is the `enqueue` function. There is no additional
parameter for it but rather a different function:
```cpp
dispatcher.enqueue_hint<an_event>("custom"_hs, 42);
```
This is mainly due to the template argument deduction rules and unfortunately
there is no real (elegant) way to avoid it.
# Event emitter
A general purpose event emitter thought mainly for those cases where it comes to
@@ -389,8 +477,7 @@ Originally designed to fit the requirements of
[`uvw`](https://github.com/skypjack/uvw) (a wrapper for `libuv` written in
modern C++), it was adapted later to be included in this library.
To create a custom emitter type, derived classes must inherit directly from the
base class as:
To create an emitter type, derived classes must inherit from the base as:
```cpp
struct my_emitter: emitter<my_emitter> {
@@ -398,18 +485,10 @@ struct my_emitter: emitter<my_emitter> {
}
```
The full list of accepted types of events isn't required. Handlers are created
internally on the fly and thus each type of event is accepted by default.
Whenever an event is published, an emitter provides the listeners with a
reference to itself along with a const reference to the event. Therefore
listeners have an handy way to work with it without incurring in the need of
capturing a reference to the emitter itself.<br/>
In addition, an opaque object is returned each time a connection is established
between an emitter and a listener, allowing the caller to disconnect them at a
later time.<br/>
The opaque object used to handle connections is both movable and copyable. On
the other side, an event emitter is movable but not copyable by default.
Handlers for the different events are created internally on the fly. It's not
required to specify in advance the full list of accepted events.<br/>
Moreover, whenever an event is published, an emitter also passes a reference
to itself to its listeners.
To create new instances of an emitter, no arguments are required:
@@ -417,90 +496,54 @@ To create new instances of an emitter, no arguments are required:
my_emitter emitter{};
```
Listeners must be movable and callable objects (free functions, lambdas,
functors, `std::function`s, whatever) whose function type is:
Listeners are movable and callable objects (free functions, lambdas, functors,
`std::function`s, whatever) whose function type is compatible with:
```cpp
void(const Event &, my_emitter &)
void(Type &, my_emitter &)
```
Where `Event` is the type of event they want to listen.<br/>
There are two ways to attach a listener to an event emitter that differ
slightly from each other:
* To register a long-lived listener, use the `on` member function. It is meant
to register a listener designed to be invoked more than once for the given
event type.<br/>
As an example:
```cpp
auto conn = emitter.on<my_event>([](const my_event &event, my_emitter &emitter) {
// ...
});
```
The connection object can be freely discarded. Otherwise, it can be used later
to disconnect the listener if required.
* To register a short-lived listener, use the `once` member function. It is
meant to register a listener designed to be invoked only once for the given
event type. The listener is automatically disconnected after the first
invocation.<br/>
As an example:
```cpp
auto conn = emitter.once<my_event>([](const my_event &event, my_emitter &emitter) {
// ...
});
```
The connection object can be freely discarded. Otherwise, it can be used later
to disconnect the listener if required.
In both cases, the connection object can be used with the `erase` member
function:
Where `Type` is the type of event they want to receive.<br/>
To attach a listener to an emitter, there exists the `on` member function:
```cpp
emitter.erase(conn);
emitter.on<my_event>([](const my_event &event, my_emitter &emitter) {
// ...
});
```
There are also two member functions to use either to disconnect all the
listeners for a given type of event or to clear the emitter:
Similarly, the `reset` member function is used to disconnect listeners given a
type while `clear` is used to disconnect all listeners at once:
```cpp
// removes all the listener for the specific event
emitter.clear<my_event>();
// resets the listener for my_event
emitter.erase<my_event>();
// removes all the listeners registered so far
emitter.clear();
// resets all listeners
emitter.clear()
```
To send an event to all the listeners that are interested in it, the `publish`
member function offers a convenient approach that relieves users from having to
create the event:
To send an event to the listener registered on a given type, the `publish`
function is the way to go:
```cpp
struct my_event { int i; };
// ...
emitter.publish<my_event>(42);
emitter.publish(my_event{42});
```
Finally, the `empty` member function tests if there exists at least either a
listener registered with the event emitter or to a given type of event:
Finally, the `empty` member function tests if there exists at least a listener
registered with the event emitter while `contains` is used to check if a given
event type is associated with a valid listener:
```cpp
bool empty;
// checks if there is any listener registered for the specific event
empty = emitter.empty<my_event>();
// checks it there are listeners registered with the event emitter
empty = emitter.empty();
if(emitter.contains<my_event>()) {
// ...
}
```
In general, the event emitter is a handy tool when the derived classes _wrap_
asynchronous operations, because it introduces a _nice-to-have_ model based on
events and listeners that kindly hides the complexity behind the scenes. However
it is not limited to such uses.
This class introduces a _nice-to-have_ model based on events and listeners.<br/>
More in general, it's a handy tool when the derived classes _wrap_ asynchronous
operations but it's not limited to such uses.

107
docs/md/unreal.md Normal file
View File

@@ -0,0 +1,107 @@
# EnTT and Unreal Engine
<!--
@cond TURN_OFF_DOXYGEN
-->
# Table of Contents
* [Enable Cpp17](#enable-cpp17)
* [EnTT as a third party module](#entt-as-a-third-party-module)
* [Include EnTT](#include-entt)
<!--
@endcond TURN_OFF_DOXYGEN
-->
## Enable Cpp17
As of writing (Unreal Engine v4.25), the default C++ standard of Unreal Engine
is C++14.<br/>
On the other hand, note that `EnTT` requires C++17 to compile. To enable it, in
the main module of the project there should be a `<Game Name>.Build.cs` file,
the constructor of which must contain the following lines:
```cs
PCHUsage = PCHUsageMode.NoSharedPCHs;
PrivatePCHHeaderFile = "<PCH filename>.h";
CppStandard = CppStandardVersion.Cpp17;
```
Replace `<PCH filename>.h` with the name of the already existing PCH header
file, if any.<br/>
In case the project doesn't already contain a file of this type, it's possible
to create one with the following content:
```cpp
#pragma once
#include "CoreMinimal.h"
```
Remember to remove any old `PCHUsage = <...>` line that was previously there. At
this point, C++17 support should be in place.<br/>
Try to compile the project to ensure it works as expected before following
further steps.
Note that updating a *project* to C++17 doesn't necessarily mean that the IDE in
use will also start to recognize its syntax.<br/>
If the plan is to use C++17 in the project too, check the specific instructions
for the IDE in use.
## EnTT as a third party module
Once this point is reached, the `Source` directory should look like this:
```
Source
| MyGame.Target.cs
| MyGameEditor.Target.cs
|
+---MyGame
| | MyGame.Build.cs
| | MyGame.h (PCH Header file)
|
\---ThirdParty
\---EnTT
| EnTT.Build.cs
|
\---entt (GitHub repository content inside)
```
To make this happen, create the folder `ThirdParty` under `Source` if it doesn't
exist already. Then, add an `EnTT` folder under `ThirdParty`.<br/>
Within the latter, create a new file `EnTT.Build.cs` with the following content:
```cs
using System.IO;
using UnrealBuildTool;
public class EnTT: ModuleRules {
public EnTT(ReadOnlyTargetRules Target) : base(Target) {
Type = ModuleType.External;
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "entt", "src", "entt"));
}
}
```
The last line indicates that the actual files will be found in the directory
`EnTT/entt/src/entt`.<br/>
Download the repository for `EnTT` and place it next to `EnTT.Build.cs` or
update the path above accordingly.
Finally, open the `<Game Name>.Build.cs` file and add `EnTT` as a dependency at
the end of the list:
```cs
PublicDependencyModuleNames.AddRange(new[] {
"Core", "CoreUObject", "Engine", "InputCore", [...], "EnTT"
});
```
Note that some IDEs might require a restart to start recognizing the new module
for code-highlighting features and such.
## Include EnTT
In any source file of the project, add `#include "entt.hpp"` or any other path
to the file from `EnTT` to use it.<br/>
Try to create a registry as `entt::registry registry;` to make sure everything
compiles fine.

34
entt.imp Normal file
View File

@@ -0,0 +1,34 @@
[
{ "include": [ "@<gtest/internal/.*>", "private", "<gtest/gtest.h>", "public" ] },
{ "include": [ "@<gtest/gtest-.*>", "private", "<gtest/gtest.h>", "public" ] },
{ "include": [ "@[\"<].*/container/fwd.hpp[\">]", "private", "<entt/container/dense_map.hpp>", "public" ] },
{ "include": [ "@[\"<].*/container/fwd.hpp[\">]", "private", "<entt/container/dense_set.hpp>", "public" ] },
{ "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/any.hpp>", "public" ] },
{ "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/family.hpp>", "public" ] },
{ "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/hashed_string.hpp>", "public" ] },
{ "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/ident.hpp>", "public" ] },
{ "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/monostate.hpp>", "public" ] },
{ "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/type_info.hpp>", "public" ] },
{ "include": [ "@[\"<].*/core/fwd.hpp[\">]", "private", "<entt/core/type_traits.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/entity.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/group.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/handle.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/helper.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/observer.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/organizer.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/registry.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/runtime_view.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/snapshot.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/sparse_set.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/storage.hpp>", "public" ] },
{ "include": [ "@[\"<].*/entity/fwd.hpp[\">]", "private", "<entt/entity/view.hpp>", "public" ] },
{ "include": [ "@[\"<].*/meta/fwd.hpp[\">]", "private", "<entt/meta/meta.hpp>", "public" ] },
{ "include": [ "@[\"<].*/poly/fwd.hpp[\">]", "private", "<entt/poly/poly.hpp>", "public" ] },
{ "include": [ "@[\"<].*/resource/fwd.hpp[\">]", "private", "<entt/resource/cache.hpp>", "public" ] },
{ "include": [ "@[\"<].*/resource/fwd.hpp[\">]", "private", "<entt/resource/loader.hpp>", "public" ] },
{ "include": [ "@[\"<].*/resource/fwd.hpp[\">]", "private", "<entt/resource/resource.hpp>", "public" ] },
{ "include": [ "@[\"<].*/signal/fwd.hpp[\">]", "private", "<entt/signal/delegate.hpp>", "public" ] },
{ "include": [ "@[\"<].*/signal/fwd.hpp[\">]", "private", "<entt/signal/dispatcher.hpp>", "public" ] },
{ "include": [ "@[\"<].*/signal/fwd.hpp[\">]", "private", "<entt/signal/emitter.hpp>", "public" ] },
{ "include": [ "@[\"<].*/signal/fwd.hpp[\">]", "private", "<entt/signal/sigh.hpp>", "public" ] }
]

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
</AutoVisualizer>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="entt::dense_map&lt;*&gt;">
<Intrinsic Name="size" Expression="packed.first_base::value.size()"/>
<Intrinsic Name="bucket_count" Expression="sparse.first_base::value.size()"/>
<DisplayString>{{ size={ size() } }}</DisplayString>
<Expand>
<Item Name="[capacity]" ExcludeView="simple">packed.first_base::value.capacity()</Item>
<Item Name="[bucket_count]" ExcludeView="simple">bucket_count()</Item>
<Item Name="[load_factor]" ExcludeView="simple">(float)size() / (float)bucket_count()</Item>
<Item Name="[max_load_factor]" ExcludeView="simple">threshold</Item>
<IndexListItems>
<Size>size()</Size>
<ValueNode>packed.first_base::value[$i].element</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="entt::dense_set&lt;*&gt;">
<Intrinsic Name="size" Expression="packed.first_base::value.size()"/>
<Intrinsic Name="bucket_count" Expression="sparse.first_base::value.size()"/>
<DisplayString>{{ size={ size() } }}</DisplayString>
<Expand>
<Item Name="[capacity]" ExcludeView="simple">packed.first_base::value.capacity()</Item>
<Item Name="[bucket_count]" ExcludeView="simple">bucket_count()</Item>
<Item Name="[load_factor]" ExcludeView="simple">(float)size() / (float)bucket_count()</Item>
<Item Name="[max_load_factor]" ExcludeView="simple">threshold</Item>
<IndexListItems>
<Size>size()</Size>
<ValueNode>packed.first_base::value[$i].second</ValueNode>
</IndexListItems>
</Expand>
</Type>
</AutoVisualizer>

32
natvis/entt/core.natvis Normal file
View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="entt::basic_any&lt;*&gt;">
<DisplayString>{{ type={ info->alias,na }, policy={ mode,en } }}</DisplayString>
</Type>
<Type Name="entt::compressed_pair&lt;*&gt;">
<Intrinsic Name="first" Optional="true" Expression="((first_base*)this)->value"/>
<Intrinsic Name="first" Optional="true" Expression="*(first_base::base_type*)this"/>
<Intrinsic Name="second" Optional="true" Expression="((second_base*)this)->value"/>
<Intrinsic Name="second" Optional="true" Expression="*(second_base::base_type*)this"/>
<DisplayString >({ first() }, { second() })</DisplayString>
<Expand>
<Item Name="[first]">first()</Item>
<Item Name="[second]">second()</Item>
</Expand>
</Type>
<Type Name="entt::basic_hashed_string&lt;*&gt;">
<DisplayString Condition="base_type::repr != nullptr">{{ hash={ base_type::hash } }}</DisplayString>
<DisplayString>{{}}</DisplayString>
<Expand>
<Item Name="[data]">base_type::repr,na</Item>
<Item Name="[length]">base_type::length</Item>
</Expand>
</Type>
<Type Name="entt::type_info">
<DisplayString>{{ name={ alias,na } }}</DisplayString>
<Expand>
<Item Name="[hash]">identifier</Item>
<Item Name="[index]">seq</Item>
</Expand>
</Type>
</AutoVisualizer>

153
natvis/entt/entity.natvis Normal file
View File

@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="entt::basic_registry&lt;*&gt;">
<Intrinsic Name="pools_size" Expression="pools.packed.first_base::value.size()"/>
<Intrinsic Name="vars_size" Expression="vars.ctx.packed.first_base::value.size()"/>
<Intrinsic Name="to_entity" Expression="*((entity_traits::entity_type *)&amp;entity) &amp; entity_traits::entity_mask">
<Parameter Name="entity" Type="entity_traits::value_type &amp;"/>
</Intrinsic>
<DisplayString>{{ size={ epool.size() } }}</DisplayString>
<Expand>
<Item IncludeView="simple" Name="[epool]">epool,view(simple)nr</Item>
<Synthetic Name="[epool]" ExcludeView="simple">
<DisplayString>{ epool.size() }</DisplayString>
<Expand>
<CustomListItems>
<Variable Name="pos" InitialValue="0" />
<Variable Name="last" InitialValue="epool.size()"/>
<Loop>
<Break Condition="pos == last"/>
<If Condition="to_entity(epool[pos]) == pos">
<Item Name="[{ pos }]">epool[pos]</Item>
</If>
<Exec>++pos</Exec>
</Loop>
</CustomListItems>
</Expand>
</Synthetic>
<Synthetic Name="[destroyed]" ExcludeView="simple">
<DisplayString>{ to_entity(free_list) != entity_traits::entity_mask }</DisplayString>
<Expand>
<CustomListItems>
<Variable Name="it" InitialValue="to_entity(free_list)" />
<Loop>
<Break Condition="it == entity_traits::entity_mask"/>
<Item Name="[{ it }]">epool[it]</Item>
<Exec>it = to_entity(epool[it])</Exec>
</Loop>
</CustomListItems>
</Expand>
</Synthetic>
<Synthetic Name="[pools]">
<DisplayString>{ pools_size() }</DisplayString>
<Expand>
<IndexListItems ExcludeView="simple">
<Size>pools_size()</Size>
<ValueNode>*pools.packed.first_base::value[$i].element.second</ValueNode>
</IndexListItems>
<IndexListItems IncludeView="simple">
<Size>pools_size()</Size>
<ValueNode>*pools.packed.first_base::value[$i].element.second,view(simple)</ValueNode>
</IndexListItems>
</Expand>
</Synthetic>
<Item Name="[groups]" ExcludeView="simple">groups.size()</Item>
<Synthetic Name="[vars]">
<DisplayString>{ vars_size() }</DisplayString>
<Expand>
<IndexListItems>
<Size>vars_size()</Size>
<ValueNode>vars.ctx.packed.first_base::value[$i].element.second</ValueNode>
</IndexListItems>
</Expand>
</Synthetic>
</Expand>
</Type>
<Type Name="entt::basic_sparse_set&lt;*&gt;">
<DisplayString>{{ size={ packed.size() }, type={ info->alias,na } }}</DisplayString>
<Expand>
<Item Name="[capacity]" ExcludeView="simple">packed.capacity()</Item>
<Item Name="[policy]">mode,en</Item>
<Synthetic Name="[sparse]">
<DisplayString>{ sparse.size() * entity_traits::page_size }</DisplayString>
<Expand>
<ExpandedItem IncludeView="simple">sparse,view(simple)</ExpandedItem>
<CustomListItems ExcludeView="simple">
<Variable Name="pos" InitialValue="0"/>
<Variable Name="page" InitialValue="0"/>
<Variable Name="offset" InitialValue="0"/>
<Variable Name="last" InitialValue="sparse.size() * entity_traits::page_size"/>
<Loop>
<Break Condition="pos == last"/>
<Exec>page = pos / entity_traits::page_size</Exec>
<Exec>offset = pos &amp; (entity_traits::page_size - 1)</Exec>
<If Condition="sparse[page] &amp;&amp; (*((entity_traits::entity_type *)&amp;sparse[page][offset]) &lt; ~entity_traits::entity_mask)">
<Item Name="[{ pos }]">*((entity_traits::entity_type *)&amp;sparse[page][offset]) &amp; entity_traits::entity_mask</Item>
</If>
<Exec>++pos</Exec>
</Loop>
</CustomListItems>
</Expand>
</Synthetic>
<Synthetic Name="[packed]">
<DisplayString>{ packed.size() }</DisplayString>
<Expand>
<ExpandedItem IncludeView="simple">packed,view(simple)</ExpandedItem>
<CustomListItems ExcludeView="simple">
<Variable Name="pos" InitialValue="0"/>
<Variable Name="last" InitialValue="packed.size()"/>
<Loop>
<Break Condition="pos == last"/>
<If Condition="*((entity_traits::entity_type *)&amp;packed[pos]) &lt; ~entity_traits::entity_mask">
<Item Name="[{ pos }]">packed[pos]</Item>
</If>
<Exec>++pos</Exec>
</Loop>
</CustomListItems>
</Expand>
</Synthetic>
</Expand>
</Type>
<Type Name="entt::basic_storage&lt;*&gt;">
<DisplayString>{{ size={ base_type::packed.size() }, type={ base_type::info->alias,na } }}</DisplayString>
<Expand>
<Item Name="[capacity]" Optional="true" ExcludeView="simple">packed.first_base::value.capacity() * comp_traits::page_size</Item>
<Item Name="[page size]" Optional="true" ExcludeView="simple">comp_traits::page_size</Item>
<Item Name="[base]" ExcludeView="simple">(base_type*)this,nand</Item>
<Item Name="[base]" IncludeView="simple">(base_type*)this,view(simple)nand</Item>
<!-- having SFINAE-like techniques in natvis is priceless :) -->
<CustomListItems Condition="packed.first_base::value.size() != 0" Optional="true">
<Variable Name="pos" InitialValue="0" />
<Variable Name="last" InitialValue="base_type::packed.size()"/>
<Loop>
<Break Condition="pos == last"/>
<If Condition="*((base_type::entity_traits::entity_type *)&amp;base_type::packed[pos]) &lt; ~base_type::entity_traits::entity_mask">
<Item Name="[{ pos }:{ base_type::packed[pos] }]">packed.first_base::value[pos / comp_traits::page_size][pos &amp; (comp_traits::page_size - 1)]</Item>
</If>
<Exec>++pos</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
<Type Name="entt::basic_view&lt;*&gt;">
<DisplayString>{{ size_hint={ view->packed.size() } }}</DisplayString>
<Expand>
<Item Name="[pools]">pools,na</Item>
<Item Name="[filter]">filter,na</Item>
</Expand>
</Type>
<Type Name="entt::basic_runtime_view&lt;*&gt;">
<DisplayString Condition="pools.size() != 0u">{{ size_hint={ pools[0]->packed.size() } }}</DisplayString>
<DisplayString>{{ size_hint=0 }}</DisplayString>
<Expand>
<Item Name="[pools]">pools,na</Item>
<Item Name="[filter]">filter,na</Item>
</Expand>
</Type>
<Type Name="entt::null_t">
<DisplayString>&lt;null&gt;</DisplayString>
</Type>
<Type Name="entt::tombstone_t">
<DisplayString>&lt;tombstone&gt;</DisplayString>
</Type>
</AutoVisualizer>

19
natvis/entt/graph.natvis Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="entt::adjacency_matrix&lt;*&gt;">
<DisplayString>{{ size={ vert } }}</DisplayString>
<Expand>
<CustomListItems>
<Variable Name="pos" InitialValue="0" />
<Variable Name="last" InitialValue="vert * vert"/>
<Loop>
<Break Condition="pos == last"/>
<If Condition="matrix[pos] != 0u">
<Item Name="{pos / vert}">pos % vert</Item>
</If>
<Exec>++pos</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
</AutoVisualizer>

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
</AutoVisualizer>

121
natvis/entt/meta.natvis Normal file
View File

@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="entt::internal::meta_base_node">
<DisplayString>{{}}</DisplayString>
</Type>
<Type Name="entt::internal::meta_conv_node">
<DisplayString>{{}}</DisplayString>
</Type>
<Type Name="entt::internal::meta_ctor_node">
<DisplayString>{{ arity={ arity } }}</DisplayString>
</Type>
<Type Name="entt::internal::meta_data_node">
<Intrinsic Name="has_property" Expression="!!(traits &amp; property)">
<Parameter Name="property" Type="int"/>
</Intrinsic>
<DisplayString>{{ arity={ arity } }}</DisplayString>
<Expand>
<Item Name="[arity]">arity</Item>
<Item Name="[is_const]">has_property(entt::internal::meta_traits::is_const)</Item>
<Item Name="[is_static]">has_property(entt::internal::meta_traits::is_static)</Item>
<Item Name="[prop]">prop</Item>
</Expand>
</Type>
<Type Name="entt::internal::meta_func_node" >
<Intrinsic Name="has_property" Expression="!!(traits &amp; property)">
<Parameter Name="property" Type="int"/>
</Intrinsic>
<DisplayString>{{ arity={ arity } }}</DisplayString>
<Expand>
<Item Name="[is_const]">has_property(entt::internal::meta_traits::is_const)</Item>
<Item Name="[is_static]">has_property(entt::internal::meta_traits::is_static)</Item>
<Item Name="[next]" Condition="next != nullptr">*next</Item>
<Item Name="[prop]">prop</Item>
</Expand>
</Type>
<Type Name="entt::internal::meta_prop_node">
<DisplayString>{ value }</DisplayString>
</Type>
<Type Name="entt::internal::meta_template_node">
<DisplayString>{{ arity={ arity } }}</DisplayString>
</Type>
<Type Name="entt::internal::meta_type_node">
<Intrinsic Name="has_property" Expression="!!(traits &amp; property)">
<Parameter Name="property" Type="int"/>
</Intrinsic>
<DisplayString Condition="info != nullptr">{{ type={ info->alias,na } }}</DisplayString>
<DisplayString>{{}}</DisplayString>
<Expand>
<Item Name="[id]">id</Item>
<Item Name="[sizeof]">size_of</Item>
<Item Name="[is_arithmetic]">has_property(entt::internal::meta_traits::is_arithmetic)</Item>
<Item Name="[is_integral]">has_property(entt::internal::meta_traits::is_integral)</Item>
<Item Name="[is_signed]">has_property(entt::internal::meta_traits::is_signed)</Item>
<Item Name="[is_array]">has_property(entt::internal::meta_traits::is_array)</Item>
<Item Name="[is_enum]">has_property(entt::internal::meta_traits::is_enum)</Item>
<Item Name="[is_class]">has_property(entt::internal::meta_traits::is_class)</Item>
<Item Name="[is_meta_pointer_like]">has_property(entt::internal::meta_traits::is_meta_pointer_like)</Item>
<Item Name="[is_meta_sequence_container]">has_property(entt::internal::meta_traits::is_meta_sequence_container)</Item>
<Item Name="[is_meta_associative_container]">has_property(entt::internal::meta_traits::is_meta_associative_container)</Item>
<Item Name="[default_constructor]">default_constructor != nullptr</Item>
<Item Name="[conversion_helper]">conversion_helper != nullptr</Item>
<Item Name="[from_void]">from_void != nullptr</Item>
<Item Name="[template_info]">templ</Item>
<Item Name="[details]" Condition="details != nullptr">*details</Item>
</Expand>
</Type>
<Type Name="entt::meta_any">
<DisplayString Condition="node.info != nullptr">{{ type={ node.info->alias,na }, policy={ storage.mode,en } }}</DisplayString>
<DisplayString>{{}}</DisplayString>
<Expand>
<ExpandedItem>node</ExpandedItem>
<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
</Expand>
</Type>
<Type Name="entt::meta_handle">
<DisplayString>{ any }</DisplayString>
</Type>
<Type Name="entt::meta_associative_container">
<DisplayString>{ storage }</DisplayString>
<Expand>
<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
</Expand>
</Type>
<Type Name="entt::meta_sequence_container">
<DisplayString>{ storage }</DisplayString>
<Expand>
<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
</Expand>
</Type>
<Type Name="entt::meta_data">
<DisplayString Condition="node != nullptr">{ *node }</DisplayString>
<DisplayString>{{}}</DisplayString>
<Expand>
<ExpandedItem Condition="node != nullptr">node</ExpandedItem>
<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
</Expand>
</Type>
<Type Name="entt::meta_func">
<DisplayString Condition="node != nullptr">{ *node }</DisplayString>
<DisplayString>{{}}</DisplayString>
<Expand>
<ExpandedItem Condition="node != nullptr">node</ExpandedItem>
<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
</Expand>
</Type>
<Type Name="entt::meta_prop">
<DisplayString Condition="node != nullptr">{ *node }</DisplayString>
<DisplayString>{{}}</DisplayString>
<Expand>
<ExpandedItem Condition="node != nullptr">node</ExpandedItem>
<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
</Expand>
</Type>
<Type Name="entt::meta_type">
<DisplayString>{ node }</DisplayString>
<Expand>
<ExpandedItem>node</ExpandedItem>
<Item Name="[context]" Condition="ctx != nullptr">ctx->value</Item>
</Expand>
</Type>
</AutoVisualizer>

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
</AutoVisualizer>

6
natvis/entt/poly.natvis Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="entt::basic_poly&lt;*&gt;">
<DisplayString>{ storage }</DisplayString>
</Type>
</AutoVisualizer>

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
</AutoVisualizer>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="entt::resource&lt;*&gt;">
<DisplayString>{ value }</DisplayString>
<Expand>
<ExpandedItem>value</ExpandedItem>
</Expand>
</Type>
<Type Name="entt::resource_cache&lt;*&gt;">
<DisplayString>{ pool.first_base::value }</DisplayString>
<Expand>
<ExpandedItem>pool.first_base::value</ExpandedItem>
</Expand>
</Type>
</AutoVisualizer>

56
natvis/entt/signal.natvis Normal file
View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="entt::delegate&lt;*&gt;">
<DisplayString>{{ type={ "$T1" } }}</DisplayString>
<Expand>
<Item Name="[empty]">fn == nullptr</Item>
<Item Name="[data]">instance</Item>
</Expand>
</Type>
<Type Name="entt::basic_dispatcher&lt;*&gt;">
<Intrinsic Name="size" Expression="pools.first_base::value.packed.first_base::value.size()"/>
<DisplayString>{{ size={ size() } }}</DisplayString>
<Expand>
<Synthetic Name="[pools]">
<DisplayString>{ size() }</DisplayString>
<Expand>
<IndexListItems>
<Size>size()</Size>
<ValueNode>*pools.first_base::value.packed.first_base::value[$i].element.second</ValueNode>
</IndexListItems>
</Expand>
</Synthetic>
</Expand>
</Type>
<Type Name="entt::internal::dispatcher_handler&lt;*&gt;">
<DisplayString>{{ size={ events.size() }, event={ "$T1" } }}</DisplayString>
<Expand>
<Item Name="[signal]">signal</Item>
</Expand>
</Type>
<Type Name="entt::emitter&lt;*&gt;">
<DisplayString>{{ size={ handlers.first_base::value.packed.first_base::value.size() } }}</DisplayString>
</Type>
<Type Name="entt::connection">
<DisplayString>{{ bound={ signal != nullptr } }}</DisplayString>
</Type>
<Type Name="entt::scoped_connection">
<DisplayString>{ conn }</DisplayString>
</Type>
<Type Name="entt::sigh&lt;*&gt;">
<DisplayString>{{ size={ calls.size() }, type={ "$T1" } }}</DisplayString>
<Expand>
<IndexListItems>
<Size>calls.size()</Size>
<ValueNode>calls[$i]</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="entt::sink&lt;*&gt;">
<DisplayString>{{ type={ "$T1" } }}</DisplayString>
<Expand>
<Item Name="[signal]">signal,na</Item>
<Item Name="[offset]">offset</Item>
</Expand>
</Type>
</AutoVisualizer>

File diff suppressed because it is too large Load Diff

View File

@@ -1,67 +1,81 @@
#ifndef ENTT_CONFIG_CONFIG_H
#define ENTT_CONFIG_CONFIG_H
#include "version.h"
#ifndef ENTT_NOEXCEPT
# define ENTT_NOEXCEPT noexcept
#endif
#ifndef ENTT_HS_SUFFIX
# define ENTT_HS_SUFFIX _hs
#endif
#ifndef ENTT_HWS_SUFFIX
# define ENTT_HWS_SUFFIX _hws
#endif
#ifndef ENTT_USE_ATOMIC
# define ENTT_MAYBE_ATOMIC(Type) Type
#if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
# define ENTT_CONSTEXPR
# define ENTT_THROW throw
# define ENTT_TRY try
# define ENTT_CATCH catch(...)
#else
# include <atomic>
# define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
# define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
# define ENTT_THROW
# define ENTT_TRY if(true)
# define ENTT_CATCH if(false)
#endif
#ifdef ENTT_USE_ATOMIC
# include <atomic>
# define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
#else
# define ENTT_MAYBE_ATOMIC(Type) Type
#endif
#ifndef ENTT_ID_TYPE
# include <cstdint>
# define ENTT_ID_TYPE std::uint32_t
# include <cstdint>
# define ENTT_ID_TYPE std::uint32_t
#endif
#ifndef ENTT_PAGE_SIZE
# define ENTT_PAGE_SIZE 32768
#ifndef ENTT_SPARSE_PAGE
# define ENTT_SPARSE_PAGE 4096
#endif
#ifndef ENTT_ASSERT
# include <cassert>
# define ENTT_ASSERT(condition) assert(condition)
#ifndef ENTT_PACKED_PAGE
# define ENTT_PACKED_PAGE 1024
#endif
#ifdef ENTT_DISABLE_ASSERT
# undef ENTT_ASSERT
# define ENTT_ASSERT(condition, msg) (void(0))
#elif !defined ENTT_ASSERT
# include <cassert>
# define ENTT_ASSERT(condition, msg) assert(condition)
#endif
#ifndef ENTT_DISABLE_ETO
# include <type_traits>
# define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
#ifdef ENTT_DISABLE_ASSERT
# undef ENTT_ASSERT_CONSTEXPR
# define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
#elif !defined ENTT_ASSERT_CONSTEXPR
# define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
#endif
#ifdef ENTT_NO_ETO
# define ENTT_ETO_TYPE(Type) void
#else
# // sfinae-friendly definition
# define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
# define ENTT_ETO_TYPE(Type) Type
#endif
#ifndef ENTT_STANDARD_CPP
# if defined _MSC_VER
# define ENTT_PRETTY_FUNCTION __FUNCSIG__
# define ENTT_PRETTY_FUNCTION_CONSTEXPR ENTT_PRETTY_FUNCTION
# elif defined __clang__ || (defined __GNUC__ && __GNUC__ > 8)
# define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
# define ENTT_PRETTY_FUNCTION_CONSTEXPR ENTT_PRETTY_FUNCTION
# elif defined __GNUC__
# define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
# endif
#ifdef ENTT_STANDARD_CPP
# define ENTT_NONSTD false
#else
# define ENTT_NONSTD true
# if defined __clang__ || defined __GNUC__
# define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
# define ENTT_PRETTY_FUNCTION_PREFIX '='
# define ENTT_PRETTY_FUNCTION_SUFFIX ']'
# elif defined _MSC_VER
# define ENTT_PRETTY_FUNCTION __FUNCSIG__
# define ENTT_PRETTY_FUNCTION_PREFIX '<'
# define ENTT_PRETTY_FUNCTION_SUFFIX '>'
# endif
#endif
#if defined _MSC_VER
# pragma detect_mismatch("entt.version", ENTT_VERSION)
# pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
# pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
# pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
#endif
#endif

7
src/entt/config/macro.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef ENTT_CONFIG_MACRO_H
#define ENTT_CONFIG_MACRO_H
#define ENTT_STR(arg) #arg
#define ENTT_XSTR(arg) ENTT_STR(arg)
#endif

View File

@@ -1,10 +1,14 @@
#ifndef ENTT_CONFIG_VERSION_H
#define ENTT_CONFIG_VERSION_H
#include "macro.h"
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 3
#define ENTT_VERSION_MINOR 11
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
"." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,895 @@
#ifndef ENTT_CONTAINER_DENSE_SET_HPP
#define ENTT_CONTAINER_DENSE_SET_HPP
#include <cmath>
#include <cstddef>
#include <functional>
#include <iterator>
#include <limits>
#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include "../config/config.h"
#include "../core/compressed_pair.hpp"
#include "../core/memory.hpp"
#include "../core/type_traits.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename It>
class dense_set_iterator final {
template<typename>
friend class dense_set_iterator;
public:
using value_type = typename It::value_type::second_type;
using pointer = const value_type *;
using reference = const value_type &;
using difference_type = std::ptrdiff_t;
using iterator_category = std::random_access_iterator_tag;
constexpr dense_set_iterator() noexcept
: it{} {}
constexpr dense_set_iterator(const It iter) noexcept
: it{iter} {}
template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
constexpr dense_set_iterator(const dense_set_iterator<Other> &other) noexcept
: it{other.it} {}
constexpr dense_set_iterator &operator++() noexcept {
return ++it, *this;
}
constexpr dense_set_iterator operator++(int) noexcept {
dense_set_iterator orig = *this;
return ++(*this), orig;
}
constexpr dense_set_iterator &operator--() noexcept {
return --it, *this;
}
constexpr dense_set_iterator operator--(int) noexcept {
dense_set_iterator orig = *this;
return operator--(), orig;
}
constexpr dense_set_iterator &operator+=(const difference_type value) noexcept {
it += value;
return *this;
}
constexpr dense_set_iterator operator+(const difference_type value) const noexcept {
dense_set_iterator copy = *this;
return (copy += value);
}
constexpr dense_set_iterator &operator-=(const difference_type value) noexcept {
return (*this += -value);
}
constexpr dense_set_iterator operator-(const difference_type value) const noexcept {
return (*this + -value);
}
[[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
return it[value].second;
}
[[nodiscard]] constexpr pointer operator->() const noexcept {
return std::addressof(it->second);
}
[[nodiscard]] constexpr reference operator*() const noexcept {
return *operator->();
}
template<typename ILhs, typename IRhs>
friend constexpr std::ptrdiff_t operator-(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) noexcept;
template<typename ILhs, typename IRhs>
friend constexpr bool operator==(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) noexcept;
template<typename ILhs, typename IRhs>
friend constexpr bool operator<(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) noexcept;
private:
It it;
};
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) noexcept {
return lhs.it - rhs.it;
}
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator==(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) noexcept {
return lhs.it == rhs.it;
}
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator!=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) noexcept {
return !(lhs == rhs);
}
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator<(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) noexcept {
return lhs.it < rhs.it;
}
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator>(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) noexcept {
return rhs < lhs;
}
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator<=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) noexcept {
return !(lhs > rhs);
}
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator>=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) noexcept {
return !(lhs < rhs);
}
template<typename It>
class dense_set_local_iterator final {
template<typename>
friend class dense_set_local_iterator;
public:
using value_type = typename It::value_type::second_type;
using pointer = const value_type *;
using reference = const value_type &;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
constexpr dense_set_local_iterator() noexcept
: it{},
offset{} {}
constexpr dense_set_local_iterator(It iter, const std::size_t pos) noexcept
: it{iter},
offset{pos} {}
template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
constexpr dense_set_local_iterator(const dense_set_local_iterator<Other> &other) noexcept
: it{other.it},
offset{other.offset} {}
constexpr dense_set_local_iterator &operator++() noexcept {
return offset = it[offset].first, *this;
}
constexpr dense_set_local_iterator operator++(int) noexcept {
dense_set_local_iterator orig = *this;
return ++(*this), orig;
}
[[nodiscard]] constexpr pointer operator->() const noexcept {
return std::addressof(it[offset].second);
}
[[nodiscard]] constexpr reference operator*() const noexcept {
return *operator->();
}
[[nodiscard]] constexpr std::size_t index() const noexcept {
return offset;
}
private:
It it;
std::size_t offset;
};
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator==(const dense_set_local_iterator<ILhs> &lhs, const dense_set_local_iterator<IRhs> &rhs) noexcept {
return lhs.index() == rhs.index();
}
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator!=(const dense_set_local_iterator<ILhs> &lhs, const dense_set_local_iterator<IRhs> &rhs) noexcept {
return !(lhs == rhs);
}
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Associative container for unique objects of a given type.
*
* Internally, elements are organized into buckets. Which bucket an element is
* placed into depends entirely on its hash. Elements with the same hash code
* appear in the same bucket.
*
* @tparam Type Value type of the associative container.
* @tparam Hash Type of function to use to hash the values.
* @tparam KeyEqual Type of function to use to compare the values for equality.
* @tparam Allocator Type of allocator used to manage memory and elements.
*/
template<typename Type, typename Hash, typename KeyEqual, typename Allocator>
class dense_set {
static constexpr float default_threshold = 0.875f;
static constexpr std::size_t minimum_capacity = 8u;
using node_type = std::pair<std::size_t, Type>;
using alloc_traits = std::allocator_traits<Allocator>;
static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
template<typename Other>
[[nodiscard]] std::size_t value_to_bucket(const Other &value) const noexcept {
return fast_mod(sparse.second()(value), bucket_count());
}
template<typename Other>
[[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) {
for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
if(packed.second()(*it, value)) {
return begin() + static_cast<typename iterator::difference_type>(it.index());
}
}
return end();
}
template<typename Other>
[[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) const {
for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
if(packed.second()(*it, value)) {
return cbegin() + static_cast<typename iterator::difference_type>(it.index());
}
}
return cend();
}
template<typename Other>
[[nodiscard]] auto insert_or_do_nothing(Other &&value) {
const auto index = value_to_bucket(value);
if(auto it = constrained_find(value, index); it != end()) {
return std::make_pair(it, false);
}
packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value));
sparse.first()[index] = packed.first().size() - 1u;
rehash_if_required();
return std::make_pair(--end(), true);
}
void move_and_pop(const std::size_t pos) {
if(const auto last = size() - 1u; pos != last) {
size_type *curr = sparse.first().data() + value_to_bucket(packed.first().back().second);
packed.first()[pos] = std::move(packed.first().back());
for(; *curr != last; curr = &packed.first()[*curr].first) {}
*curr = pos;
}
packed.first().pop_back();
}
void rehash_if_required() {
if(size() > (bucket_count() * max_load_factor())) {
rehash(bucket_count() * 2u);
}
}
public:
/*! @brief Key type of the container. */
using key_type = Type;
/*! @brief Value type of the container. */
using value_type = Type;
/*! @brief Unsigned integer type. */
using size_type = std::size_t;
/*! @brief Type of function to use to hash the elements. */
using hasher = Hash;
/*! @brief Type of function to use to compare the elements for equality. */
using key_equal = KeyEqual;
/*! @brief Allocator type. */
using allocator_type = Allocator;
/*! @brief Random access iterator type. */
using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
/*! @brief Constant random access iterator type. */
using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
/*! @brief Forward iterator type. */
using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
/*! @brief Constant forward iterator type. */
using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>;
/*! @brief Default constructor. */
dense_set()
: dense_set{minimum_capacity} {}
/**
* @brief Constructs an empty container with a given allocator.
* @param allocator The allocator to use.
*/
explicit dense_set(const allocator_type &allocator)
: dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {}
/**
* @brief Constructs an empty container with a given allocator and user
* supplied minimal number of buckets.
* @param cnt Minimal number of buckets.
* @param allocator The allocator to use.
*/
dense_set(const size_type cnt, const allocator_type &allocator)
: dense_set{cnt, hasher{}, key_equal{}, allocator} {}
/**
* @brief Constructs an empty container with a given allocator, hash
* function and user supplied minimal number of buckets.
* @param cnt Minimal number of buckets.
* @param hash Hash function to use.
* @param allocator The allocator to use.
*/
dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator)
: dense_set{cnt, hash, key_equal{}, allocator} {}
/**
* @brief Constructs an empty container with a given allocator, hash
* function, compare function and user supplied minimal number of buckets.
* @param cnt Minimal number of buckets.
* @param hash Hash function to use.
* @param equal Compare function to use.
* @param allocator The allocator to use.
*/
explicit dense_set(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
: sparse{allocator, hash},
packed{allocator, equal},
threshold{default_threshold} {
rehash(cnt);
}
/*! @brief Default copy constructor. */
dense_set(const dense_set &) = default;
/**
* @brief Allocator-extended copy constructor.
* @param other The instance to copy from.
* @param allocator The allocator to use.
*/
dense_set(const dense_set &other, const allocator_type &allocator)
: sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
threshold{other.threshold} {}
/*! @brief Default move constructor. */
dense_set(dense_set &&) noexcept(std::is_nothrow_move_constructible_v<compressed_pair<sparse_container_type, hasher>> &&std::is_nothrow_move_constructible_v<compressed_pair<packed_container_type, key_equal>>) = default;
/**
* @brief Allocator-extended move constructor.
* @param other The instance to move from.
* @param allocator The allocator to use.
*/
dense_set(dense_set &&other, const allocator_type &allocator)
: sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
threshold{other.threshold} {}
/**
* @brief Default copy assignment operator.
* @return This container.
*/
dense_set &operator=(const dense_set &) = default;
/**
* @brief Default move assignment operator.
* @return This container.
*/
dense_set &operator=(dense_set &&) noexcept(std::is_nothrow_move_assignable_v<compressed_pair<sparse_container_type, hasher>> &&std::is_nothrow_move_assignable_v<compressed_pair<packed_container_type, key_equal>>) = default;
/**
* @brief Returns the associated allocator.
* @return The associated allocator.
*/
[[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
return sparse.first().get_allocator();
}
/**
* @brief Returns an iterator to the beginning.
*
* The returned iterator points to the first instance of the internal array.
* If the array is empty, the returned iterator will be equal to `end()`.
*
* @return An iterator to the first instance of the internal array.
*/
[[nodiscard]] const_iterator cbegin() const noexcept {
return packed.first().begin();
}
/*! @copydoc cbegin */
[[nodiscard]] const_iterator begin() const noexcept {
return cbegin();
}
/*! @copydoc begin */
[[nodiscard]] iterator begin() noexcept {
return packed.first().begin();
}
/**
* @brief Returns an iterator to the end.
*
* The returned iterator points to the element following the last instance
* of the internal array. Attempting to dereference the returned iterator
* results in undefined behavior.
*
* @return An iterator to the element following the last instance of the
* internal array.
*/
[[nodiscard]] const_iterator cend() const noexcept {
return packed.first().end();
}
/*! @copydoc cend */
[[nodiscard]] const_iterator end() const noexcept {
return cend();
}
/*! @copydoc end */
[[nodiscard]] iterator end() noexcept {
return packed.first().end();
}
/**
* @brief Checks whether a container is empty.
* @return True if the container is empty, false otherwise.
*/
[[nodiscard]] bool empty() const noexcept {
return packed.first().empty();
}
/**
* @brief Returns the number of elements in a container.
* @return Number of elements in a container.
*/
[[nodiscard]] size_type size() const noexcept {
return packed.first().size();
}
/**
* @brief Returns the maximum possible number of elements.
* @return Maximum possible number of elements.
*/
[[nodiscard]] size_type max_size() const noexcept {
return packed.first().max_size();
}
/*! @brief Clears the container. */
void clear() noexcept {
sparse.first().clear();
packed.first().clear();
rehash(0u);
}
/**
* @brief Inserts an element into the container, if it does not exist.
* @param value An element to insert into the container.
* @return A pair consisting of an iterator to the inserted element (or to
* the element that prevented the insertion) and a bool denoting whether the
* insertion took place.
*/
std::pair<iterator, bool> insert(const value_type &value) {
return insert_or_do_nothing(value);
}
/*! @copydoc insert */
std::pair<iterator, bool> insert(value_type &&value) {
return insert_or_do_nothing(std::move(value));
}
/**
* @brief Inserts elements into the container, if they do not exist.
* @tparam It Type of input iterator.
* @param first An iterator to the first element of the range of elements.
* @param last An iterator past the last element of the range of elements.
*/
template<typename It>
void insert(It first, It last) {
for(; first != last; ++first) {
insert(*first);
}
}
/**
* @brief Constructs an element in-place, if it does not exist.
*
* The element is also constructed when the container already has the key,
* in which case the newly constructed object is destroyed immediately.
*
* @tparam Args Types of arguments to forward to the constructor of the
* element.
* @param args Arguments to forward to the constructor of the element.
* @return A pair consisting of an iterator to the inserted element (or to
* the element that prevented the insertion) and a bool denoting whether the
* insertion took place.
*/
template<typename... Args>
std::pair<iterator, bool> emplace(Args &&...args) {
if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::decay_t<Args>, value_type>)) {
return insert_or_do_nothing(std::forward<Args>(args)...);
} else {
auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...));
const auto index = value_to_bucket(node.second);
if(auto it = constrained_find(node.second, index); it != end()) {
packed.first().pop_back();
return std::make_pair(it, false);
}
std::swap(node.first, sparse.first()[index]);
rehash_if_required();
return std::make_pair(--end(), true);
}
}
/**
* @brief Removes an element from a given position.
* @param pos An iterator to the element to remove.
* @return An iterator following the removed element.
*/
iterator erase(const_iterator pos) {
const auto diff = pos - cbegin();
erase(*pos);
return begin() + diff;
}
/**
* @brief Removes the given elements from a container.
* @param first An iterator to the first element of the range of elements.
* @param last An iterator past the last element of the range of elements.
* @return An iterator following the last removed element.
*/
iterator erase(const_iterator first, const_iterator last) {
const auto dist = first - cbegin();
for(auto from = last - cbegin(); from != dist; --from) {
erase(packed.first()[from - 1u].second);
}
return (begin() + dist);
}
/**
* @brief Removes the element associated with a given value.
* @param value Value of an element to remove.
* @return Number of elements removed (either 0 or 1).
*/
size_type erase(const value_type &value) {
for(size_type *curr = sparse.first().data() + value_to_bucket(value); *curr != (std::numeric_limits<size_type>::max)(); curr = &packed.first()[*curr].first) {
if(packed.second()(packed.first()[*curr].second, value)) {
const auto index = *curr;
*curr = packed.first()[*curr].first;
move_and_pop(index);
return 1u;
}
}
return 0u;
}
/**
* @brief Exchanges the contents with those of a given container.
* @param other Container to exchange the content with.
*/
void swap(dense_set &other) {
using std::swap;
swap(sparse, other.sparse);
swap(packed, other.packed);
swap(threshold, other.threshold);
}
/**
* @brief Returns the number of elements matching a value (either 1 or 0).
* @param key Key value of an element to search for.
* @return Number of elements matching the key (either 1 or 0).
*/
[[nodiscard]] size_type count(const value_type &key) const {
return find(key) != end();
}
/**
* @brief Returns the number of elements matching a key (either 1 or 0).
* @tparam Other Type of the key value of an element to search for.
* @param key Key value of an element to search for.
* @return Number of elements matching the key (either 1 or 0).
*/
template<typename Other>
[[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
count(const Other &key) const {
return find(key) != end();
}
/**
* @brief Finds an element with a given value.
* @param value Value of an element to search for.
* @return An iterator to an element with the given value. If no such
* element is found, a past-the-end iterator is returned.
*/
[[nodiscard]] iterator find(const value_type &value) {
return constrained_find(value, value_to_bucket(value));
}
/*! @copydoc find */
[[nodiscard]] const_iterator find(const value_type &value) const {
return constrained_find(value, value_to_bucket(value));
}
/**
* @brief Finds an element that compares _equivalent_ to a given value.
* @tparam Other Type of an element to search for.
* @param value Value of an element to search for.
* @return An iterator to an element with the given value. If no such
* element is found, a past-the-end iterator is returned.
*/
template<typename Other>
[[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
find(const Other &value) {
return constrained_find(value, value_to_bucket(value));
}
/*! @copydoc find */
template<typename Other>
[[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
find(const Other &value) const {
return constrained_find(value, value_to_bucket(value));
}
/**
* @brief Returns a range containing all elements with a given value.
* @param value Value of an element to search for.
* @return A pair of iterators pointing to the first element and past the
* last element of the range.
*/
[[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) {
const auto it = find(value);
return {it, it + !(it == end())};
}
/*! @copydoc equal_range */
[[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const {
const auto it = find(value);
return {it, it + !(it == cend())};
}
/**
* @brief Returns a range containing all elements that compare _equivalent_
* to a given value.
* @tparam Other Type of an element to search for.
* @param value Value of an element to search for.
* @return A pair of iterators pointing to the first element and past the
* last element of the range.
*/
template<typename Other>
[[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
equal_range(const Other &value) {
const auto it = find(value);
return {it, it + !(it == end())};
}
/*! @copydoc equal_range */
template<class Other>
[[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
equal_range(const Other &value) const {
const auto it = find(value);
return {it, it + !(it == cend())};
}
/**
* @brief Checks if the container contains an element with a given value.
* @param value Value of an element to search for.
* @return True if there is such an element, false otherwise.
*/
[[nodiscard]] bool contains(const value_type &value) const {
return (find(value) != cend());
}
/**
* @brief Checks if the container contains an element that compares
* _equivalent_ to a given value.
* @tparam Other Type of an element to search for.
* @param value Value of an element to search for.
* @return True if there is such an element, false otherwise.
*/
template<typename Other>
[[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
contains(const Other &value) const {
return (find(value) != cend());
}
/**
* @brief Returns an iterator to the beginning of a given bucket.
* @param index An index of a bucket to access.
* @return An iterator to the beginning of the given bucket.
*/
[[nodiscard]] const_local_iterator cbegin(const size_type index) const {
return {packed.first().begin(), sparse.first()[index]};
}
/**
* @brief Returns an iterator to the beginning of a given bucket.
* @param index An index of a bucket to access.
* @return An iterator to the beginning of the given bucket.
*/
[[nodiscard]] const_local_iterator begin(const size_type index) const {
return cbegin(index);
}
/**
* @brief Returns an iterator to the beginning of a given bucket.
* @param index An index of a bucket to access.
* @return An iterator to the beginning of the given bucket.
*/
[[nodiscard]] local_iterator begin(const size_type index) {
return {packed.first().begin(), sparse.first()[index]};
}
/**
* @brief Returns an iterator to the end of a given bucket.
* @param index An index of a bucket to access.
* @return An iterator to the end of the given bucket.
*/
[[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
return {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
}
/**
* @brief Returns an iterator to the end of a given bucket.
* @param index An index of a bucket to access.
* @return An iterator to the end of the given bucket.
*/
[[nodiscard]] const_local_iterator end(const size_type index) const {
return cend(index);
}
/**
* @brief Returns an iterator to the end of a given bucket.
* @param index An index of a bucket to access.
* @return An iterator to the end of the given bucket.
*/
[[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
return {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
}
/**
* @brief Returns the number of buckets.
* @return The number of buckets.
*/
[[nodiscard]] size_type bucket_count() const {
return sparse.first().size();
}
/**
* @brief Returns the maximum number of buckets.
* @return The maximum number of buckets.
*/
[[nodiscard]] size_type max_bucket_count() const {
return sparse.first().max_size();
}
/**
* @brief Returns the number of elements in a given bucket.
* @param index The index of the bucket to examine.
* @return The number of elements in the given bucket.
*/
[[nodiscard]] size_type bucket_size(const size_type index) const {
return static_cast<size_type>(std::distance(begin(index), end(index)));
}
/**
* @brief Returns the bucket for a given element.
* @param value The value of the element to examine.
* @return The bucket for the given element.
*/
[[nodiscard]] size_type bucket(const value_type &value) const {
return value_to_bucket(value);
}
/**
* @brief Returns the average number of elements per bucket.
* @return The average number of elements per bucket.
*/
[[nodiscard]] float load_factor() const {
return size() / static_cast<float>(bucket_count());
}
/**
* @brief Returns the maximum average number of elements per bucket.
* @return The maximum average number of elements per bucket.
*/
[[nodiscard]] float max_load_factor() const {
return threshold;
}
/**
* @brief Sets the desired maximum average number of elements per bucket.
* @param value A desired maximum average number of elements per bucket.
*/
void max_load_factor(const float value) {
ENTT_ASSERT(value > 0.f, "Invalid load factor");
threshold = value;
rehash(0u);
}
/**
* @brief Reserves at least the specified number of buckets and regenerates
* the hash table.
* @param cnt New number of buckets.
*/
void rehash(const size_type cnt) {
auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
const auto cap = static_cast<size_type>(size() / max_load_factor());
value = value > cap ? value : cap;
if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
sparse.first().resize(sz);
for(auto &&elem: sparse.first()) {
elem = std::numeric_limits<size_type>::max();
}
for(size_type pos{}, last = size(); pos < last; ++pos) {
const auto index = value_to_bucket(packed.first()[pos].second);
packed.first()[pos].first = std::exchange(sparse.first()[index], pos);
}
}
}
/**
* @brief Reserves space for at least the specified number of elements and
* regenerates the hash table.
* @param cnt New number of elements.
*/
void reserve(const size_type cnt) {
packed.first().reserve(cnt);
rehash(static_cast<size_type>(std::ceil(cnt / max_load_factor())));
}
/**
* @brief Returns the function used to hash the elements.
* @return The function used to hash the elements.
*/
[[nodiscard]] hasher hash_function() const {
return sparse.second();
}
/**
* @brief Returns the function used to compare elements for equality.
* @return The function used to compare elements for equality.
*/
[[nodiscard]] key_equal key_eq() const {
return packed.second();
}
private:
compressed_pair<sparse_container_type, hasher> sparse;
compressed_pair<packed_container_type, key_equal> packed;
float threshold;
};
} // namespace entt
#endif

View File

@@ -0,0 +1,26 @@
#ifndef ENTT_CONTAINER_FWD_HPP
#define ENTT_CONTAINER_FWD_HPP
#include <functional>
#include <memory>
namespace entt {
template<
typename Key,
typename Type,
typename = std::hash<Key>,
typename = std::equal_to<Key>,
typename = std::allocator<std::pair<const Key, Type>>>
class dense_map;
template<
typename Type,
typename = std::hash<Type>,
typename = std::equal_to<Type>,
typename = std::allocator<Type>>
class dense_set;
} // namespace entt
#endif

View File

@@ -1,18 +1,15 @@
#ifndef ENTT_CORE_ALGORITHM_HPP
#define ENTT_CORE_ALGORITHM_HPP
#include <vector>
#include <utility>
#include <iterator>
#include <algorithm>
#include <functional>
#include <iterator>
#include <utility>
#include <vector>
#include "utility.hpp"
namespace entt {
/**
* @brief Function object to wrap `std::sort` in a class type.
*
@@ -36,12 +33,11 @@ struct std_sort {
* @param args Arguments to forward to the sort function, if any.
*/
template<typename It, typename Compare = std::less<>, typename... Args>
void operator()(It first, It last, Compare compare = Compare{}, Args &&... args) const {
void operator()(It first, It last, Compare compare = Compare{}, Args &&...args) const {
std::sort(std::forward<Args>(args)..., std::move(first), std::move(last), std::move(compare));
}
};
/*! @brief Function object for performing insertion sort. */
struct insertion_sort {
/**
@@ -58,12 +54,12 @@ struct insertion_sort {
template<typename It, typename Compare = std::less<>>
void operator()(It first, It last, Compare compare = Compare{}) const {
if(first < last) {
for(auto it = first+1; it < last; ++it) {
for(auto it = first + 1; it < last; ++it) {
auto value = std::move(*it);
auto pre = it;
for(; pre > first && compare(value, *(pre-1)); --pre) {
*pre = std::move(*(pre-1));
for(; pre > first && compare(value, *(pre - 1)); --pre) {
*pre = std::move(*(pre - 1));
}
*pre = std::move(value);
@@ -72,7 +68,6 @@ struct insertion_sort {
}
};
/**
* @brief Function object for performing LSD radix sort.
* @tparam Bit Number of bits processed per pass.
@@ -80,7 +75,7 @@ struct insertion_sort {
*/
template<std::size_t Bit, std::size_t N>
struct radix_sort {
static_assert((N % Bit) == 0);
static_assert((N % Bit) == 0, "The maximum number of bits to sort must be a multiple of the number of bits processed per pass");
/**
* @brief Sorts the elements in a range.
@@ -111,17 +106,17 @@ struct radix_sort {
std::size_t index[buckets]{};
std::size_t count[buckets]{};
std::for_each(from, to, [&getter, &count, start](const value_type &item) {
++count[(getter(item) >> start) & mask];
});
for(auto it = from; it != to; ++it) {
++count[(getter(*it) >> start) & mask];
}
std::for_each(std::next(std::begin(index)), std::end(index), [index = std::begin(index), count = std::begin(count)](auto &item) mutable {
item = *(index++) + *(count++);
});
for(std::size_t pos{}, end = buckets - 1u; pos < end; ++pos) {
index[pos + 1u] = index[pos] + count[pos];
}
std::for_each(from, to, [&getter, &out, &index, start](value_type &item) {
out[index[(getter(item) >> start) & mask]++] = std::move(item);
});
for(auto it = from; it != to; ++it) {
out[index[(getter(*it) >> start) & mask]++] = std::move(*it);
}
};
for(std::size_t pass = 0; pass < (passes & ~1); pass += 2) {
@@ -137,8 +132,6 @@ struct radix_sort {
}
};
}
} // namespace entt
#endif

510
src/entt/core/any.hpp Normal file
View File

@@ -0,0 +1,510 @@
#ifndef ENTT_CORE_ANY_HPP
#define ENTT_CORE_ANY_HPP
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
#include "../config/config.h"
#include "../core/utility.hpp"
#include "fwd.hpp"
#include "type_info.hpp"
#include "type_traits.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
enum class any_operation : std::uint8_t {
copy,
move,
transfer,
assign,
destroy,
compare,
get
};
enum class any_policy : std::uint8_t {
owner,
ref,
cref
};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief A SBO friendly, type-safe container for single values of any type.
* @tparam Len Size of the storage reserved for the small buffer optimization.
* @tparam Align Optional alignment requirement.
*/
template<std::size_t Len, std::size_t Align>
class basic_any {
using operation = internal::any_operation;
using policy = internal::any_policy;
using vtable_type = const void *(const operation, const basic_any &, const void *);
struct storage_type {
alignas(Align) std::byte data[Len + !Len];
};
template<typename Type>
static constexpr bool in_situ = Len && alignof(Type) <= Align && sizeof(Type) <= Len &&std::is_nothrow_move_constructible_v<Type>;
template<typename Type>
static const void *basic_vtable(const operation op, const basic_any &value, const void *other) {
static_assert(!std::is_same_v<Type, void> && std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
const Type *element = nullptr;
if constexpr(in_situ<Type>) {
element = value.owner() ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance);
} else {
element = static_cast<const Type *>(value.instance);
}
switch(op) {
case operation::copy:
if constexpr(std::is_copy_constructible_v<Type>) {
static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*element);
}
break;
case operation::move:
if constexpr(in_situ<Type>) {
if(value.owner()) {
return new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(element))};
}
}
return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr));
case operation::transfer:
if constexpr(std::is_move_assignable_v<Type>) {
*const_cast<Type *>(element) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
return other;
}
[[fallthrough]];
case operation::assign:
if constexpr(std::is_copy_assignable_v<Type>) {
*const_cast<Type *>(element) = *static_cast<const Type *>(other);
return other;
}
break;
case operation::destroy:
if constexpr(in_situ<Type>) {
element->~Type();
} else if constexpr(std::is_array_v<Type>) {
delete[] element;
} else {
delete element;
}
break;
case operation::compare:
if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
return *element == *static_cast<const Type *>(other) ? other : nullptr;
} else {
return (element == other) ? other : nullptr;
}
case operation::get:
return element;
}
return nullptr;
}
template<typename Type, typename... Args>
void initialize([[maybe_unused]] Args &&...args) {
info = &type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
if constexpr(!std::is_void_v<Type>) {
vtable = basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
if constexpr(std::is_lvalue_reference_v<Type>) {
static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
mode = std::is_const_v<std::remove_reference_t<Type>> ? policy::cref : policy::ref;
instance = (std::addressof(args), ...);
} else if constexpr(in_situ<std::remove_cv_t<std::remove_reference_t<Type>>>) {
if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<std::remove_cv_t<std::remove_reference_t<Type>>>) {
new(&storage) std::remove_cv_t<std::remove_reference_t<Type>>{std::forward<Args>(args)...};
} else {
new(&storage) std::remove_cv_t<std::remove_reference_t<Type>>(std::forward<Args>(args)...);
}
} else {
if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<std::remove_cv_t<std::remove_reference_t<Type>>>) {
instance = new std::remove_cv_t<std::remove_reference_t<Type>>{std::forward<Args>(args)...};
} else {
instance = new std::remove_cv_t<std::remove_reference_t<Type>>(std::forward<Args>(args)...);
}
}
}
}
basic_any(const basic_any &other, const policy pol) noexcept
: instance{other.data()},
info{other.info},
vtable{other.vtable},
mode{pol} {}
public:
/*! @brief Size of the internal storage. */
static constexpr auto length = Len;
/*! @brief Alignment requirement. */
static constexpr auto alignment = Align;
/*! @brief Default constructor. */
constexpr basic_any() noexcept
: basic_any{std::in_place_type<void>} {}
/**
* @brief Constructs a wrapper by directly initializing the new object.
* @tparam Type Type of object to use to initialize the wrapper.
* @tparam Args Types of arguments to use to construct the new instance.
* @param args Parameters to use to construct the instance.
*/
template<typename Type, typename... Args>
explicit basic_any(std::in_place_type_t<Type>, Args &&...args)
: instance{},
info{},
vtable{},
mode{policy::owner} {
initialize<Type>(std::forward<Args>(args)...);
}
/**
* @brief Constructs a wrapper from a given value.
* @tparam Type Type of object to use to initialize the wrapper.
* @param value An instance of an object to use to initialize the wrapper.
*/
template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
basic_any(Type &&value)
: basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
/**
* @brief Copy constructor.
* @param other The instance to copy from.
*/
basic_any(const basic_any &other)
: basic_any{} {
if(other.vtable) {
other.vtable(operation::copy, other, this);
}
}
/**
* @brief Move constructor.
* @param other The instance to move from.
*/
basic_any(basic_any &&other) noexcept
: instance{},
info{other.info},
vtable{other.vtable},
mode{other.mode} {
if(other.vtable) {
other.vtable(operation::move, other, this);
}
}
/*! @brief Frees the internal storage, whatever it means. */
~basic_any() {
if(vtable && owner()) {
vtable(operation::destroy, *this, nullptr);
}
}
/**
* @brief Copy assignment operator.
* @param other The instance to copy from.
* @return This any object.
*/
basic_any &operator=(const basic_any &other) {
reset();
if(other.vtable) {
other.vtable(operation::copy, other, this);
}
return *this;
}
/**
* @brief Move assignment operator.
* @param other The instance to move from.
* @return This any object.
*/
basic_any &operator=(basic_any &&other) noexcept {
reset();
if(other.vtable) {
other.vtable(operation::move, other, this);
info = other.info;
vtable = other.vtable;
mode = other.mode;
}
return *this;
}
/**
* @brief Value assignment operator.
* @tparam Type Type of object to use to initialize the wrapper.
* @param value An instance of an object to use to initialize the wrapper.
* @return This any object.
*/
template<typename Type>
std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>, basic_any &>
operator=(Type &&value) {
emplace<std::decay_t<Type>>(std::forward<Type>(value));
return *this;
}
/**
* @brief Returns the object type if any, `type_id<void>()` otherwise.
* @return The object type if any, `type_id<void>()` otherwise.
*/
[[nodiscard]] const type_info &type() const noexcept {
return *info;
}
/**
* @brief Returns an opaque pointer to the contained instance.
* @return An opaque pointer the contained instance, if any.
*/
[[nodiscard]] const void *data() const noexcept {
return vtable ? vtable(operation::get, *this, nullptr) : nullptr;
}
/**
* @brief Returns an opaque pointer to the contained instance.
* @param req Expected type.
* @return An opaque pointer the contained instance, if any.
*/
[[nodiscard]] const void *data(const type_info &req) const noexcept {
return *info == req ? data() : nullptr;
}
/**
* @brief Returns an opaque pointer to the contained instance.
* @return An opaque pointer the contained instance, if any.
*/
[[nodiscard]] void *data() noexcept {
return mode == policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data());
}
/**
* @brief Returns an opaque pointer to the contained instance.
* @param req Expected type.
* @return An opaque pointer the contained instance, if any.
*/
[[nodiscard]] void *data(const type_info &req) noexcept {
return mode == policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data(req));
}
/**
* @brief Replaces the contained object by creating a new instance directly.
* @tparam Type Type of object to use to initialize the wrapper.
* @tparam Args Types of arguments to use to construct the new instance.
* @param args Parameters to use to construct the instance.
*/
template<typename Type, typename... Args>
void emplace(Args &&...args) {
reset();
initialize<Type>(std::forward<Args>(args)...);
}
/**
* @brief Assigns a value to the contained object without replacing it.
* @param other The value to assign to the contained object.
* @return True in case of success, false otherwise.
*/
bool assign(const basic_any &other) {
if(vtable && mode != policy::cref && *info == *other.info) {
return (vtable(operation::assign, *this, other.data()) != nullptr);
}
return false;
}
/*! @copydoc assign */
bool assign(basic_any &&other) {
if(vtable && mode != policy::cref && *info == *other.info) {
if(auto *val = other.data(); val) {
return (vtable(operation::transfer, *this, val) != nullptr);
} else {
return (vtable(operation::assign, *this, std::as_const(other).data()) != nullptr);
}
}
return false;
}
/*! @brief Destroys contained object */
void reset() {
if(vtable && owner()) {
vtable(operation::destroy, *this, nullptr);
}
// unnecessary but it helps to detect nasty bugs
ENTT_ASSERT((instance = nullptr) == nullptr, "");
info = &type_id<void>();
vtable = nullptr;
mode = policy::owner;
}
/**
* @brief Returns false if a wrapper is empty, true otherwise.
* @return False if the wrapper is empty, true otherwise.
*/
[[nodiscard]] explicit operator bool() const noexcept {
return vtable != nullptr;
}
/**
* @brief Checks if two wrappers differ in their content.
* @param other Wrapper with which to compare.
* @return False if the two objects differ in their content, true otherwise.
*/
[[nodiscard]] bool operator==(const basic_any &other) const noexcept {
if(vtable && *info == *other.info) {
return (vtable(operation::compare, *this, other.data()) != nullptr);
}
return (!vtable && !other.vtable);
}
/**
* @brief Checks if two wrappers differ in their content.
* @param other Wrapper with which to compare.
* @return True if the two objects differ in their content, false otherwise.
*/
[[nodiscard]] bool operator!=(const basic_any &other) const noexcept {
return !(*this == other);
}
/**
* @brief Aliasing constructor.
* @return A wrapper that shares a reference to an unmanaged object.
*/
[[nodiscard]] basic_any as_ref() noexcept {
return basic_any{*this, (mode == policy::cref ? policy::cref : policy::ref)};
}
/*! @copydoc as_ref */
[[nodiscard]] basic_any as_ref() const noexcept {
return basic_any{*this, policy::cref};
}
/**
* @brief Returns true if a wrapper owns its object, false otherwise.
* @return True if the wrapper owns its object, false otherwise.
*/
[[nodiscard]] bool owner() const noexcept {
return (mode == policy::owner);
}
private:
union {
const void *instance;
storage_type storage;
};
const type_info *info;
vtable_type *vtable;
policy mode;
};
/**
* @brief Performs type-safe access to the contained object.
* @tparam Type Type to which conversion is required.
* @tparam Len Size of the storage reserved for the small buffer optimization.
* @tparam Align Alignment requirement.
* @param data Target any object.
* @return The element converted to the requested type.
*/
template<typename Type, std::size_t Len, std::size_t Align>
Type any_cast(const basic_any<Len, Align> &data) noexcept {
const auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
ENTT_ASSERT(instance, "Invalid instance");
return static_cast<Type>(*instance);
}
/*! @copydoc any_cast */
template<typename Type, std::size_t Len, std::size_t Align>
Type any_cast(basic_any<Len, Align> &data) noexcept {
// forces const on non-reference types to make them work also with wrappers for const references
auto *const instance = any_cast<std::remove_reference_t<const Type>>(&data);
ENTT_ASSERT(instance, "Invalid instance");
return static_cast<Type>(*instance);
}
/*! @copydoc any_cast */
template<typename Type, std::size_t Len, std::size_t Align>
Type any_cast(basic_any<Len, Align> &&data) noexcept {
if constexpr(std::is_copy_constructible_v<std::remove_cv_t<std::remove_reference_t<Type>>>) {
if(auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); instance) {
return static_cast<Type>(std::move(*instance));
} else {
return any_cast<Type>(data);
}
} else {
auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
ENTT_ASSERT(instance, "Invalid instance");
return static_cast<Type>(std::move(*instance));
}
}
/*! @copydoc any_cast */
template<typename Type, std::size_t Len, std::size_t Align>
const Type *any_cast(const basic_any<Len, Align> *data) noexcept {
const auto &info = type_id<std::remove_cv_t<Type>>();
return static_cast<const Type *>(data->data(info));
}
/*! @copydoc any_cast */
template<typename Type, std::size_t Len, std::size_t Align>
Type *any_cast(basic_any<Len, Align> *data) noexcept {
if constexpr(std::is_const_v<Type>) {
// last attempt to make wrappers for const references return their values
return any_cast<Type>(&std::as_const(*data));
} else {
const auto &info = type_id<std::remove_cv_t<Type>>();
return static_cast<Type *>(data->data(info));
}
}
/**
* @brief Constructs a wrapper from a given type, passing it all arguments.
* @tparam Type Type of object to use to initialize the wrapper.
* @tparam Len Size of the storage reserved for the small buffer optimization.
* @tparam Align Optional alignment requirement.
* @tparam Args Types of arguments to use to construct the new instance.
* @param args Parameters to use to construct the instance.
* @return A properly initialized wrapper for an object of the given type.
*/
template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args>
basic_any<Len, Align> make_any(Args &&...args) {
return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...};
}
/**
* @brief Forwards its argument and avoids copies for lvalue references.
* @tparam Len Size of the storage reserved for the small buffer optimization.
* @tparam Align Optional alignment requirement.
* @tparam Type Type of argument to use to construct the new instance.
* @param value Parameter to use to construct the instance.
* @return A properly initialized and not necessarily owning wrapper.
*/
template<std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename Type>
basic_any<Len, Align> forward_as_any(Type &&value) {
return basic_any<Len, Align>{std::in_place_type<Type &&>, std::forward<Type>(value)};
}
} // namespace entt
#endif

View File

@@ -1,33 +1,30 @@
#ifndef ENTT_CORE_ATTRIBUTE_H
#define ENTT_CORE_ATTRIBUTE_H
#ifndef ENTT_EXPORT
# if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
# define ENTT_EXPORT __declspec(dllexport)
# define ENTT_IMPORT __declspec(dllimport)
# define ENTT_HIDDEN
# elif defined __GNUC__ && __GNUC__ >= 4
# define ENTT_EXPORT __attribute__((visibility("default")))
# define ENTT_IMPORT __attribute__((visibility("default")))
# define ENTT_HIDDEN __attribute__((visibility("hidden")))
# else /* Unsupported compiler */
# define ENTT_EXPORT
# define ENTT_IMPORT
# define ENTT_HIDDEN
# endif
# if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
# define ENTT_EXPORT __declspec(dllexport)
# define ENTT_IMPORT __declspec(dllimport)
# define ENTT_HIDDEN
# elif defined __GNUC__ && __GNUC__ >= 4
# define ENTT_EXPORT __attribute__((visibility("default")))
# define ENTT_IMPORT __attribute__((visibility("default")))
# define ENTT_HIDDEN __attribute__((visibility("hidden")))
# else /* Unsupported compiler */
# define ENTT_EXPORT
# define ENTT_IMPORT
# define ENTT_HIDDEN
# endif
#endif
#ifndef ENTT_API
# if defined ENTT_API_EXPORT
# define ENTT_API ENTT_EXPORT
# elif defined ENTT_API_IMPORT
# define ENTT_API ENTT_IMPORT
# else /* No API */
# define ENTT_API
# endif
# if defined ENTT_API_EXPORT
# define ENTT_API ENTT_EXPORT
# elif defined ENTT_API_IMPORT
# define ENTT_API ENTT_IMPORT
# else /* No API */
# define ENTT_API
# endif
#endif
#endif

View File

@@ -0,0 +1,279 @@
#ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
#define ENTT_CORE_COMPRESSED_PAIR_HPP
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>
#include "type_traits.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename Type, std::size_t, typename = void>
struct compressed_pair_element {
using reference = Type &;
using const_reference = const Type &;
template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<Type>>>
constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>)
: value{} {}
template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
: value{std::forward<Arg>(arg)} {}
template<typename... Args, std::size_t... Index>
constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
: value{std::forward<Args>(std::get<Index>(args))...} {}
[[nodiscard]] constexpr reference get() noexcept {
return value;
}
[[nodiscard]] constexpr const_reference get() const noexcept {
return value;
}
private:
Type value;
};
template<typename Type, std::size_t Tag>
struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
using reference = Type &;
using const_reference = const Type &;
using base_type = Type;
template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<base_type>>>
constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
: base_type{} {}
template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
: base_type{std::forward<Arg>(arg)} {}
template<typename... Args, std::size_t... Index>
constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
: base_type{std::forward<Args>(std::get<Index>(args))...} {}
[[nodiscard]] constexpr reference get() noexcept {
return *this;
}
[[nodiscard]] constexpr const_reference get() const noexcept {
return *this;
}
};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief A compressed pair.
*
* A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
* reduce its final size to a minimum.
*
* @tparam First The type of the first element that the pair stores.
* @tparam Second The type of the second element that the pair stores.
*/
template<typename First, typename Second>
class compressed_pair final
: internal::compressed_pair_element<First, 0u>,
internal::compressed_pair_element<Second, 1u> {
using first_base = internal::compressed_pair_element<First, 0u>;
using second_base = internal::compressed_pair_element<Second, 1u>;
public:
/*! @brief The type of the first element that the pair stores. */
using first_type = First;
/*! @brief The type of the second element that the pair stores. */
using second_type = Second;
/**
* @brief Default constructor, conditionally enabled.
*
* This constructor is only available when the types that the pair stores
* are both at least default constructible.
*
* @tparam Dummy Dummy template parameter used for internal purposes.
*/
template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> &&std::is_nothrow_default_constructible_v<second_base>)
: first_base{},
second_base{} {}
/**
* @brief Copy constructor.
* @param other The instance to copy from.
*/
constexpr compressed_pair(const compressed_pair &other) noexcept(std::is_nothrow_copy_constructible_v<first_base> &&std::is_nothrow_copy_constructible_v<second_base>) = default;
/**
* @brief Move constructor.
* @param other The instance to move from.
*/
constexpr compressed_pair(compressed_pair &&other) noexcept(std::is_nothrow_move_constructible_v<first_base> &&std::is_nothrow_move_constructible_v<second_base>) = default;
/**
* @brief Constructs a pair from its values.
* @tparam Arg Type of value to use to initialize the first element.
* @tparam Other Type of value to use to initialize the second element.
* @param arg Value to use to initialize the first element.
* @param other Value to use to initialize the second element.
*/
template<typename Arg, typename Other>
constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> &&std::is_nothrow_constructible_v<second_base, Other>)
: first_base{std::forward<Arg>(arg)},
second_base{std::forward<Other>(other)} {}
/**
* @brief Constructs a pair by forwarding the arguments to its parts.
* @tparam Args Types of arguments to use to initialize the first element.
* @tparam Other Types of arguments to use to initialize the second element.
* @param args Arguments to use to initialize the first element.
* @param other Arguments to use to initialize the second element.
*/
template<typename... Args, typename... Other>
constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> &&std::is_nothrow_constructible_v<second_base, Other...>)
: first_base{std::move(args), std::index_sequence_for<Args...>{}},
second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
/**
* @brief Copy assignment operator.
* @param other The instance to copy from.
* @return This compressed pair object.
*/
constexpr compressed_pair &operator=(const compressed_pair &other) noexcept(std::is_nothrow_copy_assignable_v<first_base> &&std::is_nothrow_copy_assignable_v<second_base>) = default;
/**
* @brief Move assignment operator.
* @param other The instance to move from.
* @return This compressed pair object.
*/
constexpr compressed_pair &operator=(compressed_pair &&other) noexcept(std::is_nothrow_move_assignable_v<first_base> &&std::is_nothrow_move_assignable_v<second_base>) = default;
/**
* @brief Returns the first element that a pair stores.
* @return The first element that a pair stores.
*/
[[nodiscard]] constexpr first_type &first() noexcept {
return static_cast<first_base &>(*this).get();
}
/*! @copydoc first */
[[nodiscard]] constexpr const first_type &first() const noexcept {
return static_cast<const first_base &>(*this).get();
}
/**
* @brief Returns the second element that a pair stores.
* @return The second element that a pair stores.
*/
[[nodiscard]] constexpr second_type &second() noexcept {
return static_cast<second_base &>(*this).get();
}
/*! @copydoc second */
[[nodiscard]] constexpr const second_type &second() const noexcept {
return static_cast<const second_base &>(*this).get();
}
/**
* @brief Swaps two compressed pair objects.
* @param other The compressed pair to swap with.
*/
constexpr void swap(compressed_pair &other) noexcept(std::is_nothrow_swappable_v<first_type> &&std::is_nothrow_swappable_v<second_type>) {
using std::swap;
swap(first(), other.first());
swap(second(), other.second());
}
/**
* @brief Extracts an element from the compressed pair.
* @tparam Index An integer value that is either 0 or 1.
* @return Returns a reference to the first element if `Index` is 0 and a
* reference to the second element if `Index` is 1.
*/
template<std::size_t Index>
constexpr decltype(auto) get() noexcept {
if constexpr(Index == 0u) {
return first();
} else {
static_assert(Index == 1u, "Index out of bounds");
return second();
}
}
/*! @copydoc get */
template<std::size_t Index>
constexpr decltype(auto) get() const noexcept {
if constexpr(Index == 0u) {
return first();
} else {
static_assert(Index == 1u, "Index out of bounds");
return second();
}
}
};
/**
* @brief Deduction guide.
* @tparam Type Type of value to use to initialize the first element.
* @tparam Other Type of value to use to initialize the second element.
*/
template<typename Type, typename Other>
compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
/**
* @brief Swaps two compressed pair objects.
* @tparam First The type of the first element that the pairs store.
* @tparam Second The type of the second element that the pairs store.
* @param lhs A valid compressed pair object.
* @param rhs A valid compressed pair object.
*/
template<typename First, typename Second>
inline constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) {
lhs.swap(rhs);
}
} // namespace entt
// disable structured binding support for clang 6, it messes when specializing tuple_size
#if !defined __clang_major__ || __clang_major__ > 6
namespace std {
/**
* @brief `std::tuple_size` specialization for `compressed_pair`s.
* @tparam First The type of the first element that the pair stores.
* @tparam Second The type of the second element that the pair stores.
*/
template<typename First, typename Second>
struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
/**
* @brief `std::tuple_element` specialization for `compressed_pair`s.
* @tparam Index The index of the type to return.
* @tparam First The type of the first element that the pair stores.
* @tparam Second The type of the second element that the pair stores.
*/
template<size_t Index, typename First, typename Second>
struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
static_assert(Index < 2u, "Index out of bounds");
};
} // namespace std
#endif
#endif

97
src/entt/core/enum.hpp Normal file
View File

@@ -0,0 +1,97 @@
#ifndef ENTT_CORE_ENUM_HPP
#define ENTT_CORE_ENUM_HPP
#include <type_traits>
namespace entt {
/**
* @brief Enable bitmask support for enum classes.
* @tparam Type The enum type for which to enable bitmask support.
*/
template<typename Type, typename = void>
struct enum_as_bitmask: std::false_type {};
/*! @copydoc enum_as_bitmask */
template<typename Type>
struct enum_as_bitmask<Type, std::void_t<decltype(Type::_entt_enum_as_bitmask)>>: std::is_enum<Type> {};
/**
* @brief Helper variable template.
* @tparam Type The enum class type for which to enable bitmask support.
*/
template<typename Type>
inline constexpr bool enum_as_bitmask_v = enum_as_bitmask<Type>::value;
} // namespace entt
/**
* @brief Operator available for enums for which bitmask support is enabled.
* @tparam Type Enum class type.
* @param lhs The first value to use.
* @param rhs The second value to use.
* @return The result of invoking the operator on the underlying types of the
* two values provided.
*/
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
operator|(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) | static_cast<std::underlying_type_t<Type>>(rhs));
}
/*! @copydoc operator| */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
operator&(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) & static_cast<std::underlying_type_t<Type>>(rhs));
}
/*! @copydoc operator| */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
operator^(const Type lhs, const Type rhs) noexcept {
return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) ^ static_cast<std::underlying_type_t<Type>>(rhs));
}
/**
* @brief Operator available for enums for which bitmask support is enabled.
* @tparam Type Enum class type.
* @param value The value to use.
* @return The result of invoking the operator on the underlying types of the
* value provided.
*/
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
operator~(const Type value) noexcept {
return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value));
}
/*! @copydoc operator~ */
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, bool>
operator!(const Type value) noexcept {
return !static_cast<std::underlying_type_t<Type>>(value);
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
operator|=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs | rhs));
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
operator&=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs & rhs));
}
/*! @copydoc operator| */
template<typename Type>
constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
operator^=(Type &lhs, const Type rhs) noexcept {
return (lhs = (lhs ^ rhs));
}
#endif

View File

@@ -1,13 +1,11 @@
#ifndef ENTT_CORE_FAMILY_HPP
#define ENTT_CORE_FAMILY_HPP
#include "../config/config.h"
#include "fwd.hpp"
namespace entt {
/**
* @brief Dynamic identifier generator.
*
@@ -17,20 +15,18 @@ namespace entt {
*/
template<typename...>
class family {
inline static ENTT_MAYBE_ATOMIC(ENTT_ID_TYPE) identifier{};
inline static ENTT_MAYBE_ATOMIC(id_type) identifier{};
public:
/*! @brief Unsigned integer type. */
using family_type = ENTT_ID_TYPE;
using value_type = id_type;
/*! @brief Statically generated unique identifier for the given type. */
template<typename... Type>
// at the time I'm writing, clang crashes during compilation if auto is used instead of family_type
inline static const family_type type = identifier++;
inline static const value_type value = identifier++;
};
}
} // namespace entt
#endif

20
src/entt/core/fwd.hpp Normal file
View File

@@ -0,0 +1,20 @@
#ifndef ENTT_CORE_FWD_HPP
#define ENTT_CORE_FWD_HPP
#include <cstddef>
#include "../config/config.h"
namespace entt {
template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
class basic_any;
/*! @brief Alias declaration for type identifiers. */
using id_type = ENTT_ID_TYPE;
/*! @brief Alias declaration for the most common use case. */
using any = basic_any<>;
} // namespace entt
#endif

View File

@@ -1,28 +1,22 @@
#ifndef ENTT_CORE_HASHED_STRING_HPP
#define ENTT_CORE_HASHED_STRING_HPP
#include <cstddef>
#include <cstdint>
#include "../config/config.h"
#include "fwd.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename>
struct fnv1a_traits;
template<>
struct fnv1a_traits<std::uint32_t> {
using type = std::uint32_t;
@@ -30,7 +24,6 @@ struct fnv1a_traits<std::uint32_t> {
static constexpr std::uint32_t prime = 16777619;
};
template<>
struct fnv1a_traits<std::uint64_t> {
using type = std::uint64_t;
@@ -38,72 +31,101 @@ struct fnv1a_traits<std::uint64_t> {
static constexpr std::uint64_t prime = 1099511628211ull;
};
template<typename Char>
struct basic_hashed_string {
using value_type = Char;
using size_type = std::size_t;
using hash_type = id_type;
}
const value_type *repr;
size_type length;
hash_type hash;
};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond TURN_OFF_DOXYGEN
* @endcond
*/
/**
* @brief Zero overhead unique identifier.
*
* A hashed string is a compile-time tool that allows users to use
* human-readable identifers in the codebase while using their numeric
* human-readable identifiers in the codebase while using their numeric
* counterparts at runtime.<br/>
* Because of that, a hashed string can also be used in constant expressions if
* required.
*
* @warning
* This class doesn't take ownership of user-supplied strings nor does it make a
* copy of them.
*
* @tparam Char Character type.
*/
template<typename Char>
class basic_hashed_string {
using traits_type = internal::fnv1a_traits<ENTT_ID_TYPE>;
class basic_hashed_string: internal::basic_hashed_string<Char> {
using base_type = internal::basic_hashed_string<Char>;
using hs_traits = internal::fnv1a_traits<id_type>;
struct const_wrapper {
// non-explicit constructor on purpose
constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
const Char *str;
constexpr const_wrapper(const Char *str) noexcept
: repr{str} {}
const Char *repr;
};
// FowlerNollVo hash function v. 1a - the good
static constexpr ENTT_ID_TYPE helper(const Char *curr) ENTT_NOEXCEPT {
auto value = traits_type::offset;
[[nodiscard]] static constexpr auto helper(const Char *str) noexcept {
base_type base{str, 0u, hs_traits::offset};
while(*curr != 0) {
value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
for(; str[base.length]; ++base.length) {
base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
}
return value;
return base;
}
// FowlerNollVo hash function v. 1a - the good
[[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) noexcept {
base_type base{str, len, hs_traits::offset};
for(size_type pos{}; pos < len; ++pos) {
base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
}
return base;
}
public:
/*! @brief Character type. */
using value_type = Char;
using value_type = typename base_type::value_type;
/*! @brief Unsigned integer type. */
using hash_type = ENTT_ID_TYPE;
using size_type = typename base_type::size_type;
/*! @brief Unsigned integer type. */
using hash_type = typename base_type::hash_type;
/**
* @brief Returns directly the numeric representation of a string view.
* @param str Human-readable identifier.
* @param len Length of the string to hash.
* @return The numeric representation of the string.
*/
[[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
return basic_hashed_string{str, len};
}
/**
* @brief Returns directly the numeric representation of a string.
*
* Forcing template resolution avoids implicit conversions. An
* human-readable identifier can be anything but a plain, old bunch of
* characters.<br/>
* Example of use:
* @code{.cpp}
* const auto value = basic_hashed_string<char>::to_value("my.png");
* @endcode
*
* @tparam N Number of characters of the identifier.
* @param str Human-readable identifer.
* @param str Human-readable identifier.
* @return The numeric representation of the string.
*/
template<std::size_t N>
static constexpr hash_type value(const value_type (&str)[N]) ENTT_NOEXCEPT {
return helper(str);
[[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) noexcept {
return basic_hashed_string{str};
}
/**
@@ -111,109 +133,98 @@ public:
* @param wrapper Helps achieving the purpose by relying on overloading.
* @return The numeric representation of the string.
*/
static hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
return helper(wrapper.str);
}
/**
* @brief Returns directly the numeric representation of a string view.
* @param str Human-readable identifer.
* @param size Length of the string to hash.
* @return The numeric representation of the string.
*/
static hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
ENTT_ID_TYPE partial{traits_type::offset};
while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
return partial;
[[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
return basic_hashed_string{wrapper};
}
/*! @brief Constructs an empty hashed string. */
constexpr basic_hashed_string() ENTT_NOEXCEPT
: str{nullptr}, hash{}
{}
constexpr basic_hashed_string() noexcept
: base_type{} {}
/**
* @brief Constructs a hashed string from a string view.
* @param str Human-readable identifier.
* @param len Length of the string to hash.
*/
constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
: base_type{helper(str, len)} {}
/**
* @brief Constructs a hashed string from an array of const characters.
*
* Forcing template resolution avoids implicit conversions. An
* human-readable identifier can be anything but a plain, old bunch of
* characters.<br/>
* Example of use:
* @code{.cpp}
* basic_hashed_string<char> hs{"my.png"};
* @endcode
*
* @tparam N Number of characters of the identifier.
* @param curr Human-readable identifer.
* @param str Human-readable identifier.
*/
template<std::size_t N>
constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
: str{curr}, hash{helper(curr)}
{}
constexpr basic_hashed_string(const value_type (&str)[N]) noexcept
: base_type{helper(str)} {}
/**
* @brief Explicit constructor on purpose to avoid constructing a hashed
* string directly from a `const value_type *`.
*
* @warning
* The lifetime of the string is not extended nor is it copied.
*
* @param wrapper Helps achieving the purpose by relying on overloading.
*/
explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
: str{wrapper.str}, hash{helper(wrapper.str)}
{}
explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
: base_type{helper(wrapper.repr)} {}
/**
* @brief Returns the size a hashed string.
* @return The size of the hashed string.
*/
[[nodiscard]] constexpr size_type size() const noexcept {
return base_type::length;
}
/**
* @brief Returns the human-readable representation of a hashed string.
* @return The string used to initialize the instance.
* @return The string used to initialize the hashed string.
*/
constexpr const value_type * data() const ENTT_NOEXCEPT {
return str;
[[nodiscard]] constexpr const value_type *data() const noexcept {
return base_type::repr;
}
/**
* @brief Returns the numeric representation of a hashed string.
* @return The numeric representation of the instance.
* @return The numeric representation of the hashed string.
*/
constexpr hash_type value() const ENTT_NOEXCEPT {
return hash;
[[nodiscard]] constexpr hash_type value() const noexcept {
return base_type::hash;
}
/*! @copydoc data */
constexpr operator const value_type *() const ENTT_NOEXCEPT { return data(); }
[[nodiscard]] constexpr operator const value_type *() const noexcept {
return data();
}
/**
* @brief Returns the numeric representation of a hashed string.
* @return The numeric representation of the instance.
* @return The numeric representation of the hashed string.
*/
constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
/**
* @brief Compares two hashed strings.
* @param other Hashed string with which to compare.
* @return True if the two hashed strings are identical, false otherwise.
*/
constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
return hash == other.hash;
[[nodiscard]] constexpr operator hash_type() const noexcept {
return value();
}
private:
const value_type *str;
hash_type hash;
};
/**
* @brief Deduction guide.
*
* It allows to deduce the character type of the hashed string directly from a
* human-readable identifer provided to the constructor.
*
* @tparam Char Character type.
* @param str Human-readable identifier.
* @param len Length of the string to hash.
*/
template<typename Char>
basic_hashed_string(const Char *str, const std::size_t len) -> basic_hashed_string<Char>;
/**
* @brief Deduction guide.
* @tparam Char Character type.
* @tparam N Number of characters of the identifier.
* @param str Human-readable identifer.
* @param str Human-readable identifier.
*/
template<typename Char, std::size_t N>
basic_hashed_string(const Char (&str)[N]) ENTT_NOEXCEPT
-> basic_hashed_string<Char>;
basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
/**
* @brief Compares two hashed strings.
@@ -223,40 +234,101 @@ basic_hashed_string(const Char (&str)[N]) ENTT_NOEXCEPT
* @return True if the two hashed strings are identical, false otherwise.
*/
template<typename Char>
constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
[[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
return lhs.value() == rhs.value();
}
/**
* @brief Compares two hashed strings.
* @tparam Char Character type.
* @param lhs A valid hashed string.
* @param rhs A valid hashed string.
* @return True if the two hashed strings differ, false otherwise.
*/
template<typename Char>
[[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
return !(lhs == rhs);
}
/**
* @brief Compares two hashed strings.
* @tparam Char Character type.
* @param lhs A valid hashed string.
* @param rhs A valid hashed string.
* @return True if the first element is less than the second, false otherwise.
*/
template<typename Char>
[[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
return lhs.value() < rhs.value();
}
/**
* @brief Compares two hashed strings.
* @tparam Char Character type.
* @param lhs A valid hashed string.
* @param rhs A valid hashed string.
* @return True if the first element is less than or equal to the second, false
* otherwise.
*/
template<typename Char>
[[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
return !(rhs < lhs);
}
/**
* @brief Compares two hashed strings.
* @tparam Char Character type.
* @param lhs A valid hashed string.
* @param rhs A valid hashed string.
* @return True if the first element is greater than the second, false
* otherwise.
*/
template<typename Char>
[[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
return rhs < lhs;
}
/**
* @brief Compares two hashed strings.
* @tparam Char Character type.
* @param lhs A valid hashed string.
* @param rhs A valid hashed string.
* @return True if the first element is greater than or equal to the second,
* false otherwise.
*/
template<typename Char>
[[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
return !(lhs < rhs);
}
/*! @brief Aliases for common character types. */
using hashed_string = basic_hashed_string<char>;
/*! @brief Aliases for common character types. */
using hashed_wstring = basic_hashed_string<wchar_t>;
}
inline namespace literals {
/**
* @brief User defined literal for hashed strings.
* @param str The literal without its suffix.
* @return A properly initialized hashed string.
*/
constexpr entt::hashed_string operator"" ENTT_HS_SUFFIX(const char *str, std::size_t) ENTT_NOEXCEPT {
return entt::hashed_string{str};
[[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) noexcept {
return hashed_string{str};
}
/**
* @brief User defined literal for hashed wstrings.
* @param str The literal without its suffix.
* @return A properly initialized hashed wstring.
*/
constexpr entt::hashed_wstring operator"" ENTT_HWS_SUFFIX(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
return entt::hashed_wstring{str};
[[nodiscard]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) noexcept {
return hashed_wstring{str};
}
} // namespace literals
} // namespace entt
#endif

View File

@@ -1,65 +1,35 @@
#ifndef ENTT_CORE_IDENT_HPP
#define ENTT_CORE_IDENT_HPP
#include <tuple>
#include <cstddef>
#include <utility>
#include <type_traits>
#include "../config/config.h"
#include <utility>
#include "fwd.hpp"
#include "type_traits.hpp"
namespace entt {
/**
* @brief Types identifiers.
*
* Variable template used to generate identifiers at compile-time for the given
* types. Use the `get` member function to know what's the identifier associated
* to the specific type.
*
* @note
* Identifiers are constant expression and can be used in any context where such
* an expression is required. As an example:
* @code{.cpp}
* using id = entt::identifier<a_type, another_type>;
*
* switch(a_type_identifier) {
* case id::type<a_type>:
* // ...
* break;
* case id::type<another_type>:
* // ...
* break;
* default:
* // ...
* }
* @endcode
*
* @tparam Types List of types for which to generate identifiers.
* @brief Type integral identifiers.
* @tparam Type List of types for which to generate identifiers.
*/
template<typename... Types>
class identifier {
using tuple_type = std::tuple<std::decay_t<Types>...>;
template<typename Type, std::size_t... Indexes>
static constexpr ENTT_ID_TYPE get(std::index_sequence<Indexes...>) {
static_assert(std::disjunction_v<std::is_same<Type, Types>...>);
return (0 + ... + (std::is_same_v<Type, std::tuple_element_t<Indexes, tuple_type>> ? ENTT_ID_TYPE(Indexes) : ENTT_ID_TYPE{}));
template<typename... Type>
class ident {
template<typename Curr, std::size_t... Index>
[[nodiscard]] static constexpr id_type get(std::index_sequence<Index...>) noexcept {
static_assert((std::is_same_v<Curr, Type> || ...), "Invalid type");
return (0 + ... + (std::is_same_v<Curr, type_list_element_t<Index, type_list<std::decay_t<Type>...>>> ? id_type{Index} : id_type{}));
}
public:
/*! @brief Unsigned integer type. */
using identifier_type = ENTT_ID_TYPE;
using value_type = id_type;
/*! @brief Statically generated unique identifier for the given type. */
template<typename Type>
static constexpr identifier_type type = get<std::decay_t<Type>>(std::index_sequence_for<Types...>{});
template<typename Curr>
static constexpr value_type value = get<std::decay_t<Curr>>(std::index_sequence_for<Type...>{});
};
}
} // namespace entt
#endif

197
src/entt/core/iterator.hpp Normal file
View File

@@ -0,0 +1,197 @@
#ifndef ENTT_CORE_ITERATOR_HPP
#define ENTT_CORE_ITERATOR_HPP
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
namespace entt {
/**
* @brief Helper type to use as pointer with input iterators.
* @tparam Type of wrapped value.
*/
template<typename Type>
struct input_iterator_pointer final {
/*! @brief Value type. */
using value_type = Type;
/*! @brief Pointer type. */
using pointer = Type *;
/*! @brief Reference type. */
using reference = Type &;
/**
* @brief Constructs a proxy object by move.
* @param val Value to use to initialize the proxy object.
*/
constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
: value{std::move(val)} {}
/**
* @brief Access operator for accessing wrapped values.
* @return A pointer to the wrapped value.
*/
[[nodiscard]] constexpr pointer operator->() noexcept {
return std::addressof(value);
}
/**
* @brief Dereference operator for accessing wrapped values.
* @return A reference to the wrapped value.
*/
[[nodiscard]] constexpr reference operator*() noexcept {
return value;
}
private:
Type value;
};
/**
* @brief Plain iota iterator (waiting for C++20).
* @tparam Type Value type.
*/
template<typename Type>
class iota_iterator final {
static_assert(std::is_integral_v<Type>, "Not an integral type");
public:
/*! @brief Value type, likely an integral one. */
using value_type = Type;
/*! @brief Invalid pointer type. */
using pointer = void;
/*! @brief Non-reference type, same as value type. */
using reference = value_type;
/*! @brief Difference type. */
using difference_type = std::ptrdiff_t;
/*! @brief Iterator category. */
using iterator_category = std::input_iterator_tag;
/*! @brief Default constructor. */
constexpr iota_iterator() noexcept
: current{} {}
/**
* @brief Constructs an iota iterator from a given value.
* @param init The initial value assigned to the iota iterator.
*/
constexpr iota_iterator(const value_type init) noexcept
: current{init} {}
/**
* @brief Pre-increment operator.
* @return This iota iterator.
*/
constexpr iota_iterator &operator++() noexcept {
return ++current, *this;
}
/**
* @brief Post-increment operator.
* @return This iota iterator.
*/
constexpr iota_iterator operator++(int) noexcept {
iota_iterator orig = *this;
return ++(*this), orig;
}
/**
* @brief Dereference operator.
* @return The underlying value.
*/
[[nodiscard]] constexpr reference operator*() const noexcept {
return current;
}
private:
value_type current;
};
/**
* @brief Comparison operator.
* @tparam Type Value type of the iota iterator.
* @param lhs A properly initialized iota iterator.
* @param rhs A properly initialized iota iterator.
* @return True if the two iterators are identical, false otherwise.
*/
template<typename Type>
[[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
return *lhs == *rhs;
}
/**
* @brief Comparison operator.
* @tparam Type Value type of the iota iterator.
* @param lhs A properly initialized iota iterator.
* @param rhs A properly initialized iota iterator.
* @return True if the two iterators differ, false otherwise.
*/
template<typename Type>
[[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
return !(lhs == rhs);
}
/**
* @brief Utility class to create an iterable object from a pair of iterators.
* @tparam It Type of iterator.
* @tparam Sentinel Type of sentinel.
*/
template<typename It, typename Sentinel = It>
struct iterable_adaptor final {
/*! @brief Value type. */
using value_type = typename std::iterator_traits<It>::value_type;
/*! @brief Iterator type. */
using iterator = It;
/*! @brief Sentinel type. */
using sentinel = Sentinel;
/*! @brief Default constructor. */
constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> &&std::is_nothrow_default_constructible_v<sentinel>)
: first{},
last{} {}
/**
* @brief Creates an iterable object from a pair of iterators.
* @param from Begin iterator.
* @param to End iterator.
*/
constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> &&std::is_nothrow_move_constructible_v<sentinel>)
: first{std::move(from)},
last{std::move(to)} {}
/**
* @brief Returns an iterator to the beginning.
* @return An iterator to the first element of the range.
*/
[[nodiscard]] constexpr iterator begin() const noexcept {
return first;
}
/**
* @brief Returns an iterator to the end.
* @return An iterator to the element following the last element of the
* range.
*/
[[nodiscard]] constexpr sentinel end() const noexcept {
return last;
}
/*! @copydoc begin */
[[nodiscard]] constexpr iterator cbegin() const noexcept {
return begin();
}
/*! @copydoc end */
[[nodiscard]] constexpr sentinel cend() const noexcept {
return end();
}
private:
It first;
Sentinel last;
};
} // namespace entt
#endif

289
src/entt/core/memory.hpp Normal file
View File

@@ -0,0 +1,289 @@
#ifndef ENTT_CORE_MEMORY_HPP
#define ENTT_CORE_MEMORY_HPP
#include <cstddef>
#include <limits>
#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>
#include "../config/config.h"
namespace entt {
/**
* @brief Checks whether a value is a power of two or not.
* @param value A value that may or may not be a power of two.
* @return True if the value is a power of two, false otherwise.
*/
[[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) noexcept {
return value && ((value & (value - 1)) == 0);
}
/**
* @brief Computes the smallest power of two greater than or equal to a value.
* @param value The value to use.
* @return The smallest power of two greater than or equal to the given value.
*/
[[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) noexcept {
ENTT_ASSERT_CONSTEXPR(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
std::size_t curr = value - (value != 0u);
for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
curr |= curr >> next;
}
return ++curr;
}
/**
* @brief Fast module utility function (powers of two only).
* @param value A value for which to calculate the modulus.
* @param mod _Modulus_, it must be a power of two.
* @return The common remainder.
*/
[[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) noexcept {
ENTT_ASSERT_CONSTEXPR(is_power_of_two(mod), "Value must be a power of two");
return value & (mod - 1u);
}
/**
* @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
* @tparam Type Pointer type.
* @param ptr Fancy or raw pointer.
* @return A raw pointer that represents the address of the original pointer.
*/
template<typename Type>
[[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
return ptr;
} else {
return to_address(std::forward<Type>(ptr).operator->());
}
}
/**
* @brief Utility function to design allocation-aware containers.
* @tparam Allocator Type of allocator.
* @param lhs A valid allocator.
* @param rhs Another valid allocator.
*/
template<typename Allocator>
constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
lhs = rhs;
}
}
/**
* @brief Utility function to design allocation-aware containers.
* @tparam Allocator Type of allocator.
* @param lhs A valid allocator.
* @param rhs Another valid allocator.
*/
template<typename Allocator>
constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
lhs = std::move(rhs);
}
}
/**
* @brief Utility function to design allocation-aware containers.
* @tparam Allocator Type of allocator.
* @param lhs A valid allocator.
* @param rhs Another valid allocator.
*/
template<typename Allocator>
constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
using std::swap;
swap(lhs, rhs);
} else {
ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
}
}
/**
* @brief Deleter for allocator-aware unique pointers (waiting for C++20).
* @tparam Args Types of arguments to use to construct the object.
*/
template<typename Allocator>
struct allocation_deleter: private Allocator {
/*! @brief Allocator type. */
using allocator_type = Allocator;
/*! @brief Pointer type. */
using pointer = typename std::allocator_traits<Allocator>::pointer;
/**
* @brief Inherited constructors.
* @param alloc The allocator to use.
*/
constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
: Allocator{alloc} {}
/**
* @brief Destroys the pointed object and deallocates its memory.
* @param ptr A valid pointer to an object of the given type.
*/
constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
using alloc_traits = typename std::allocator_traits<Allocator>;
alloc_traits::destroy(*this, to_address(ptr));
alloc_traits::deallocate(*this, ptr, 1u);
}
};
/**
* @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
* @tparam Type Type of object to allocate for and to construct.
* @tparam Allocator Type of allocator used to manage memory and elements.
* @tparam Args Types of arguments to use to construct the object.
* @param allocator The allocator to use.
* @param args Parameters to use to construct the object.
* @return A properly initialized unique pointer with a custom deleter.
*/
template<typename Type, typename Allocator, typename... Args>
ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
static_assert(!std::is_array_v<Type>, "Array types are not supported");
using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
using allocator_type = typename alloc_traits::allocator_type;
allocator_type alloc{allocator};
auto ptr = alloc_traits::allocate(alloc, 1u);
ENTT_TRY {
alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
}
ENTT_CATCH {
alloc_traits::deallocate(alloc, ptr, 1u);
ENTT_THROW;
}
return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
}
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename Type>
struct uses_allocator_construction {
template<typename Allocator, typename... Params>
static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
return std::forward_as_tuple(std::forward<Params>(params)...);
} else {
static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
} else {
static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
}
}
}
};
template<typename Type, typename Other>
struct uses_allocator_construction<std::pair<Type, Other>> {
using type = std::pair<Type, Other>;
template<typename Allocator, typename First, typename Second>
static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
return std::make_tuple(
std::piecewise_construct,
std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
}
template<typename Allocator>
static constexpr auto args(const Allocator &allocator) noexcept {
return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
}
template<typename Allocator, typename First, typename Second>
static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
}
template<typename Allocator, typename First, typename Second>
static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
}
template<typename Allocator, typename First, typename Second>
static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
}
};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Uses-allocator construction utility (waiting for C++20).
*
* Primarily intended for internal use. Prepares the argument list needed to
* create an object of a given type by means of uses-allocator construction.
*
* @tparam Type Type to return arguments for.
* @tparam Allocator Type of allocator used to manage memory and elements.
* @tparam Args Types of arguments to use to construct the object.
* @param allocator The allocator to use.
* @param args Parameters to use to construct the object.
* @return The arguments needed to create an object of the given type.
*/
template<typename Type, typename Allocator, typename... Args>
constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
}
/**
* @brief Uses-allocator construction utility (waiting for C++20).
*
* Primarily intended for internal use. Creates an object of a given type by
* means of uses-allocator construction.
*
* @tparam Type Type of object to create.
* @tparam Allocator Type of allocator used to manage memory and elements.
* @tparam Args Types of arguments to use to construct the object.
* @param allocator The allocator to use.
* @param args Parameters to use to construct the object.
* @return A newly created object of the given type.
*/
template<typename Type, typename Allocator, typename... Args>
constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
}
/**
* @brief Uses-allocator construction utility (waiting for C++20).
*
* Primarily intended for internal use. Creates an object of a given type by
* means of uses-allocator construction at an uninitialized memory location.
*
* @tparam Type Type of object to create.
* @tparam Allocator Type of allocator used to manage memory and elements.
* @tparam Args Types of arguments to use to construct the object.
* @param value Memory location in which to place the object.
* @param allocator The allocator to use.
* @param args Parameters to use to construct the object.
* @return A pointer to the newly created object of the given type.
*/
template<typename Type, typename Allocator, typename... Args>
constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
return std::apply([value](auto &&...curr) { return new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
}
} // namespace entt
#endif

View File

@@ -1,13 +1,11 @@
#ifndef ENTT_CORE_MONOSTATE_HPP
#define ENTT_CORE_MONOSTATE_HPP
#include "../config/config.h"
#include "fwd.hpp"
namespace entt {
/**
* @brief Minimal implementation of the monostate pattern.
*
@@ -19,7 +17,7 @@ namespace entt {
* both during an assignment and when they try to read back their data.
* Otherwise, they can incur in unexpected results.
*/
template<ENTT_ID_TYPE>
template<id_type>
struct monostate {
/**
* @brief Assigns a value of a specific type to a given key.
@@ -27,7 +25,7 @@ struct monostate {
* @param val User data to assign to the given key.
*/
template<typename Type>
void operator=(Type val) const ENTT_NOEXCEPT {
void operator=(Type val) const noexcept {
value<Type> = val;
}
@@ -37,7 +35,7 @@ struct monostate {
* @return Stored value, if any.
*/
template<typename Type>
operator Type() const ENTT_NOEXCEPT {
operator Type() const noexcept {
return value<Type>;
}
@@ -46,16 +44,13 @@ private:
inline static ENTT_MAYBE_ATOMIC(Type) value{};
};
/**
* @brief Helper variable template.
* @tparam Value Value used to differentiate between different variables.
*/
template<ENTT_ID_TYPE Value>
template<id_type Value>
inline monostate<Value> monostate_v = {};
}
} // namespace entt
#endif

103
src/entt/core/tuple.hpp Normal file
View File

@@ -0,0 +1,103 @@
#ifndef ENTT_CORE_TUPLE_HPP
#define ENTT_CORE_TUPLE_HPP
#include <tuple>
#include <type_traits>
#include <utility>
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename>
struct is_tuple_impl: std::false_type {};
template<typename... Args>
struct is_tuple_impl<std::tuple<Args...>>: std::true_type {};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Provides the member constant `value` to true if a given type is a
* tuple, false otherwise.
* @tparam Type The type to test.
*/
template<typename Type>
struct is_tuple: internal::is_tuple_impl<std::remove_cv_t<Type>> {};
/**
* @brief Helper variable template.
* @tparam Type The type to test.
*/
template<typename Type>
inline constexpr bool is_tuple_v = is_tuple<Type>::value;
/**
* @brief Utility function to unwrap tuples of a single element.
* @tparam Type Tuple type of any sizes.
* @param value A tuple object of the given type.
* @return The tuple itself if it contains more than one element, the first
* element otherwise.
*/
template<typename Type>
constexpr decltype(auto) unwrap_tuple(Type &&value) noexcept {
if constexpr(std::tuple_size_v<std::remove_reference_t<Type>> == 1u) {
return std::get<0>(std::forward<Type>(value));
} else {
return std::forward<Type>(value);
}
}
/**
* @brief Utility class to forward-and-apply tuple objects.
* @tparam Func Type of underlying invocable object.
*/
template<typename Func>
struct forward_apply: private Func {
/**
* @brief Constructs a forward-and-apply object.
* @tparam Args Types of arguments to use to construct the new instance.
* @param args Parameters to use to construct the instance.
*/
template<class... Args>
constexpr forward_apply(Args &&...args) noexcept(std::is_nothrow_constructible_v<Func, Args...>)
: Func{std::forward<Args>(args)...} {}
/**
* @brief Forwards and applies the arguments with the underlying function.
* @tparam Type Tuple-like type to forward to the underlying function.
* @param args Parameters to forward to the underlying function.
* @return Return value of the underlying function, if any.
*/
template<class Type>
constexpr decltype(auto) operator()(Type &&args) noexcept(noexcept(std::apply(std::declval<Func &>(), args))) {
return std::apply(static_cast<Func &>(*this), std::forward<Type>(args));
}
/*! @copydoc operator()() */
template<class Type>
constexpr decltype(auto) operator()(Type &&args) const noexcept(noexcept(std::apply(std::declval<const Func &>(), args))) {
return std::apply(static_cast<const Func &>(*this), std::forward<Type>(args));
}
};
/**
* @brief Deduction guide.
* @tparam Func Type of underlying invocable object.
*/
template<typename Func>
forward_apply(Func) -> forward_apply<std::remove_reference_t<std::remove_cv_t<Func>>>;
} // namespace entt
#endif

View File

@@ -1,80 +1,274 @@
#ifndef ENTT_CORE_TYPE_INFO_HPP
#define ENTT_CORE_TYPE_INFO_HPP
#include <string_view>
#include <type_traits>
#include <utility>
#include "../config/config.h"
#include "../core/attribute.h"
#include "fwd.hpp"
#include "hashed_string.hpp"
#ifndef ENTT_PRETTY_FUNCTION
# define ENTT_TYPE_ID_API ENTT_API
#else
# define ENTT_TYPE_ID_API
#endif
namespace entt {
#ifndef ENTT_PRETTY_FUNCTION
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
struct ENTT_API type_id_generator {
static ENTT_ID_TYPE next() ENTT_NOEXCEPT {
static ENTT_ID_TYPE value{};
struct ENTT_API type_index final {
[[nodiscard]] static id_type next() noexcept {
static ENTT_MAYBE_ATOMIC(id_type) value{};
return value++;
}
};
template<typename Type>
[[nodiscard]] constexpr auto stripped_type_name() noexcept {
#if defined ENTT_PRETTY_FUNCTION
std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
auto value = pretty_function.substr(first, pretty_function.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
return value;
#else
return std::string_view{""};
#endif
}
template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
[[nodiscard]] static constexpr std::string_view type_name(int) noexcept {
constexpr auto value = stripped_type_name<Type>();
return value;
}
template<typename Type>
[[nodiscard]] static std::string_view type_name(char) noexcept {
static const auto value = stripped_type_name<Type>();
return value;
}
template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
[[nodiscard]] static constexpr id_type type_hash(int) noexcept {
constexpr auto stripped = stripped_type_name<Type>();
constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
return value;
}
template<typename Type>
[[nodiscard]] static id_type type_hash(char) noexcept {
static const auto value = [](const auto stripped) {
return hashed_string::value(stripped.data(), stripped.size());
}(stripped_type_name<Type>());
return value;
}
} // namespace internal
/**
* Internal details not to be documented.
* @endcond TURN_OFF_DOXYGEN
* @endcond
*/
#endif
/**
* @brief Types identifiers.
* @tparam Type Type for which to generate an identifier.
* @brief Type sequential identifier.
* @tparam Type Type for which to generate a sequential identifier.
*/
template<typename Type, typename = void>
struct ENTT_TYPE_ID_API type_info {
struct ENTT_API type_index final {
/**
* @brief Returns the sequential identifier of a given type.
* @return The sequential identifier of a given type.
*/
[[nodiscard]] static id_type value() noexcept {
static const id_type value = internal::type_index::next();
return value;
}
/*! @copydoc value */
[[nodiscard]] constexpr operator id_type() const noexcept {
return value();
}
};
/**
* @brief Type hash.
* @tparam Type Type for which to generate a hash value.
*/
template<typename Type, typename = void>
struct type_hash final {
/**
* @brief Returns the numeric representation of a given type.
* @return The numeric representation of the given type.
*/
#if defined ENTT_PRETTY_FUNCTION_CONSTEXPR
static constexpr ENTT_ID_TYPE id() ENTT_NOEXCEPT {
constexpr auto value = entt::hashed_string::value(ENTT_PRETTY_FUNCTION_CONSTEXPR);
return value;
}
#elif defined ENTT_PRETTY_FUNCTION
static ENTT_ID_TYPE id() ENTT_NOEXCEPT {
static const auto value = entt::hashed_string::value(ENTT_PRETTY_FUNCTION);
return value;
}
#if defined ENTT_PRETTY_FUNCTION
[[nodiscard]] static constexpr id_type value() noexcept {
return internal::type_hash<Type>(0);
#else
static ENTT_ID_TYPE id() ENTT_NOEXCEPT {
static const ENTT_ID_TYPE value = internal::type_id_generator::next();
return value;
}
[[nodiscard]] static constexpr id_type value() noexcept {
return type_index<Type>::value();
#endif
}
/*! @copydoc value */
[[nodiscard]] constexpr operator id_type() const noexcept {
return value();
}
};
/**
* @brief Type name.
* @tparam Type Type for which to generate a name.
*/
template<typename Type, typename = void>
struct type_name final {
/**
* @brief Returns the name of a given type.
* @return The name of the given type.
*/
[[nodiscard]] static constexpr std::string_view value() noexcept {
return internal::type_name<Type>(0);
}
/*! @copydoc value */
[[nodiscard]] constexpr operator std::string_view() const noexcept {
return value();
}
};
/*! @brief Implementation specific information about a type. */
struct type_info final {
/**
* @brief Constructs a type info object for a given type.
* @tparam Type Type for which to construct a type info object.
*/
template<typename Type>
constexpr type_info(std::in_place_type_t<Type>) noexcept
: seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()},
alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {}
/**
* @brief Type index.
* @return Type index.
*/
[[nodiscard]] constexpr id_type index() const noexcept {
return seq;
}
/**
* @brief Type hash.
* @return Type hash.
*/
[[nodiscard]] constexpr id_type hash() const noexcept {
return identifier;
}
/**
* @brief Type name.
* @return Type name.
*/
[[nodiscard]] constexpr std::string_view name() const noexcept {
return alias;
}
private:
id_type seq;
id_type identifier;
std::string_view alias;
};
/**
* @brief Compares the contents of two type info objects.
* @param lhs A type info object.
* @param rhs A type info object.
* @return True if the two type info objects are identical, false otherwise.
*/
[[nodiscard]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
return lhs.hash() == rhs.hash();
}
/**
* @brief Compares the contents of two type info objects.
* @param lhs A type info object.
* @param rhs A type info object.
* @return True if the two type info objects differ, false otherwise.
*/
[[nodiscard]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
return !(lhs == rhs);
}
/**
* @brief Compares two type info objects.
* @param lhs A valid type info object.
* @param rhs A valid type info object.
* @return True if the first element is less than the second, false otherwise.
*/
[[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
return lhs.index() < rhs.index();
}
/**
* @brief Compares two type info objects.
* @param lhs A valid type info object.
* @param rhs A valid type info object.
* @return True if the first element is less than or equal to the second, false
* otherwise.
*/
[[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
return !(rhs < lhs);
}
/**
* @brief Compares two type info objects.
* @param lhs A valid type info object.
* @param rhs A valid type info object.
* @return True if the first element is greater than the second, false
* otherwise.
*/
[[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
return rhs < lhs;
}
/**
* @brief Compares two type info objects.
* @param lhs A valid type info object.
* @param rhs A valid type info object.
* @return True if the first element is greater than or equal to the second,
* false otherwise.
*/
[[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
return !(lhs < rhs);
}
/**
* @brief Returns the type info object associated to a given type.
*
* The returned element refers to an object with static storage duration.<br/>
* The type doesn't need to be a complete type. If the type is a reference, the
* result refers to the referenced type. In all cases, top-level cv-qualifiers
* are ignored.
*
* @tparam Type Type for which to generate a type info object.
* @return A reference to a properly initialized type info object.
*/
template<typename Type>
[[nodiscard]] const type_info &type_id() noexcept {
if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) {
static type_info instance{std::in_place_type<Type>};
return instance;
} else {
return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
}
}
/*! @copydoc type_id */
template<typename Type>
[[nodiscard]] const type_info &type_id(Type &&) noexcept {
return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>();
}
} // namespace entt
#endif

View File

@@ -1,76 +1,219 @@
#ifndef ENTT_CORE_TYPE_TRAITS_HPP
#define ENTT_CORE_TYPE_TRAITS_HPP
#include <cstddef>
#include <utility>
#include <iterator>
#include <type_traits>
#include <utility>
#include "../config/config.h"
#include "../core/hashed_string.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @brief Utility class to disambiguate overloaded functions.
* @tparam N Number of choices available.
*/
template<std::size_t N>
struct choice_t
// Unfortunately, doxygen cannot parse such a construct.
/*! @cond TURN_OFF_DOXYGEN */
: choice_t<N-1>
/*! @endcond TURN_OFF_DOXYGEN */
// Unfortunately, doxygen cannot parse such a construct.
: /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
{};
/*! @copybrief choice_t */
template<>
struct choice_t<0> {};
/**
* @brief Variable template for the choice trick.
* @tparam N Number of choices available.
*/
template<std::size_t N>
constexpr choice_t<N> choice{};
/*! @brief A class to use to push around lists of types, nothing more. */
template<typename...>
struct type_list {};
/*! @brief Primary template isn't defined on purpose. */
template<typename>
struct type_list_size;
inline constexpr choice_t<N> choice{};
/**
* @brief Compile-time number of elements in a type list.
* @brief Identity type trait.
*
* Useful to establish non-deduced contexts in template argument deduction
* (waiting for C++20) or to provide types through function arguments.
*
* @tparam Type A type.
*/
template<typename Type>
struct type_identity {
/*! @brief Identity type. */
using type = Type;
};
/**
* @brief Helper type.
* @tparam Type A type.
*/
template<typename Type>
using type_identity_t = typename type_identity<Type>::type;
/**
* @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
* @tparam Type The type of which to return the size.
* @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
*/
template<typename Type, typename = void>
struct size_of: std::integral_constant<std::size_t, 0u> {};
/*! @copydoc size_of */
template<typename Type>
struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
: std::integral_constant<std::size_t, sizeof(Type)> {};
/**
* @brief Helper variable template.
* @tparam Type The type of which to return the size.
*/
template<typename Type>
inline constexpr std::size_t size_of_v = size_of<Type>::value;
/**
* @brief Using declaration to be used to _repeat_ the same type a number of
* times equal to the size of a given parameter pack.
* @tparam Type A type to repeat.
*/
template<typename Type, typename>
using unpack_as_type = Type;
/**
* @brief Helper variable template to be used to _repeat_ the same value a
* number of times equal to the size of a given parameter pack.
* @tparam Value A value to repeat.
*/
template<auto Value, typename>
inline constexpr auto unpack_as_value = Value;
/**
* @brief Wraps a static constant.
* @tparam Value A static constant.
*/
template<auto Value>
using integral_constant = std::integral_constant<decltype(Value), Value>;
/**
* @brief Alias template to facilitate the creation of named values.
* @tparam Value A constant value at least convertible to `id_type`.
*/
template<id_type Value>
using tag = integral_constant<Value>;
/**
* @brief A class to use to push around lists of types, nothing more.
* @tparam Type Types provided by the type list.
*/
template<typename... Type>
struct type_list_size<type_list<Type...>>
: std::integral_constant<std::size_t, sizeof...(Type)>
{};
struct type_list {
/*! @brief Type list type. */
using type = type_list;
/*! @brief Compile-time number of elements in the type list. */
static constexpr auto size = sizeof...(Type);
};
/*! @brief Primary template isn't defined on purpose. */
template<std::size_t, typename>
struct type_list_element;
/**
* @brief Provides compile-time indexed access to the types of a type list.
* @tparam Index Index of the type to return.
* @tparam First First type provided by the type list.
* @tparam Other Other types provided by the type list.
*/
template<std::size_t Index, typename First, typename... Other>
struct type_list_element<Index, type_list<First, Other...>>
: type_list_element<Index - 1u, type_list<Other...>> {};
/**
* @brief Provides compile-time indexed access to the types of a type list.
* @tparam First First type provided by the type list.
* @tparam Other Other types provided by the type list.
*/
template<typename First, typename... Other>
struct type_list_element<0u, type_list<First, Other...>> {
/*! @brief Searched type. */
using type = First;
};
/**
* @brief Helper type.
* @tparam Index Index of the type to return.
* @tparam List Type list to search into.
*/
template<std::size_t Index, typename List>
using type_list_element_t = typename type_list_element<Index, List>::type;
/*! @brief Primary template isn't defined on purpose. */
template<typename, typename>
struct type_list_index;
/**
* @brief Provides compile-time type access to the types of a type list.
* @tparam Type Type to look for and for which to return the index.
* @tparam First First type provided by the type list.
* @tparam Other Other types provided by the type list.
*/
template<typename Type, typename First, typename... Other>
struct type_list_index<Type, type_list<First, Other...>> {
/*! @brief Unsigned integer type. */
using value_type = std::size_t;
/*! @brief Compile-time position of the given type in the sublist. */
static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
};
/**
* @brief Provides compile-time type access to the types of a type list.
* @tparam Type Type to look for and for which to return the index.
* @tparam Other Other types provided by the type list.
*/
template<typename Type, typename... Other>
struct type_list_index<Type, type_list<Type, Other...>> {
static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
/*! @brief Unsigned integer type. */
using value_type = std::size_t;
/*! @brief Compile-time position of the given type in the sublist. */
static constexpr value_type value = 0u;
};
/**
* @brief Provides compile-time type access to the types of a type list.
* @tparam Type Type to look for and for which to return the index.
*/
template<typename Type>
struct type_list_index<Type, type_list<>> {
/*! @brief Unsigned integer type. */
using value_type = std::size_t;
/*! @brief Compile-time position of the given type in the sublist. */
static constexpr value_type value = 0u;
};
/**
* @brief Helper variable template.
* @tparam List Type list.
* @tparam Type Type to look for and for which to return the index.
*/
template<class List>
constexpr auto type_list_size_v = type_list_size<List>::value;
template<typename Type, typename List>
inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
/**
* @brief Concatenates multiple type lists.
* @tparam Type Types provided by the first type list.
* @tparam Other Types provided by the second type list.
* @return A type list composed by the types of both the type lists.
*/
template<typename... Type, typename... Other>
constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
return {};
}
/*! @brief Primary template isn't defined on purpose. */
template<typename...>
struct type_list_cat;
/*! @brief Concatenates multiple type lists. */
template<>
struct type_list_cat<> {
@@ -78,7 +221,6 @@ struct type_list_cat<> {
using type = type_list<>;
};
/**
* @brief Concatenates multiple type lists.
* @tparam Type Types provided by the first type list.
@@ -91,7 +233,6 @@ struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
};
/**
* @brief Concatenates multiple type lists.
* @tparam Type Types provided by the type list.
@@ -102,7 +243,6 @@ struct type_list_cat<type_list<Type...>> {
using type = type_list<Type...>;
};
/**
* @brief Helper type.
* @tparam List Type lists to concatenate.
@@ -110,12 +250,10 @@ struct type_list_cat<type_list<Type...>> {
template<typename... List>
using type_list_cat_t = typename type_list_cat<List...>::type;
/*! @brief Primary template isn't defined on purpose. */
template<typename>
struct type_list_unique;
/**
* @brief Removes duplicates types from a type list.
* @tparam Type One of the types provided by the given type list.
@@ -125,13 +263,11 @@ template<typename Type, typename... Other>
struct type_list_unique<type_list<Type, Other...>> {
/*! @brief A type list without duplicate types. */
using type = std::conditional_t<
std::disjunction_v<std::is_same<Type, Other>...>,
(std::is_same_v<Type, Other> || ...),
typename type_list_unique<type_list<Other...>>::type,
type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>
>;
type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>>;
};
/*! @brief Removes duplicates types from a type list. */
template<>
struct type_list_unique<type_list<>> {
@@ -139,7 +275,6 @@ struct type_list_unique<type_list<>> {
using type = type_list<>;
};
/**
* @brief Helper type.
* @tparam Type A type list.
@@ -147,28 +282,415 @@ struct type_list_unique<type_list<>> {
template<typename Type>
using type_list_unique_t = typename type_list_unique<Type>::type;
/**
* @brief Provides the member constant `value` to true if a type list contains a
* given type, false otherwise.
* @tparam List Type list.
* @tparam Type Type to look for.
*/
template<typename List, typename Type>
struct type_list_contains;
/**
* @copybrief type_list_contains
* @tparam Type Types provided by the type list.
* @tparam Other Type to look for.
*/
template<typename... Type, typename Other>
struct type_list_contains<type_list<Type...>, Other>: std::disjunction<std::is_same<Type, Other>...> {};
/**
* @brief Helper variable template.
* @tparam List Type list.
* @tparam Type Type to look for.
*/
template<typename List, typename Type>
inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
/*! @brief Primary template isn't defined on purpose. */
template<typename...>
struct type_list_diff;
/**
* @brief Computes the difference between two type lists.
* @tparam Type Types provided by the first type list.
* @tparam Other Types provided by the second type list.
*/
template<typename... Type, typename... Other>
struct type_list_diff<type_list<Type...>, type_list<Other...>> {
/*! @brief A type list that is the difference between the two type lists. */
using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
};
/**
* @brief Helper type.
* @tparam List Type lists between which to compute the difference.
*/
template<typename... List>
using type_list_diff_t = typename type_list_diff<List...>::type;
/*! @brief Primary template isn't defined on purpose. */
template<typename, template<typename...> class>
struct type_list_transform;
/**
* @brief Applies a given _function_ to a type list and generate a new list.
* @tparam Type Types provided by the type list.
* @tparam Op Unary operation as template class with a type member named `type`.
*/
template<typename... Type, template<typename...> class Op>
struct type_list_transform<type_list<Type...>, Op> {
/*! @brief Resulting type list after applying the transform function. */
using type = type_list<typename Op<Type>::type...>;
};
/**
* @brief Helper type.
* @tparam List Type list.
* @tparam Op Unary operation as template class with a type member named `type`.
*/
template<typename List, template<typename...> class Op>
using type_list_transform_t = typename type_list_transform<List, Op>::type;
/**
* @brief A class to use to push around lists of constant values, nothing more.
* @tparam Value Values provided by the value list.
*/
template<auto... Value>
struct value_list {
/*! @brief Value list type. */
using type = value_list;
/*! @brief Compile-time number of elements in the value list. */
static constexpr auto size = sizeof...(Value);
};
/*! @brief Primary template isn't defined on purpose. */
template<std::size_t, typename>
struct value_list_element;
/**
* @brief Provides compile-time indexed access to the values of a value list.
* @tparam Index Index of the value to return.
* @tparam Value First value provided by the value list.
* @tparam Other Other values provided by the value list.
*/
template<std::size_t Index, auto Value, auto... Other>
struct value_list_element<Index, value_list<Value, Other...>>
: value_list_element<Index - 1u, value_list<Other...>> {};
/**
* @brief Provides compile-time indexed access to the types of a type list.
* @tparam Value First value provided by the value list.
* @tparam Other Other values provided by the value list.
*/
template<auto Value, auto... Other>
struct value_list_element<0u, value_list<Value, Other...>> {
/*! @brief Searched value. */
static constexpr auto value = Value;
};
/**
* @brief Helper type.
* @tparam Index Index of the value to return.
* @tparam List Value list to search into.
*/
template<std::size_t Index, typename List>
inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
/**
* @brief Concatenates multiple value lists.
* @tparam Value Values provided by the first value list.
* @tparam Other Values provided by the second value list.
* @return A value list composed by the values of both the value lists.
*/
template<auto... Value, auto... Other>
constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
return {};
}
/*! @brief Primary template isn't defined on purpose. */
template<typename...>
struct value_list_cat;
/*! @brief Concatenates multiple value lists. */
template<>
struct value_list_cat<> {
/*! @brief A value list composed by the values of all the value lists. */
using type = value_list<>;
};
/**
* @brief Concatenates multiple value lists.
* @tparam Value Values provided by the first value list.
* @tparam Other Values provided by the second value list.
* @tparam List Other value lists, if any.
*/
template<auto... Value, auto... Other, typename... List>
struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
/*! @brief A value list composed by the values of all the value lists. */
using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
};
/**
* @brief Concatenates multiple value lists.
* @tparam Value Values provided by the value list.
*/
template<auto... Value>
struct value_list_cat<value_list<Value...>> {
/*! @brief A value list composed by the values of all the value lists. */
using type = value_list<Value...>;
};
/**
* @brief Helper type.
* @tparam List Value lists to concatenate.
*/
template<typename... List>
using value_list_cat_t = typename value_list_cat<List...>::type;
/*! @brief Same as std::is_invocable, but with tuples. */
template<typename, typename>
struct is_applicable: std::false_type {};
/**
* @copybrief is_applicable
* @tparam Func A valid function type.
* @tparam Tuple Tuple-like type.
* @tparam Args The list of arguments to use to probe the function type.
*/
template<typename Func, template<typename...> class Tuple, typename... Args>
struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
/**
* @copybrief is_applicable
* @tparam Func A valid function type.
* @tparam Tuple Tuple-like type.
* @tparam Args The list of arguments to use to probe the function type.
*/
template<typename Func, template<typename...> class Tuple, typename... Args>
struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
/**
* @brief Helper variable template.
* @tparam Func A valid function type.
* @tparam Args The list of arguments to use to probe the function type.
*/
template<typename Func, typename Args>
inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
/*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
template<typename, typename, typename>
struct is_applicable_r: std::false_type {};
/**
* @copybrief is_applicable_r
* @tparam Ret The type to which the return type of the function should be
* convertible.
* @tparam Func A valid function type.
* @tparam Args The list of arguments to use to probe the function type.
*/
template<typename Ret, typename Func, typename... Args>
struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
/**
* @brief Helper variable template.
* @tparam Ret The type to which the return type of the function should be
* convertible.
* @tparam Func A valid function type.
* @tparam Args The list of arguments to use to probe the function type.
*/
template<typename Ret, typename Func, typename Args>
inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
/**
* @brief Provides the member constant `value` to true if a given type is
* complete, false otherwise.
* @tparam Type The type to test.
*/
template<typename Type, typename = void>
struct is_complete: std::false_type {};
/*! @copydoc is_complete */
template<typename Type>
struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
/**
* @brief Helper variable template.
* @tparam Type The type to test.
*/
template<typename Type>
inline constexpr bool is_complete_v = is_complete<Type>::value;
/**
* @brief Provides the member constant `value` to true if a given type is an
* iterator, false otherwise.
* @tparam Type The type to test.
*/
template<typename Type, typename = void>
struct is_iterator: std::false_type {};
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename, typename = void>
struct has_iterator_category: std::false_type {};
template<typename Type>
struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/*! @copydoc is_iterator */
template<typename Type>
struct is_iterator<Type, std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_pointer_t<Type>>, void>>>
: internal::has_iterator_category<Type> {};
/**
* @brief Helper variable template.
* @tparam Type The type to test.
*/
template<typename Type>
inline constexpr bool is_iterator_v = is_iterator<Type>::value;
/**
* @brief Provides the member constant `value` to true if a given type is both
* an empty and non-final class, false otherwise.
* @tparam Type The type to test
*/
template<typename Type>
struct is_ebco_eligible
: std::conjunction<std::is_empty<Type>, std::negation<std::is_final<Type>>> {};
/**
* @brief Helper variable template.
* @tparam Type The type to test.
*/
template<typename Type>
inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
/**
* @brief Provides the member constant `value` to true if `Type::is_transparent`
* is valid and denotes a type, false otherwise.
* @tparam Type The type to test.
*/
template<typename Type, typename = void>
struct is_transparent: std::false_type {};
/*! @copydoc is_transparent */
template<typename Type>
struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
/**
* @brief Helper variable template.
* @tparam Type The type to test.
*/
template<typename Type>
inline constexpr bool is_transparent_v = is_transparent<Type>::value;
/**
* @brief Provides the member constant `value` to true if a given type is
* equality comparable, false otherwise.
* @tparam Type Potentially equality comparable type.
* @tparam Type The type to test.
*/
template<typename Type, typename = std::void_t<>>
template<typename Type, typename = void>
struct is_equality_comparable: std::false_type {};
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename, typename = void>
struct has_tuple_size_value: std::false_type {};
template<typename Type>
struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
template<typename Type, std::size_t... Index>
[[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
return (is_equality_comparable<std::tuple_element_t<Index, Type>>::value && ...);
}
template<typename>
[[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) {
return true;
}
template<typename Type>
[[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval<typename Type::value_type>(), bool{}) {
if constexpr(is_iterator_v<Type>) {
return true;
} else if constexpr(std::is_same_v<typename Type::value_type, Type>) {
return maybe_equality_comparable<Type>(choice<0>);
} else {
return is_equality_comparable<typename Type::value_type>::value;
}
}
template<typename Type>
[[nodiscard]] constexpr std::enable_if_t<is_complete_v<std::tuple_size<std::remove_cv_t<Type>>>, bool> maybe_equality_comparable(choice_t<2>) {
if constexpr(has_tuple_size_value<Type>::value) {
return unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
} else {
return maybe_equality_comparable<Type>(choice<1>);
}
}
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/*! @copydoc is_equality_comparable */
template<typename Type>
struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>: std::true_type {};
struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
: std::bool_constant<internal::maybe_equality_comparable<Type>(choice<2>)> {};
/**
* @brief Helper variable template.
* @tparam Type Potentially equality comparable type.
* @tparam Type The type to test.
*/
template<class Type>
constexpr auto is_equality_comparable_v = is_equality_comparable<Type>::value;
template<typename Type>
inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
/**
* @brief Transcribes the constness of a type to another type.
* @tparam To The type to which to transcribe the constness.
* @tparam From The type from which to transcribe the constness.
*/
template<typename To, typename From>
struct constness_as {
/*! @brief The type resulting from the transcription of the constness. */
using type = std::remove_const_t<To>;
};
/*! @copydoc constness_as */
template<typename To, typename From>
struct constness_as<To, const From> {
/*! @brief The type resulting from the transcription of the constness. */
using type = const To;
};
/**
* @brief Alias template to facilitate the transcription of the constness.
* @tparam To The type to which to transcribe the constness.
* @tparam From The type from which to transcribe the constness.
*/
template<typename To, typename From>
using constness_as_t = typename constness_as<To, From>::type;
/**
* @brief Extracts the class of a non-static member object or function.
@@ -176,23 +698,22 @@ constexpr auto is_equality_comparable_v = is_equality_comparable<Type>::value;
*/
template<typename Member>
class member_class {
static_assert(std::is_member_pointer_v<Member>);
static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
template<typename Class, typename Ret, typename... Args>
static Class * clazz(Ret(Class:: *)(Args...));
static Class *clazz(Ret (Class::*)(Args...));
template<typename Class, typename Ret, typename... Args>
static Class * clazz(Ret(Class:: *)(Args...) const);
static Class *clazz(Ret (Class::*)(Args...) const);
template<typename Class, typename Type>
static Class * clazz(Type Class:: *);
static Class *clazz(Type Class::*);
public:
/*! @brief The class of the given non-static member object or function. */
using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
};
/**
* @brief Helper type.
* @tparam Member A pointer to a non-static member object or function.
@@ -200,30 +721,38 @@ public:
template<typename Member>
using member_class_t = typename member_class<Member>::type;
/**
* @brief Extracts the n-th argument of a given function or member function.
* @tparam Index The index of the argument to extract.
* @tparam Candidate A valid function, member function or data member.
*/
template<std::size_t Index, auto Candidate>
class nth_argument {
template<typename Ret, typename... Args>
static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
template<typename Ret, typename Class, typename... Args>
static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
template<typename Ret, typename Class, typename... Args>
static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
template<typename Type, typename Class>
static constexpr type_list<Type> pick_up(Type Class ::*);
public:
/*! @brief N-th argument of the given function or member function. */
using type = type_list_element_t<Index, decltype(pick_up(Candidate))>;
};
/**
* @brief Alias template to ease the creation of named values.
* @tparam Value A constant value at least convertible to `ENTT_ID_TYPE`.
* @brief Helper type.
* @tparam Index The index of the argument to extract.
* @tparam Candidate A valid function, member function or data member.
*/
template<ENTT_ID_TYPE Value>
using tag = std::integral_constant<ENTT_ID_TYPE, Value>;
}
/**
* @brief Defines an enum class to use for opaque identifiers and a dedicate
* `to_integer` function to convert the identifiers to their underlying type.
* @param clazz The name to use for the enum class.
* @param type The underlying type for the enum class.
*/
#define ENTT_OPAQUE_TYPE(clazz, type)\
enum class clazz: type {};\
constexpr auto to_integral(const clazz id) ENTT_NOEXCEPT {\
return static_cast<std::underlying_type_t<clazz>>(id);\
}\
static_assert(true)
template<std::size_t Index, auto Candidate>
using nth_argument_t = typename nth_argument<Index, Candidate>::type;
} // namespace entt
#endif

View File

@@ -1,16 +1,16 @@
#ifndef ENTT_CORE_UTILITY_HPP
#define ENTT_CORE_UTILITY_HPP
#include <type_traits>
#include <utility>
#include "../config/config.h"
namespace entt {
/*! @brief Identity function object (waiting for C++20). */
struct identity {
/*! @brief Indicates that this is a transparent function object. */
using is_transparent = void;
/**
* @brief Returns its argument unchanged.
* @tparam Type Type of the argument.
@@ -18,12 +18,11 @@ struct identity {
* @return The submitted value as-is.
*/
template<class Type>
constexpr Type && operator()(Type &&value) const ENTT_NOEXCEPT {
[[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
return std::forward<Type>(value);
}
};
/**
* @brief Constant utility to disambiguate overloaded members of a class.
* @tparam Type Type of the desired overload.
@@ -32,8 +31,9 @@ struct identity {
* @return Pointer to the member.
*/
template<typename Type, typename Class>
constexpr auto overload(Type Class:: *member) ENTT_NOEXCEPT { return member; }
[[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
return member;
}
/**
* @brief Constant utility to disambiguate overloaded functions.
@@ -42,8 +42,9 @@ constexpr auto overload(Type Class:: *member) ENTT_NOEXCEPT { return member; }
* @return Pointer to the function.
*/
template<typename Func>
constexpr auto overload(Func *func) ENTT_NOEXCEPT { return func; }
[[nodiscard]] constexpr auto overload(Func *func) noexcept {
return func;
}
/**
* @brief Helper type for visitors.
@@ -54,7 +55,6 @@ struct overloaded: Func... {
using Func::operator()...;
};
/**
* @brief Deduction guide.
* @tparam Func Types of function objects.
@@ -62,7 +62,6 @@ struct overloaded: Func... {
template<class... Func>
overloaded(Func...) -> overloaded<Func...>;
/**
* @brief Basic implementation of a y-combinator.
* @tparam Func Type of a potentially recursive function.
@@ -73,9 +72,8 @@ struct y_combinator {
* @brief Constructs a y-combinator from a given function.
* @param recursive A potentially recursive function.
*/
y_combinator(Func recursive):
func{std::move(recursive)}
{}
constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
: func{std::move(recursive)} {}
/**
* @brief Invokes a y-combinator and therefore its underlying function.
@@ -83,14 +81,14 @@ struct y_combinator {
* @param args Parameters to use to invoke the underlying function.
* @return Return value of the underlying function, if any.
*/
template <class... Args>
decltype(auto) operator()(Args &&... args) const {
template<class... Args>
constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
return func(*this, std::forward<Args>(args)...);
}
/*! @copydoc operator()() */
template <class... Args>
decltype(auto) operator()(Args &&... args) {
template<class... Args>
constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
return func(*this, std::forward<Args>(args)...);
}
@@ -98,8 +96,6 @@ private:
Func func;
};
}
} // namespace entt
#endif

View File

@@ -1,206 +0,0 @@
#ifndef ENTT_ENTITY_ACTOR_HPP
#define ENTT_ENTITY_ACTOR_HPP
#include <utility>
#include <type_traits>
#include "../config/config.h"
#include "registry.hpp"
#include "entity.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @brief Dedicated to those who aren't confident with the
* entity-component-system architecture.
*
* Tiny wrapper around a registry, for all those users that aren't confident
* with entity-component-system architecture and prefer to iterate objects
* directly.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
*/
template<typename Entity>
struct basic_actor {
/*! @brief Type of registry used internally. */
using registry_type = basic_registry<Entity>;
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
basic_actor() ENTT_NOEXCEPT
: entt{entt::null}, reg{nullptr}
{}
/**
* @brief Move constructor.
*
* After actor move construction, instances that have been moved from are
* placed in a valid but unspecified state. It's highly discouraged to
* continue using them.
*
* @param other The instance to move from.
*/
basic_actor(basic_actor &&other) ENTT_NOEXCEPT
: entt{other.entt}, reg{other.reg}
{
other.entt = null;
}
/**
* @brief Constructs an actor from a given registry.
* @param ref An instance of the registry class.
*/
explicit basic_actor(registry_type &ref)
: entt{ref.create()}, reg{&ref}
{}
/**
* @brief Constructs an actor from a given entity.
* @param entity A valid entity identifier.
* @param ref An instance of the registry class.
*/
explicit basic_actor(entity_type entity, registry_type &ref) ENTT_NOEXCEPT
: entt{entity}, reg{&ref}
{
ENTT_ASSERT(ref.valid(entity));
}
/*! @brief Default destructor. */
virtual ~basic_actor() {
if(*this) {
reg->destroy(entt);
}
}
/**
* @brief Move assignment operator.
*
* After actor move assignment, instances that have been moved from are
* placed in a valid but unspecified state. It's highly discouraged to
* continue using them.
*
* @param other The instance to move from.
* @return This actor.
*/
basic_actor & operator=(basic_actor &&other) ENTT_NOEXCEPT {
if(this != &other) {
auto tmp{std::move(other)};
std::swap(reg, tmp.reg);
std::swap(entt, tmp.entt);
}
return *this;
}
/**
* @brief Assigns the given component to an actor.
*
* A new instance of the given component is created and initialized with the
* arguments provided (the component must have a proper constructor or be of
* aggregate type). Then the component is assigned to the actor.<br/>
* In case the actor already has a component of the given type, it's
* replaced with the new one.
*
* @tparam Component Type of the component to create.
* @tparam Args Types of arguments to use to construct the component.
* @param args Parameters to use to initialize the component.
* @return A reference to the newly created component.
*/
template<typename Component, typename... Args>
decltype(auto) assign(Args &&... args) {
return reg->template assign_or_replace<Component>(entt, std::forward<Args>(args)...);
}
/**
* @brief Removes the given component from an actor.
* @tparam Component Type of the component to remove.
*/
template<typename Component>
void remove() {
reg->template remove<Component>(entt);
}
/**
* @brief Checks if an actor has the given components.
* @tparam Component Components for which to perform the check.
* @return True if the actor has all the components, false otherwise.
*/
template<typename... Component>
bool has() const {
return (reg->template has<Component>(entt) && ...);
}
/**
* @brief Returns references to the given components for an actor.
* @tparam Component Types of components to get.
* @return References to the components owned by the actor.
*/
template<typename... Component>
decltype(auto) get() const {
return std::as_const(*reg).template get<Component...>(entt);
}
/*! @copydoc get */
template<typename... Component>
decltype(auto) get() {
return reg->template get<Component...>(entt);
}
/**
* @brief Returns pointers to the given components for an actor.
* @tparam Component Types of components to get.
* @return Pointers to the components owned by the actor.
*/
template<typename... Component>
auto try_get() const {
return std::as_const(*reg).template try_get<Component...>(entt);
}
/*! @copydoc try_get */
template<typename... Component>
auto try_get() {
return reg->template try_get<Component...>(entt);
}
/**
* @brief Returns a reference to the underlying registry.
* @return A reference to the underlying registry.
*/
const registry_type & backend() const ENTT_NOEXCEPT {
return *reg;
}
/*! @copydoc backend */
registry_type & backend() ENTT_NOEXCEPT {
return const_cast<registry_type &>(std::as_const(*this).backend());
}
/**
* @brief Returns the entity associated with an actor.
* @return The entity associated with the actor.
*/
entity_type entity() const ENTT_NOEXCEPT {
return entt;
}
/**
* @brief Checks if an actor refers to a valid entity or not.
* @return True if the actor refers to a valid entity, false otherwise.
*/
explicit operator bool() const {
return reg && reg->valid(entt);
}
private:
entity_type entt;
registry_type *reg;
};
}
#endif

View File

@@ -0,0 +1,64 @@
#ifndef ENTT_ENTITY_COMPONENT_HPP
#define ENTT_ENTITY_COMPONENT_HPP
#include <cstddef>
#include <type_traits>
#include "../config/config.h"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename Type, typename = void>
struct in_place_delete: std::bool_constant<!(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>)> {};
template<typename Type>
struct in_place_delete<Type, std::enable_if_t<Type::in_place_delete>>
: std::true_type {};
template<typename Type, typename = void>
struct page_size: std::integral_constant<std::size_t, !std::is_empty_v<ENTT_ETO_TYPE(Type)> * ENTT_PACKED_PAGE> {};
template<typename Type>
struct page_size<Type, std::enable_if_t<std::is_convertible_v<decltype(Type::page_size), std::size_t>>>
: std::integral_constant<std::size_t, Type::page_size> {};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Common way to access various properties of components.
* @tparam Type Type of component.
*/
template<typename Type, typename = void>
struct component_traits {
static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
/*! @brief Component type. */
using type = Type;
/*! @brief Pointer stability, default is `false`. */
static constexpr bool in_place_delete = internal::in_place_delete<Type>::value;
/*! @brief Page size, default is `ENTT_PACKED_PAGE` for non-empty types. */
static constexpr std::size_t page_size = internal::page_size<Type>::value;
};
/**
* @brief Helper variable template.
* @tparam Type Type of component.
*/
template<class Type>
inline constexpr bool ignore_as_empty_v = (std::is_void_v<Type> || component_traits<Type>::page_size == 0u);
} // namespace entt
#endif

View File

@@ -1,175 +1,339 @@
#ifndef ENTT_ENTITY_ENTITY_HPP
#define ENTT_ENTITY_ENTITY_HPP
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include "../config/config.h"
#include "../core/type_traits.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @brief Entity traits.
*
* Primary template isn't defined on purpose. All the specializations give a
* compile-time error unless the template parameter is an accepted entity type.
*/
template<typename>
struct entt_traits;
/**
* @brief Entity traits for a 16 bits entity identifier.
*
* A 16 bits entity identifier guarantees:
*
* * 12 bits for the entity number (up to 4k entities).
* * 4 bit for the version (resets in [0-15]).
*/
template<>
struct entt_traits<std::uint16_t> {
/*! @brief Underlying entity type. */
using entity_type = std::uint16_t;
/*! @brief Underlying version type. */
using version_type = std::uint8_t;
/*! @brief Difference type. */
using difference_type = std::int32_t;
/*! @brief Mask to use to get the entity number out of an identifier. */
static constexpr std::uint16_t entity_mask = 0xFFF;
/*! @brief Mask to use to get the version out of an identifier. */
static constexpr std::uint16_t version_mask = 0xF;
/*! @brief Extent of the entity number within an identifier. */
static constexpr auto entity_shift = 12;
};
/**
* @brief Entity traits for a 32 bits entity identifier.
*
* A 32 bits entity identifier guarantees:
*
* * 20 bits for the entity number (suitable for almost all the games).
* * 12 bit for the version (resets in [0-4095]).
*/
template<>
struct entt_traits<std::uint32_t> {
/*! @brief Underlying entity type. */
using entity_type = std::uint32_t;
/*! @brief Underlying version type. */
using version_type = std::uint16_t;
/*! @brief Difference type. */
using difference_type = std::int64_t;
/*! @brief Mask to use to get the entity number out of an identifier. */
static constexpr std::uint32_t entity_mask = 0xFFFFF;
/*! @brief Mask to use to get the version out of an identifier. */
static constexpr std::uint32_t version_mask = 0xFFF;
/*! @brief Extent of the entity number within an identifier. */
static constexpr auto entity_shift = 20;
};
/**
* @brief Entity traits for a 64 bits entity identifier.
*
* A 64 bits entity identifier guarantees:
*
* * 32 bits for the entity number (an indecently large number).
* * 32 bit for the version (an indecently large number).
*/
template<>
struct entt_traits<std::uint64_t> {
/*! @brief Underlying entity type. */
using entity_type = std::uint64_t;
/*! @brief Underlying version type. */
using version_type = std::uint32_t;
/*! @brief Difference type. */
using difference_type = std::int64_t;
/*! @brief Mask to use to get the entity number out of an identifier. */
static constexpr std::uint64_t entity_mask = 0xFFFFFFFF;
/*! @brief Mask to use to get the version out of an identifier. */
static constexpr std::uint64_t version_mask = 0xFFFFFFFF;
/*! @brief Extent of the entity number within an identifier. */
static constexpr auto entity_shift = 32;
};
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename, typename = void>
struct entt_traits;
class null {
template<typename Entity>
using traits_type = entt_traits<std::underlying_type_t<Entity>>;
template<typename Type>
struct entt_traits<Type, std::enable_if_t<std::is_enum_v<Type>>>
: entt_traits<std::underlying_type_t<Type>> {};
template<typename Type>
struct entt_traits<Type, std::enable_if_t<std::is_class_v<Type>>>
: entt_traits<typename Type::entity_type> {};
template<>
struct entt_traits<std::uint32_t> {
using entity_type = std::uint32_t;
using version_type = std::uint16_t;
static constexpr entity_type entity_mask = 0xFFFFF;
static constexpr entity_type version_mask = 0xFFF;
static constexpr std::size_t entity_shift = 20u;
};
template<>
struct entt_traits<std::uint64_t> {
using entity_type = std::uint64_t;
using version_type = std::uint32_t;
static constexpr entity_type entity_mask = 0xFFFFFFFF;
static constexpr entity_type version_mask = 0xFFFFFFFF;
static constexpr std::size_t entity_shift = 32u;
};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Entity traits.
* @tparam Type Type of identifier.
*/
template<typename Type>
class entt_traits: internal::entt_traits<Type> {
using base_type = internal::entt_traits<Type>;
public:
template<typename Entity>
constexpr operator Entity() const ENTT_NOEXCEPT {
return Entity{traits_type<Entity>::entity_mask};
/*! @brief Value type. */
using value_type = Type;
/*! @brief Underlying entity type. */
using entity_type = typename base_type::entity_type;
/*! @brief Underlying version type. */
using version_type = typename base_type::version_type;
/*! @brief Reserved identifier. */
static constexpr entity_type reserved = base_type::entity_mask | (base_type::version_mask << base_type::entity_shift);
/*! @brief Page size, default is `ENTT_SPARSE_PAGE`. */
static constexpr auto page_size = ENTT_SPARSE_PAGE;
/**
* @brief Converts an entity to its underlying type.
* @param value The value to convert.
* @return The integral representation of the given value.
*/
[[nodiscard]] static constexpr entity_type to_integral(const value_type value) noexcept {
return static_cast<entity_type>(value);
}
constexpr bool operator==(null) const ENTT_NOEXCEPT {
/**
* @brief Returns the entity part once converted to the underlying type.
* @param value The value to convert.
* @return The integral representation of the entity part.
*/
[[nodiscard]] static constexpr entity_type to_entity(const value_type value) noexcept {
return (to_integral(value) & base_type::entity_mask);
}
/**
* @brief Returns the version part once converted to the underlying type.
* @param value The value to convert.
* @return The integral representation of the version part.
*/
[[nodiscard]] static constexpr version_type to_version(const value_type value) noexcept {
return (to_integral(value) >> base_type::entity_shift);
}
/**
* @brief Constructs an identifier from its parts.
*
* If the version part is not provided, a tombstone is returned.<br/>
* If the entity part is not provided, a null identifier is returned.
*
* @param entity The entity part of the identifier.
* @param version The version part of the identifier.
* @return A properly constructed identifier.
*/
[[nodiscard]] static constexpr value_type construct(const entity_type entity, const version_type version) noexcept {
return value_type{(entity & base_type::entity_mask) | (static_cast<entity_type>(version) << base_type::entity_shift)};
}
/**
* @brief Combines two identifiers in a single one.
*
* The returned identifier is a copy of the first element except for its
* version, which is taken from the second element.
*
* @param lhs The identifier from which to take the entity part.
* @param rhs The identifier from which to take the version part.
* @return A properly constructed identifier.
*/
[[nodiscard]] static constexpr value_type combine(const entity_type lhs, const entity_type rhs) noexcept {
constexpr auto mask = (base_type::version_mask << base_type::entity_shift);
return value_type{(lhs & base_type::entity_mask) | (rhs & mask)};
}
};
/**
* @copydoc entt_traits<Entity>::to_integral
* @tparam Entity The value type.
*/
template<typename Entity>
[[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_integral(const Entity value) noexcept {
return entt_traits<Entity>::to_integral(value);
}
/**
* @copydoc entt_traits<Entity>::to_entity
* @tparam Entity The value type.
*/
template<typename Entity>
[[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_entity(const Entity value) noexcept {
return entt_traits<Entity>::to_entity(value);
}
/**
* @copydoc entt_traits<Entity>::to_version
* @tparam Entity The value type.
*/
template<typename Entity>
[[nodiscard]] constexpr typename entt_traits<Entity>::version_type to_version(const Entity value) noexcept {
return entt_traits<Entity>::to_version(value);
}
/*! @brief Null object for all identifiers. */
struct null_t {
/**
* @brief Converts the null object to identifiers of any type.
* @tparam Entity Type of identifier.
* @return The null representation for the given type.
*/
template<typename Entity>
[[nodiscard]] constexpr operator Entity() const noexcept {
using entity_traits = entt_traits<Entity>;
return entity_traits::combine(entity_traits::reserved, entity_traits::reserved);
}
/**
* @brief Compares two null objects.
* @param other A null object.
* @return True in all cases.
*/
[[nodiscard]] constexpr bool operator==([[maybe_unused]] const null_t other) const noexcept {
return true;
}
constexpr bool operator!=(null) const ENTT_NOEXCEPT {
/**
* @brief Compares two null objects.
* @param other A null object.
* @return False in all cases.
*/
[[nodiscard]] constexpr bool operator!=([[maybe_unused]] const null_t other) const noexcept {
return false;
}
/**
* @brief Compares a null object and an identifier of any type.
* @tparam Entity Type of identifier.
* @param entity Identifier with which to compare.
* @return False if the two elements differ, true otherwise.
*/
template<typename Entity>
constexpr bool operator==(const Entity entity) const ENTT_NOEXCEPT {
return (to_integral(entity) & traits_type<Entity>::entity_mask) == to_integral(static_cast<Entity>(*this));
[[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept {
using entity_traits = entt_traits<Entity>;
return entity_traits::to_entity(entity) == entity_traits::to_entity(*this);
}
/**
* @brief Compares a null object and an identifier of any type.
* @tparam Entity Type of identifier.
* @param entity Identifier with which to compare.
* @return True if the two elements differ, false otherwise.
*/
template<typename Entity>
constexpr bool operator!=(const Entity entity) const ENTT_NOEXCEPT {
[[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept {
return !(entity == *this);
}
};
/**
* @brief Compares a null object and an identifier of any type.
* @tparam Entity Type of identifier.
* @param entity Identifier with which to compare.
* @param other A null object yet to be converted.
* @return False if the two elements differ, true otherwise.
*/
template<typename Entity>
constexpr bool operator==(const Entity entity, null other) ENTT_NOEXCEPT {
return other == entity;
[[nodiscard]] constexpr bool operator==(const Entity entity, const null_t other) noexcept {
return other.operator==(entity);
}
template<typename Entity>
constexpr bool operator!=(const Entity entity, null other) ENTT_NOEXCEPT {
return other != entity;
}
}
/**
* Internal details not to be documented.
* @endcond TURN_OFF_DOXYGEN
* @brief Compares a null object and an identifier of any type.
* @tparam Entity Type of identifier.
* @param entity Identifier with which to compare.
* @param other A null object yet to be converted.
* @return True if the two elements differ, false otherwise.
*/
template<typename Entity>
[[nodiscard]] constexpr bool operator!=(const Entity entity, const null_t other) noexcept {
return !(other == entity);
}
/*! @brief Tombstone object for all identifiers. */
struct tombstone_t {
/**
* @brief Converts the tombstone object to identifiers of any type.
* @tparam Entity Type of identifier.
* @return The tombstone representation for the given type.
*/
template<typename Entity>
[[nodiscard]] constexpr operator Entity() const noexcept {
using entity_traits = entt_traits<Entity>;
return entity_traits::combine(entity_traits::reserved, entity_traits::reserved);
}
/**
* @brief Compares two tombstone objects.
* @param other A tombstone object.
* @return True in all cases.
*/
[[nodiscard]] constexpr bool operator==([[maybe_unused]] const tombstone_t other) const noexcept {
return true;
}
/**
* @brief Compares two tombstone objects.
* @param other A tombstone object.
* @return False in all cases.
*/
[[nodiscard]] constexpr bool operator!=([[maybe_unused]] const tombstone_t other) const noexcept {
return false;
}
/**
* @brief Compares a tombstone object and an identifier of any type.
* @tparam Entity Type of identifier.
* @param entity Identifier with which to compare.
* @return False if the two elements differ, true otherwise.
*/
template<typename Entity>
[[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept {
using entity_traits = entt_traits<Entity>;
return entity_traits::to_version(entity) == entity_traits::to_version(*this);
}
/**
* @brief Compares a tombstone object and an identifier of any type.
* @tparam Entity Type of identifier.
* @param entity Identifier with which to compare.
* @return True if the two elements differ, false otherwise.
*/
template<typename Entity>
[[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept {
return !(entity == *this);
}
};
/**
* @brief Compares a tombstone object and an identifier of any type.
* @tparam Entity Type of identifier.
* @param entity Identifier with which to compare.
* @param other A tombstone object yet to be converted.
* @return False if the two elements differ, true otherwise.
*/
template<typename Entity>
[[nodiscard]] constexpr bool operator==(const Entity entity, const tombstone_t other) noexcept {
return other.operator==(entity);
}
/**
* @brief Compares a tombstone object and an identifier of any type.
* @tparam Entity Type of identifier.
* @param entity Identifier with which to compare.
* @param other A tombstone object yet to be converted.
* @return True if the two elements differ, false otherwise.
*/
template<typename Entity>
[[nodiscard]] constexpr bool operator!=(const Entity entity, const tombstone_t other) noexcept {
return !(other == entity);
}
/**
* @brief Compile-time constant for null entities.
*
* There exist implicit conversions from this variable to entity identifiers of
* any allowed type. Similarly, there exist comparision operators between the
* null entity and any other entity identifier.
* There exist implicit conversions from this variable to identifiers of any
* allowed type. Similarly, there exist comparison operators between the null
* entity and any other identifier.
*/
constexpr auto null = internal::null{};
inline constexpr null_t null{};
/**
* @brief Compile-time constant for tombstone entities.
*
* There exist implicit conversions from this variable to identifiers of any
* allowed type. Similarly, there exist comparison operators between the
* tombstone entity and any other identifier.
*/
inline constexpr tombstone_t tombstone{};
}
} // namespace entt
#endif

View File

@@ -1,122 +1,174 @@
#ifndef ENTT_ENTITY_FWD_HPP
#define ENTT_ENTITY_FWD_HPP
#include "../config/config.h"
#include <memory>
#include <type_traits>
#include "../core/fwd.hpp"
#include "../core/type_traits.hpp"
namespace entt {
/*! @brief Default entity identifier. */
enum class entity : id_type {};
template<typename Entity = entity, typename = std::allocator<Entity>>
class basic_sparse_set;
template<typename Type, typename = entity, typename = std::allocator<Type>, typename = void>
class basic_storage;
template<typename Type, typename = entity, typename = std::allocator<Type>, typename = void>
struct storage_type;
template<typename Type, typename = entity, typename = std::allocator<std::remove_const_t<Type>>>
struct storage_for;
template<typename Type>
class sigh_storage_mixin;
template<typename Entity = entity, typename = std::allocator<Entity>>
class basic_registry;
template<typename, typename, typename = void>
class basic_view;
template<typename Type, typename = std::allocator<Type *>>
class basic_runtime_view;
template<typename, typename, typename>
class basic_group;
template<typename>
class basic_observer;
template<typename>
class basic_organizer;
template<typename, typename...>
struct basic_handle;
template<typename>
class basic_snapshot;
template<typename>
class basic_snapshot_loader;
template<typename>
class basic_continuous_loader;
/**
* @brief Alias for exclusion lists.
* @tparam Type List of types.
*/
template<typename... Type>
struct exclude_t: type_list<Type...> {};
using exclude_t = type_list<Type...>;
/**
* @brief Variable template for exclusion lists.
* @tparam Type List of types.
*/
template<typename... Type>
constexpr exclude_t<Type...> exclude{};
inline constexpr exclude_t<Type...> exclude{};
/**
* @brief Alias for lists of observed components.
* @tparam Type List of types.
*/
template<typename... Type>
struct get_t: type_list<Type...>{};
using get_t = type_list<Type...>;
/**
* @brief Variable template for lists of observed components.
* @tparam Type List of types.
*/
template<typename... Type>
constexpr get_t<Type...> get{};
inline constexpr get_t<Type...> get{};
/**
* @brief Alias for lists of owned components.
* @tparam Type List of types.
*/
template<typename... Type>
using owned_t = type_list<Type...>;
/*! @class basic_registry */
template <typename>
class basic_registry;
/*! @class basic_view */
template<typename...>
class basic_view;
/*! @class basic_runtime_view */
template<typename>
class basic_runtime_view;
/*! @class basic_group */
template<typename...>
class basic_group;
/*! @class basic_observer */
template<typename>
class basic_observer;
/*! @struct basic_actor */
template <typename>
struct basic_actor;
/*! @class basic_snapshot */
template<typename>
class basic_snapshot;
/*! @class basic_snapshot_loader */
template<typename>
class basic_snapshot_loader;
/*! @class basic_continuous_loader */
template<typename>
class basic_continuous_loader;
/**
* @brief Variable template for lists of owned components.
* @tparam Type List of types.
*/
template<typename... Type>
inline constexpr owned_t<Type...> owned{};
/*! @brief Alias declaration for the most common use case. */
ENTT_OPAQUE_TYPE(entity, ENTT_ID_TYPE);
/*! @brief Alias declaration for the most common use case. */
using registry = basic_registry<entity>;
/*! @brief Alias declaration for the most common use case. */
using observer = basic_observer<entity>;
/*! @brief Alias declaration for the most common use case. */
using actor = basic_actor<entity>;
/*! @brief Alias declaration for the most common use case. */
using snapshot = basic_snapshot<entity>;
/*! @brief Alias declaration for the most common use case. */
using snapshot_loader = basic_snapshot_loader<entity>;
/*! @brief Alias declaration for the most common use case. */
using continuous_loader = basic_continuous_loader<entity>;
using sparse_set = basic_sparse_set<>;
/**
* @brief Alias declaration for the most common use case.
* @tparam Types Types of components iterated by the view.
* @tparam Type Type of objects assigned to the entities.
*/
template<typename... Types>
using view = basic_view<entity, Types...>;
template<typename Type>
using storage = basic_storage<Type>;
/*! @brief Alias declaration for the most common use case. */
using runtime_view = basic_runtime_view<entity>;
using registry = basic_registry<>;
/*! @brief Alias declaration for the most common use case. */
using observer = basic_observer<registry>;
/*! @brief Alias declaration for the most common use case. */
using organizer = basic_organizer<registry>;
/*! @brief Alias declaration for the most common use case. */
using handle = basic_handle<registry>;
/*! @brief Alias declaration for the most common use case. */
using const_handle = basic_handle<const registry>;
/**
* @brief Alias declaration for the most common use case.
* @tparam Types Types of components iterated by the group.
* @tparam Args Other template parameters.
*/
template<typename... Types>
using group = basic_group<entity, Types...>;
template<typename... Args>
using handle_view = basic_handle<registry, Args...>;
/**
* @brief Alias declaration for the most common use case.
* @tparam Args Other template parameters.
*/
template<typename... Args>
using const_handle_view = basic_handle<const registry, Args...>;
}
/*! @brief Alias declaration for the most common use case. */
using snapshot = basic_snapshot<registry>;
/*! @brief Alias declaration for the most common use case. */
using snapshot_loader = basic_snapshot_loader<registry>;
/*! @brief Alias declaration for the most common use case. */
using continuous_loader = basic_continuous_loader<registry>;
/**
* @brief Alias declaration for the most common use case.
* @tparam Get Types of storage iterated by the view.
* @tparam Exclude Types of storage used to filter the view.
*/
template<typename Get, typename Exclude = exclude_t<>>
using view = basic_view<type_list_transform_t<Get, storage_for>, type_list_transform_t<Exclude, storage_for>>;
/*! @brief Alias declaration for the most common use case. */
using runtime_view = basic_runtime_view<sparse_set>;
/*! @brief Alias declaration for the most common use case. */
using const_runtime_view = basic_runtime_view<const sparse_set>;
/**
* @brief Alias declaration for the most common use case.
* @tparam Owned Types of storage _owned_ by the group.
* @tparam Get Types of storage _observed_ by the group.
* @tparam Exclude Types of storage used to filter the group.
*/
template<typename Owned, typename Get, typename Exclude>
using group = basic_group<type_list_transform_t<Owned, storage_for>, type_list_transform_t<Get, storage_for>, type_list_transform_t<Exclude, storage_for>>;
} // namespace entt
#endif

File diff suppressed because it is too large Load Diff

382
src/entt/entity/handle.hpp Normal file
View File

@@ -0,0 +1,382 @@
#ifndef ENTT_ENTITY_HANDLE_HPP
#define ENTT_ENTITY_HANDLE_HPP
#include <iterator>
#include <tuple>
#include <type_traits>
#include <utility>
#include "../core/iterator.hpp"
#include "../core/type_traits.hpp"
#include "entity.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename It>
class handle_storage_iterator final {
template<typename Other>
friend class handle_storage_iterator;
using underlying_type = std::remove_reference_t<typename It::value_type::second_type>;
using entity_type = typename underlying_type::entity_type;
public:
using value_type = typename std::iterator_traits<It>::value_type;
using pointer = input_iterator_pointer<value_type>;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category = std::input_iterator_tag;
constexpr handle_storage_iterator() noexcept
: entt{null},
it{},
last{} {}
constexpr handle_storage_iterator(entity_type value, It from, It to) noexcept
: entt{value},
it{from},
last{to} {
while(it != last && !it->second.contains(entt)) { ++it; }
}
constexpr handle_storage_iterator &operator++() noexcept {
while(++it != last && !it->second.contains(entt)) {}
return *this;
}
constexpr handle_storage_iterator operator++(int) noexcept {
handle_storage_iterator orig = *this;
return ++(*this), orig;
}
[[nodiscard]] constexpr reference operator*() const noexcept {
return *it;
}
[[nodiscard]] constexpr pointer operator->() const noexcept {
return operator*();
}
template<typename ILhs, typename IRhs>
friend constexpr bool operator==(const handle_storage_iterator<ILhs> &, const handle_storage_iterator<IRhs> &) noexcept;
private:
entity_type entt;
It it;
It last;
};
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator==(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept {
return lhs.it == rhs.it;
}
template<typename ILhs, typename IRhs>
[[nodiscard]] constexpr bool operator!=(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept {
return !(lhs == rhs);
}
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Non-owning handle to an entity.
*
* Tiny wrapper around a registry and an entity.
*
* @tparam Registry Basic registry type.
* @tparam Scope Types to which to restrict the scope of a handle.
*/
template<typename Registry, typename... Scope>
struct basic_handle {
/*! @brief Type of registry accepted by the handle. */
using registry_type = Registry;
/*! @brief Underlying entity identifier. */
using entity_type = typename registry_type::entity_type;
/*! @brief Underlying version type. */
using version_type = typename registry_type::version_type;
/*! @brief Unsigned integer type. */
using size_type = typename registry_type::size_type;
/*! @brief Constructs an invalid handle. */
basic_handle() noexcept
: reg{},
entt{null} {}
/**
* @brief Constructs a handle from a given registry and entity.
* @param ref An instance of the registry class.
* @param value A valid identifier.
*/
basic_handle(registry_type &ref, entity_type value) noexcept
: reg{&ref},
entt{value} {}
/**
* @brief Returns an iterable object to use to _visit_ a handle.
*
* The iterable object returns a pair that contains the name and a reference
* to the current storage.<br/>
* Returned storage are those that contain the entity associated with the
* handle.
*
* @return An iterable object to use to _visit_ the handle.
*/
[[nodiscard]] auto storage() const noexcept {
auto iterable = reg->storage();
using iterator_type = internal::handle_storage_iterator<typename decltype(iterable)::iterator>;
return iterable_adaptor{iterator_type{entt, iterable.begin(), iterable.end()}, iterator_type{entt, iterable.end(), iterable.end()}};
}
/**
* @brief Constructs a const handle from a non-const one.
* @tparam Other A valid entity type (see entt_traits for more details).
* @tparam Args Scope of the handle to construct.
* @return A const handle referring to the same registry and the same
* entity.
*/
template<typename Other, typename... Args>
operator basic_handle<Other, Args...>() const noexcept {
static_assert(std::is_same_v<Other, Registry> || std::is_same_v<std::remove_const_t<Other>, Registry>, "Invalid conversion between different handles");
static_assert((sizeof...(Scope) == 0 || ((sizeof...(Args) != 0 && sizeof...(Args) <= sizeof...(Scope)) && ... && (type_list_contains_v<type_list<Scope...>, Args>))), "Invalid conversion between different handles");
return reg ? basic_handle<Other, Args...>{*reg, entt} : basic_handle<Other, Args...>{};
}
/**
* @brief Converts a handle to its underlying entity.
* @return The contained identifier.
*/
[[nodiscard]] operator entity_type() const noexcept {
return entity();
}
/**
* @brief Checks if a handle refers to non-null registry pointer and entity.
* @return True if the handle refers to non-null registry and entity, false otherwise.
*/
[[nodiscard]] explicit operator bool() const noexcept {
return reg && reg->valid(entt);
}
/**
* @brief Checks if a handle refers to a valid entity or not.
* @return True if the handle refers to a valid entity, false otherwise.
*/
[[nodiscard]] bool valid() const {
return reg->valid(entt);
}
/**
* @brief Returns a pointer to the underlying registry, if any.
* @return A pointer to the underlying registry, if any.
*/
[[nodiscard]] registry_type *registry() const noexcept {
return reg;
}
/**
* @brief Returns the entity associated with a handle.
* @return The entity associated with the handle.
*/
[[nodiscard]] entity_type entity() const noexcept {
return entt;
}
/*! @brief Destroys the entity associated with a handle. */
void destroy() {
reg->destroy(entt);
}
/**
* @brief Destroys the entity associated with a handle.
* @param version A desired version upon destruction.
*/
void destroy(const version_type version) {
reg->destroy(entt, version);
}
/**
* @brief Assigns the given component to a handle.
* @tparam Component Type of component to create.
* @tparam Args Types of arguments to use to construct the component.
* @param args Parameters to use to initialize the component.
* @return A reference to the newly created component.
*/
template<typename Component, typename... Args>
decltype(auto) emplace(Args &&...args) const {
static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
return reg->template emplace<Component>(entt, std::forward<Args>(args)...);
}
/**
* @brief Assigns or replaces the given component for a handle.
* @tparam Component Type of component to assign or replace.
* @tparam Args Types of arguments to use to construct the component.
* @param args Parameters to use to initialize the component.
* @return A reference to the newly created component.
*/
template<typename Component, typename... Args>
decltype(auto) emplace_or_replace(Args &&...args) const {
static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
return reg->template emplace_or_replace<Component>(entt, std::forward<Args>(args)...);
}
/**
* @brief Patches the given component for a handle.
* @tparam Component Type of component to patch.
* @tparam Func Types of the function objects to invoke.
* @param func Valid function objects.
* @return A reference to the patched component.
*/
template<typename Component, typename... Func>
decltype(auto) patch(Func &&...func) const {
static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
return reg->template patch<Component>(entt, std::forward<Func>(func)...);
}
/**
* @brief Replaces the given component for a handle.
* @tparam Component Type of component to replace.
* @tparam Args Types of arguments to use to construct the component.
* @param args Parameters to use to initialize the component.
* @return A reference to the component being replaced.
*/
template<typename Component, typename... Args>
decltype(auto) replace(Args &&...args) const {
static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
return reg->template replace<Component>(entt, std::forward<Args>(args)...);
}
/**
* @brief Removes the given components from a handle.
* @tparam Component Types of components to remove.
* @return The number of components actually removed.
*/
template<typename... Component>
size_type remove() const {
static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Component> && ...), "Invalid type");
return reg->template remove<Component...>(entt);
}
/**
* @brief Erases the given components from a handle.
* @tparam Component Types of components to erase.
*/
template<typename... Component>
void erase() const {
static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Component> && ...), "Invalid type");
reg->template erase<Component...>(entt);
}
/**
* @brief Checks if a handle has all the given components.
* @tparam Component Components for which to perform the check.
* @return True if the handle has all the components, false otherwise.
*/
template<typename... Component>
[[nodiscard]] decltype(auto) all_of() const {
return reg->template all_of<Component...>(entt);
}
/**
* @brief Checks if a handle has at least one of the given components.
* @tparam Component Components for which to perform the check.
* @return True if the handle has at least one of the given components,
* false otherwise.
*/
template<typename... Component>
[[nodiscard]] decltype(auto) any_of() const {
return reg->template any_of<Component...>(entt);
}
/**
* @brief Returns references to the given components for a handle.
* @tparam Component Types of components to get.
* @return References to the components owned by the handle.
*/
template<typename... Component>
[[nodiscard]] decltype(auto) get() const {
static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Component> && ...), "Invalid type");
return reg->template get<Component...>(entt);
}
/**
* @brief Returns a reference to the given component for a handle.
* @tparam Component Type of component to get.
* @tparam Args Types of arguments to use to construct the component.
* @param args Parameters to use to initialize the component.
* @return Reference to the component owned by the handle.
*/
template<typename Component, typename... Args>
[[nodiscard]] decltype(auto) get_or_emplace(Args &&...args) const {
static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Component, Scope>), "Invalid type");
return reg->template get_or_emplace<Component>(entt, std::forward<Args>(args)...);
}
/**
* @brief Returns pointers to the given components for a handle.
* @tparam Component Types of components to get.
* @return Pointers to the components owned by the handle.
*/
template<typename... Component>
[[nodiscard]] auto try_get() const {
static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Component> && ...), "Invalid type");
return reg->template try_get<Component...>(entt);
}
/**
* @brief Checks if a handle has components assigned.
* @return True if the handle has no components assigned, false otherwise.
*/
[[nodiscard]] bool orphan() const {
return reg->orphan(entt);
}
private:
registry_type *reg;
entity_type entt;
};
/**
* @brief Compares two handles.
* @tparam Args Scope of the first handle.
* @tparam Other Scope of the second handle.
* @param lhs A valid handle.
* @param rhs A valid handle.
* @return True if both handles refer to the same registry and the same
* entity, false otherwise.
*/
template<typename... Args, typename... Other>
[[nodiscard]] bool operator==(const basic_handle<Args...> &lhs, const basic_handle<Other...> &rhs) noexcept {
return lhs.registry() == rhs.registry() && lhs.entity() == rhs.entity();
}
/**
* @brief Compares two handles.
* @tparam Args Scope of the first handle.
* @tparam Other Scope of the second handle.
* @param lhs A valid handle.
* @param rhs A valid handle.
* @return False if both handles refer to the same registry and the same
* entity, true otherwise.
*/
template<typename... Args, typename... Other>
[[nodiscard]] bool operator!=(const basic_handle<Args...> &lhs, const basic_handle<Other...> &rhs) noexcept {
return !(lhs == rhs);
}
} // namespace entt
#endif

View File

@@ -1,117 +1,144 @@
#ifndef ENTT_ENTITY_HELPER_HPP
#define ENTT_ENTITY_HELPER_HPP
#include <memory>
#include <type_traits>
#include "../core/fwd.hpp"
#include "../core/type_traits.hpp"
#include "../config/config.h"
#include "registry.hpp"
#include "../signal/delegate.hpp"
#include "component.hpp"
#include "fwd.hpp"
#include "group.hpp"
#include "view.hpp"
namespace entt {
/**
* @brief Converts a registry to a view.
* @tparam Const Constness of the accepted registry.
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Registry Basic registry type.
*/
template<bool Const, typename Entity>
struct as_view {
template<typename Registry>
class as_view {
template<typename... Get, typename... Exclude>
auto dispatch(get_t<Get...>, exclude_t<Exclude...>) const {
return reg.template view<constness_as_t<typename Get::value_type, Get>...>(exclude_t<constness_as_t<typename Exclude::value_type, Exclude>...>{});
}
public:
/*! @brief Type of registry to convert. */
using registry_type = std::conditional_t<Const, const entt::basic_registry<Entity>, entt::basic_registry<Entity>>;
using registry_type = Registry;
/*! @brief Underlying entity identifier. */
using entity_type = std::remove_const_t<typename registry_type::entity_type>;
/**
* @brief Constructs a converter for a given registry.
* @param source A valid reference to a registry.
*/
as_view(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
as_view(registry_type &source) noexcept
: reg{source} {}
/**
* @brief Conversion function from a registry to a view.
* @tparam Exclude Types of components used to filter the view.
* @tparam Component Type of components used to construct the view.
* @tparam Get Type of storage used to construct the view.
* @tparam Exclude Types of storage used to filter the view.
* @return A newly created view.
*/
template<typename Exclude, typename... Component>
operator entt::basic_view<Entity, Exclude, Component...>() const {
return reg.template view<Component...>(Exclude{});
template<typename Get, typename Exclude>
operator basic_view<Get, Exclude>() const {
return dispatch(Get{}, Exclude{});
}
private:
registry_type &reg;
};
/**
* @brief Deduction guide.
*
* It allows to deduce the constness of a registry directly from the instance
* provided to the constructor.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
*/
template<typename Entity>
as_view(basic_registry<Entity> &) ENTT_NOEXCEPT -> as_view<false, Entity>;
/*! @copydoc as_view */
template<typename Entity>
as_view(const basic_registry<Entity> &) ENTT_NOEXCEPT -> as_view<true, Entity>;
/**
* @brief Converts a registry to a group.
* @tparam Const Constness of the accepted registry.
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Registry Basic registry type.
*/
template<bool Const, typename Entity>
struct as_group {
template<typename Registry>
class as_group {
template<typename... Owned, typename... Get, typename... Exclude>
auto dispatch(owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>) const {
if constexpr(std::is_const_v<registry_type>) {
return reg.template group_if_exists<typename Owned::value_type...>(get_t<typename Get::value_type...>{}, exclude_t<typename Exclude::value_type...>{});
} else {
return reg.template group<constness_as_t<typename Owned::value_type, Owned>...>(get_t<constness_as_t<typename Get::value_type, Get>...>{}, exclude_t<constness_as_t<typename Exclude::value_type, Exclude>...>{});
}
}
public:
/*! @brief Type of registry to convert. */
using registry_type = std::conditional_t<Const, const entt::basic_registry<Entity>, entt::basic_registry<Entity>>;
using registry_type = Registry;
/*! @brief Underlying entity identifier. */
using entity_type = std::remove_const_t<typename registry_type::entity_type>;
/**
* @brief Constructs a converter for a given registry.
* @param source A valid reference to a registry.
*/
as_group(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
as_group(registry_type &source) noexcept
: reg{source} {}
/**
* @brief Conversion function from a registry to a group.
* @tparam Exclude Types of components used to filter the group.
* @tparam Get Types of components observed by the group.
* @tparam Owned Types of components owned by the group.
* @tparam Owned Types of _owned_ by the group.
* @tparam Get Types of storage _observed_ by the group.
* @tparam Exclude Types of storage used to filter the group.
* @return A newly created group.
*/
template<typename Exclude, typename Get, typename... Owned>
operator entt::basic_group<Entity, Exclude, Get, Owned...>() const {
return reg.template group<Owned...>(Get{}, Exclude{});
template<typename Owned, typename Get, typename Exclude>
operator basic_group<Owned, Get, Exclude>() const {
return dispatch(Owned{}, Get{}, Exclude{});
}
private:
registry_type &reg;
};
/**
* @brief Deduction guide.
*
* It allows to deduce the constness of a registry directly from the instance
* provided to the constructor.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
* @brief Helper to create a listener that directly invokes a member function.
* @tparam Member Member function to invoke on a component of the given type.
* @tparam Registry Basic registry type.
* @param reg A registry that contains the given entity and its components.
* @param entt Entity from which to get the component.
*/
template<typename Entity>
as_group(basic_registry<Entity> &) ENTT_NOEXCEPT -> as_group<false, Entity>;
/*! @copydoc as_group */
template<typename Entity>
as_group(const basic_registry<Entity> &) ENTT_NOEXCEPT -> as_group<true, Entity>;
template<auto Member, typename Registry = std::decay_t<nth_argument_t<0u, Member>>>
void invoke(Registry &reg, const typename Registry::entity_type entt) {
static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
delegate<void(Registry &, const typename Registry::entity_type)> func;
func.template connect<Member>(reg.template get<member_class_t<decltype(Member)>>(entt));
func(reg, entt);
}
/**
* @brief Returns the entity associated with a given component.
*
* @warning
* Currently, this function only works correctly with the default pool as it
* makes assumptions about how the components are laid out.
*
* @tparam Registry Basic registry type.
* @tparam Component Type of component.
* @param reg A registry that contains the given entity and its components.
* @param instance A valid component instance.
* @return The entity associated with the given component.
*/
template<typename Registry, typename Component>
typename Registry::entity_type to_entity(const Registry &reg, const Component &instance) {
const auto &storage = reg.template storage<Component>();
const typename Registry::base_type &base = storage;
const auto *addr = std::addressof(instance);
for(auto it = base.rbegin(), last = base.rend(); it < last; it += component_traits<Component>::page_size) {
if(const auto dist = (addr - std::addressof(storage.get(*it))); dist >= 0 && dist < static_cast<decltype(dist)>(component_traits<Component>::page_size)) {
return *(it + dist);
}
}
return null;
}
} // namespace entt
#endif

View File

@@ -1,28 +1,22 @@
#ifndef ENTT_ENTITY_OBSERVER_HPP
#define ENTT_ENTITY_OBSERVER_HPP
#include <limits>
#include <cstddef>
#include <cstdint>
#include <utility>
#include <limits>
#include <type_traits>
#include "../config/config.h"
#include <utility>
#include "../core/type_traits.hpp"
#include "registry.hpp"
#include "storage.hpp"
#include "entity.hpp"
#include "../signal/delegate.hpp"
#include "fwd.hpp"
#include "storage.hpp"
namespace entt {
/*! @brief Grouping matcher. */
template<typename...>
struct matcher {};
/**
* @brief Collector.
*
@@ -32,7 +26,6 @@ struct matcher {};
template<typename...>
struct basic_collector;
/**
* @brief Collector.
*
@@ -50,7 +43,7 @@ struct basic_collector<> {
* @return The updated collector.
*/
template<typename... AllOf, typename... NoneOf>
static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
static constexpr auto group(exclude_t<NoneOf...> = {}) noexcept {
return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>>{};
}
@@ -60,7 +53,7 @@ struct basic_collector<> {
* @return The updated collector.
*/
template<typename AnyOf>
static constexpr auto replace() ENTT_NOEXCEPT {
static constexpr auto update() noexcept {
return basic_collector<matcher<type_list<>, type_list<>, AnyOf>>{};
}
};
@@ -85,7 +78,7 @@ struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule
* @return The updated collector.
*/
template<typename... AllOf, typename... NoneOf>
static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
static constexpr auto group(exclude_t<NoneOf...> = {}) noexcept {
return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{};
}
@@ -95,7 +88,7 @@ struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule
* @return The updated collector.
*/
template<typename AnyOf>
static constexpr auto replace() ENTT_NOEXCEPT {
static constexpr auto update() noexcept {
return basic_collector<matcher<type_list<>, type_list<>, AnyOf>, current_type, Other...>{};
}
@@ -106,16 +99,14 @@ struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule
* @return The updated collector.
*/
template<typename... AllOf, typename... NoneOf>
static constexpr auto where(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
static constexpr auto where(exclude_t<NoneOf...> = {}) noexcept {
using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>;
return basic_collector<extended_type, Other...>{};
}
};
/*! @brief Variable template used to ease the definition of collectors. */
constexpr basic_collector<> collector{};
inline constexpr basic_collector<> collector{};
/**
* @brief Observer.
@@ -129,8 +120,8 @@ constexpr basic_collector<> collector{};
* collector:
*
* * Observing matcher: an observer will return at least all the living entities
* for which one or more of the given components have been explicitly
* replaced and not yet destroyed.
* for which one or more of the given components have been updated and not yet
* destroyed.
* * Grouping matcher: an observer will return at least all the living entities
* that would have entered the given group if it existed and that would have
* not yet left it.
@@ -159,16 +150,16 @@ constexpr basic_collector<> collector{};
* behavior.
*
* @warning
* Lifetime of an observer doesn't necessarily have to overcome the one of the
* Lifetime of an observer doesn't necessarily have to overcome that of the
* registry to which it is connected. However, the observer must be disconnected
* from the registry before being destroyed to avoid crashes due to dangling
* pointers.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Registry Basic registry type.
*/
template<typename Entity>
class basic_observer {
using payload_type = std::uint32_t;
template<typename Registry>
class basic_observer: private basic_storage<std::uint32_t, typename Registry::entity_type> {
using base_type = basic_storage<std::uint32_t, typename Registry::entity_type>;
template<typename>
struct matcher_handler;
@@ -176,70 +167,78 @@ class basic_observer {
template<typename... Reject, typename... Require, typename AnyOf>
struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
template<std::size_t Index>
static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
if(reg.template has<Require...>(entt) && !(reg.template has<Reject>(entt) || ...)) {
if(auto *comp = obs.view.try_get(entt); !comp) {
obs.view.construct(entt);
static void maybe_valid_if(basic_observer &obs, Registry &reg, const typename Registry::entity_type entt) {
if(reg.template all_of<Require...>(entt) && !reg.template any_of<Reject...>(entt)) {
if(!obs.contains(entt)) {
obs.emplace(entt);
}
obs.view.get(entt) |= (1 << Index);
obs.get(entt) |= (1 << Index);
}
}
template<std::size_t Index>
static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
obs.view.destroy(entt);
static void discard_if(basic_observer &obs, Registry &, const typename Registry::entity_type entt) {
if(obs.contains(entt) && !(obs.get(entt) &= (~(1 << Index)))) {
obs.erase(entt);
}
}
template<std::size_t Index>
static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
static void connect(basic_observer &obs, Registry &reg) {
(reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
(reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
reg.template on_replace<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
reg.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
}
static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
static void disconnect(basic_observer &obs, Registry &reg) {
(reg.template on_destroy<Require>().disconnect(obs), ...);
(reg.template on_construct<Reject>().disconnect(obs), ...);
reg.template on_replace<AnyOf>().disconnect(obs);
reg.template on_update<AnyOf>().disconnect(obs);
reg.template on_destroy<AnyOf>().disconnect(obs);
}
};
template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
template<std::size_t Index>
static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
if(reg.template has<AllOf..., Require...>(entt) && !(reg.template has<NoneOf>(entt) || ...) && !(reg.template has<Reject>(entt) || ...)) {
if(auto *comp = obs.view.try_get(entt); !comp) {
obs.view.construct(entt);
template<std::size_t Index, typename... Ignore>
static void maybe_valid_if(basic_observer &obs, Registry &reg, const typename Registry::entity_type entt) {
auto condition = [&reg, entt]() {
if constexpr(sizeof...(Ignore) == 0) {
return reg.template all_of<AllOf..., Require...>(entt) && !reg.template any_of<NoneOf..., Reject...>(entt);
} else {
return reg.template all_of<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !reg.template any_of<NoneOf>(entt)) && ...) && !reg.template any_of<Reject...>(entt);
}
};
if(condition()) {
if(!obs.contains(entt)) {
obs.emplace(entt);
}
obs.view.get(entt) |= (1 << Index);
obs.get(entt) |= (1 << Index);
}
}
template<std::size_t Index>
static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
obs.view.destroy(entt);
static void discard_if(basic_observer &obs, Registry &, const typename Registry::entity_type entt) {
if(obs.contains(entt) && !(obs.get(entt) &= (~(1 << Index)))) {
obs.erase(entt);
}
}
template<std::size_t Index>
static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
static void connect(basic_observer &obs, Registry &reg) {
(reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
(reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
(reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
(reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
(reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(obs), ...);
(reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
(reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
}
static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
static void disconnect(basic_observer &obs, Registry &reg) {
(reg.template on_destroy<Require>().disconnect(obs), ...);
(reg.template on_construct<Reject>().disconnect(obs), ...);
(reg.template on_construct<AllOf>().disconnect(obs), ...);
@@ -250,29 +249,30 @@ class basic_observer {
};
template<typename... Matcher>
static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
static void disconnect(Registry &reg, basic_observer &obs) {
(matcher_handler<Matcher>::disconnect(obs, reg), ...);
}
template<typename... Matcher, std::size_t... Index>
void connect(basic_registry<Entity> &reg, std::index_sequence<Index...>) {
static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits);
void connect(Registry &reg, std::index_sequence<Index...>) {
static_assert(sizeof...(Matcher) < std::numeric_limits<typename base_type::value_type>::digits, "Too many matchers");
(matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
release = &basic_observer::disconnect<Matcher...>;
release.template connect<&basic_observer::disconnect<Matcher...>>(reg);
}
public:
/*! Basic registry type. */
using registry_type = Registry;
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
using entity_type = typename registry_type::entity_type;
/*! @brief Unsigned integer type. */
using size_type = std::size_t;
/*! @brief Input iterator type. */
using iterator_type = typename sparse_set<Entity>::iterator_type;
/*! @brief Random access iterator type. */
using iterator = typename registry_type::base_type::iterator;
/*! @brief Default constructor. */
basic_observer()
: target{}, release{}, view{}
{}
: release{} {}
/*! @brief Default copy constructor, deleted on purpose. */
basic_observer(const basic_observer &) = delete;
@@ -285,11 +285,8 @@ public:
* @param reg A valid reference to a registry.
*/
template<typename... Matcher>
basic_observer(basic_registry<entity_type> &reg, basic_collector<Matcher...>)
: target{&reg},
release{},
view{}
{
basic_observer(registry_type &reg, basic_collector<Matcher...>)
: basic_observer{} {
connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
}
@@ -300,13 +297,13 @@ public:
* @brief Default copy assignment operator, deleted on purpose.
* @return This observer.
*/
basic_observer & operator=(const basic_observer &) = delete;
basic_observer &operator=(const basic_observer &) = delete;
/**
* @brief Default move assignment operator, deleted on purpose.
* @return This observer.
*/
basic_observer & operator=(basic_observer &&) = delete;
basic_observer &operator=(basic_observer &&) = delete;
/**
* @brief Connects an observer to a given registry.
@@ -314,18 +311,17 @@ public:
* @param reg A valid reference to a registry.
*/
template<typename... Matcher>
void connect(basic_registry<entity_type> &reg, basic_collector<Matcher...>) {
void connect(registry_type &reg, basic_collector<Matcher...>) {
disconnect();
connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
target = &reg;
view.clear();
base_type::clear();
}
/*! @brief Disconnects an observer from the registry it keeps track of. */
void disconnect() {
if(release) {
release(*this, *target);
release = nullptr;
release(*this);
release.reset();
}
}
@@ -333,32 +329,32 @@ public:
* @brief Returns the number of elements in an observer.
* @return Number of elements.
*/
size_type size() const ENTT_NOEXCEPT {
return view.size();
[[nodiscard]] size_type size() const noexcept {
return base_type::size();
}
/**
* @brief Checks whether an observer is empty.
* @return True if the observer is empty, false otherwise.
*/
bool empty() const ENTT_NOEXCEPT {
return view.empty();
[[nodiscard]] bool empty() const noexcept {
return base_type::empty();
}
/**
* @brief Direct access to the list of entities of the observer.
*
* The returned pointer is such that range `[data(), data() + size()]` is
* The returned pointer is such that range `[data(), data() + size())` is
* always a valid range, even if the container is empty.
*
* @note
* There are no guarantees on the order of the entities. Use `begin` and
* `end` if you want to iterate the observer in the expected order.
* Entities are in the reverse order as returned by the `begin`/`end`
* iterators.
*
* @return A pointer to the array of entities.
*/
const entity_type * data() const ENTT_NOEXCEPT {
return view.data();
[[nodiscard]] const entity_type *data() const noexcept {
return base_type::data();
}
/**
@@ -369,8 +365,8 @@ public:
*
* @return An iterator to the first entity of the observer.
*/
iterator_type begin() const ENTT_NOEXCEPT {
return view.sparse_set<entity_type>::begin();
[[nodiscard]] iterator begin() const noexcept {
return base_type::base_type::begin();
}
/**
@@ -383,13 +379,13 @@ public:
* @return An iterator to the entity following the last entity of the
* observer.
*/
iterator_type end() const ENTT_NOEXCEPT {
return view.sparse_set<entity_type>::end();
[[nodiscard]] iterator end() const noexcept {
return base_type::base_type::end();
}
/*! @brief Clears the underlying container. */
void clear() ENTT_NOEXCEPT {
view.clear();
void clear() noexcept {
base_type::clear();
}
/**
@@ -407,8 +403,6 @@ public:
*/
template<typename Func>
void each(Func func) const {
static_assert(std::is_invocable_v<Func, entity_type>);
for(const auto entity: *this) {
func(entity);
}
@@ -430,13 +424,9 @@ public:
}
private:
basic_registry<entity_type> *target;
void(* release)(basic_observer &, basic_registry<entity_type> &);
storage<entity_type, payload_type> view;
delegate<void(basic_observer &)> release;
};
}
} // namespace entt
#endif

View File

@@ -0,0 +1,412 @@
#ifndef ENTT_ENTITY_ORGANIZER_HPP
#define ENTT_ENTITY_ORGANIZER_HPP
#include <cstddef>
#include <type_traits>
#include <utility>
#include <vector>
#include "../core/type_info.hpp"
#include "../core/type_traits.hpp"
#include "../core/utility.hpp"
#include "../graph/adjacency_matrix.hpp"
#include "../graph/flow.hpp"
#include "fwd.hpp"
#include "helper.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename>
struct is_view: std::false_type {};
template<typename... Args>
struct is_view<basic_view<Args...>>: std::true_type {};
template<typename Type>
inline constexpr bool is_view_v = is_view<Type>::value;
template<typename Type, typename Override>
struct unpack_type {
using ro = std::conditional_t<
type_list_contains_v<Override, const Type> || (std::is_const_v<Type> && !type_list_contains_v<Override, std::remove_const_t<Type>>),
type_list<std::remove_const_t<Type>>,
type_list<>>;
using rw = std::conditional_t<
type_list_contains_v<Override, std::remove_const_t<Type>> || (!std::is_const_v<Type> && !type_list_contains_v<Override, const Type>),
type_list<Type>,
type_list<>>;
};
template<typename... Args, typename... Override>
struct unpack_type<basic_registry<Args...>, type_list<Override...>> {
using ro = type_list<>;
using rw = type_list<>;
};
template<typename... Args, typename... Override>
struct unpack_type<const basic_registry<Args...>, type_list<Override...>>
: unpack_type<basic_registry<Args...>, type_list<Override...>> {};
template<typename... Get, typename... Exclude, typename... Override>
struct unpack_type<basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {
using ro = type_list_cat_t<type_list<typename Exclude::value_type...>, typename unpack_type<constness_as_t<typename Get::value_type, Get>, type_list<Override...>>::ro...>;
using rw = type_list_cat_t<typename unpack_type<constness_as_t<typename Get::value_type, Get>, type_list<Override...>>::rw...>;
};
template<typename... Get, typename... Exclude, typename... Override>
struct unpack_type<const basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>>
: unpack_type<basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {};
template<typename, typename>
struct resource_traits;
template<typename... Args, typename... Req>
struct resource_traits<type_list<Args...>, type_list<Req...>> {
using args = type_list<std::remove_const_t<Args>...>;
using ro = type_list_cat_t<typename unpack_type<Args, type_list<Req...>>::ro..., typename unpack_type<Req, type_list<>>::ro...>;
using rw = type_list_cat_t<typename unpack_type<Args, type_list<Req...>>::rw..., typename unpack_type<Req, type_list<>>::rw...>;
};
template<typename... Req, typename Ret, typename... Args>
resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> free_function_to_resource_traits(Ret (*)(Args...));
template<typename... Req, typename Ret, typename Type, typename... Args>
resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (*)(Type &, Args...));
template<typename... Req, typename Ret, typename Class, typename... Args>
resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...));
template<typename... Req, typename Ret, typename Class, typename... Args>
resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...) const);
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Utility class for creating a static task graph.
*
* This class offers minimal support (but sufficient in many cases) for creating
* an execution graph from functions and their requirements on resources.<br/>
* Note that the resulting tasks aren't executed in any case. This isn't the
* goal of the tool. Instead, they are returned to the user in the form of a
* graph that allows for safe execution.
*
* @tparam Registry Basic registry type.
*/
template<typename Registry>
class basic_organizer final {
using callback_type = void(const void *, Registry &);
using prepare_type = void(Registry &);
using dependency_type = std::size_t(const bool, const type_info **, const std::size_t);
struct vertex_data final {
std::size_t ro_count{};
std::size_t rw_count{};
const char *name{};
const void *payload{};
callback_type *callback{};
dependency_type *dependency;
prepare_type *prepare{};
const type_info *info{};
};
template<typename Type>
[[nodiscard]] static decltype(auto) extract(Registry &reg) {
if constexpr(std::is_same_v<Type, Registry>) {
return reg;
} else if constexpr(internal::is_view_v<Type>) {
return as_view{reg};
} else {
return reg.ctx().template emplace<std::remove_reference_t<Type>>();
}
}
template<typename... Args>
[[nodiscard]] static auto to_args(Registry &reg, type_list<Args...>) {
return std::tuple<decltype(extract<Args>(reg))...>(extract<Args>(reg)...);
}
template<typename... Type>
static std::size_t fill_dependencies(type_list<Type...>, [[maybe_unused]] const type_info **buffer, [[maybe_unused]] const std::size_t count) {
if constexpr(sizeof...(Type) == 0u) {
return {};
} else {
const type_info *info[sizeof...(Type)]{&type_id<Type>()...};
const auto length = count < sizeof...(Type) ? count : sizeof...(Type);
for(std::size_t pos{}; pos < length; ++pos) {
buffer[pos] = info[pos];
}
return length;
}
}
template<typename... RO, typename... RW>
void track_dependencies(std::size_t index, const bool requires_registry, type_list<RO...>, type_list<RW...>) {
builder.bind(static_cast<id_type>(index));
builder.set(type_hash<Registry>::value(), requires_registry || (sizeof...(RO) + sizeof...(RW) == 0u));
(builder.ro(type_hash<RO>::value()), ...);
(builder.rw(type_hash<RW>::value()), ...);
}
public:
/*! Basic registry type. */
using registry_type = Registry;
/*! @brief Underlying entity identifier. */
using entity_type = typename registry_type::entity_type;
/*! @brief Unsigned integer type. */
using size_type = std::size_t;
/*! @brief Raw task function type. */
using function_type = callback_type;
/*! @brief Vertex type of a task graph defined as an adjacency list. */
struct vertex {
/**
* @brief Constructs a vertex of the task graph.
* @param vtype True if the vertex is a top-level one, false otherwise.
* @param data The data associated with the vertex.
* @param edges The indices of the children in the adjacency list.
*/
vertex(const bool vtype, vertex_data data, std::vector<std::size_t> edges)
: is_top_level{vtype},
node{std::move(data)},
reachable{std::move(edges)} {}
/**
* @brief Fills a buffer with the type info objects for the writable
* resources of a vertex.
* @param buffer A buffer pre-allocated by the user.
* @param length The length of the user-supplied buffer.
* @return The number of type info objects written to the buffer.
*/
size_type ro_dependency(const type_info **buffer, const std::size_t length) const noexcept {
return node.dependency(false, buffer, length);
}
/**
* @brief Fills a buffer with the type info objects for the read-only
* resources of a vertex.
* @param buffer A buffer pre-allocated by the user.
* @param length The length of the user-supplied buffer.
* @return The number of type info objects written to the buffer.
*/
size_type rw_dependency(const type_info **buffer, const std::size_t length) const noexcept {
return node.dependency(true, buffer, length);
}
/**
* @brief Returns the number of read-only resources of a vertex.
* @return The number of read-only resources of the vertex.
*/
size_type ro_count() const noexcept {
return node.ro_count;
}
/**
* @brief Returns the number of writable resources of a vertex.
* @return The number of writable resources of the vertex.
*/
size_type rw_count() const noexcept {
return node.rw_count;
}
/**
* @brief Checks if a vertex is also a top-level one.
* @return True if the vertex is a top-level one, false otherwise.
*/
bool top_level() const noexcept {
return is_top_level;
}
/**
* @brief Returns a type info object associated with a vertex.
* @return A properly initialized type info object.
*/
const type_info &info() const noexcept {
return *node.info;
}
/**
* @brief Returns a user defined name associated with a vertex, if any.
* @return The user defined name associated with the vertex, if any.
*/
const char *name() const noexcept {
return node.name;
}
/**
* @brief Returns the function associated with a vertex.
* @return The function associated with the vertex.
*/
function_type *callback() const noexcept {
return node.callback;
}
/**
* @brief Returns the payload associated with a vertex, if any.
* @return The payload associated with the vertex, if any.
*/
const void *data() const noexcept {
return node.payload;
}
/**
* @brief Returns the list of nodes reachable from a given vertex.
* @return The list of nodes reachable from the vertex.
*/
const std::vector<std::size_t> &children() const noexcept {
return reachable;
}
/**
* @brief Prepares a registry and assures that all required resources
* are properly instantiated before using them.
* @param reg A valid registry.
*/
void prepare(registry_type &reg) const {
node.prepare ? node.prepare(reg) : void();
}
private:
bool is_top_level;
vertex_data node;
std::vector<std::size_t> reachable;
};
/**
* @brief Adds a free function to the task list.
* @tparam Candidate Function to add to the task list.
* @tparam Req Additional requirements and/or override resource access mode.
* @param name Optional name to associate with the task.
*/
template<auto Candidate, typename... Req>
void emplace(const char *name = nullptr) {
using resource_type = decltype(internal::free_function_to_resource_traits<Req...>(Candidate));
constexpr auto requires_registry = type_list_contains_v<typename resource_type::args, registry_type>;
callback_type *callback = +[](const void *, registry_type &reg) {
std::apply(Candidate, to_args(reg, typename resource_type::args{}));
};
vertex_data vdata{
resource_type::ro::size,
resource_type::rw::size,
name,
nullptr,
callback,
+[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); },
+[](registry_type &reg) { void(to_args(reg, typename resource_type::args{})); },
&type_id<std::integral_constant<decltype(Candidate), Candidate>>()};
track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{});
vertices.push_back(std::move(vdata));
}
/**
* @brief Adds a free function with payload or a member function with an
* instance to the task list.
* @tparam Candidate Function or member to add to the task list.
* @tparam Req Additional requirements and/or override resource access mode.
* @tparam Type Type of class or type of payload.
* @param value_or_instance A valid object that fits the purpose.
* @param name Optional name to associate with the task.
*/
template<auto Candidate, typename... Req, typename Type>
void emplace(Type &value_or_instance, const char *name = nullptr) {
using resource_type = decltype(internal::constrained_function_to_resource_traits<Req...>(Candidate));
constexpr auto requires_registry = type_list_contains_v<typename resource_type::args, registry_type>;
callback_type *callback = +[](const void *payload, registry_type &reg) {
Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
std::apply(Candidate, std::tuple_cat(std::forward_as_tuple(*curr), to_args(reg, typename resource_type::args{})));
};
vertex_data vdata{
resource_type::ro::size,
resource_type::rw::size,
name,
&value_or_instance,
callback,
+[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); },
+[](registry_type &reg) { void(to_args(reg, typename resource_type::args{})); },
&type_id<std::integral_constant<decltype(Candidate), Candidate>>()};
track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{});
vertices.push_back(std::move(vdata));
}
/**
* @brief Adds an user defined function with optional payload to the task
* list.
* @tparam Req Additional requirements and/or override resource access mode.
* @param func Function to add to the task list.
* @param payload User defined arbitrary data.
* @param name Optional name to associate with the task.
*/
template<typename... Req>
void emplace(function_type *func, const void *payload = nullptr, const char *name = nullptr) {
using resource_type = internal::resource_traits<type_list<>, type_list<Req...>>;
track_dependencies(vertices.size(), true, typename resource_type::ro{}, typename resource_type::rw{});
vertex_data vdata{
resource_type::ro::size,
resource_type::rw::size,
name,
payload,
func,
+[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); },
nullptr,
&type_id<void>()};
vertices.push_back(std::move(vdata));
}
/**
* @brief Generates a task graph for the current content.
* @return The adjacency list of the task graph.
*/
std::vector<vertex> graph() {
std::vector<vertex> adjacency_list{};
adjacency_list.reserve(vertices.size());
auto adjacency_matrix = builder.graph();
for(auto curr: adjacency_matrix.vertices()) {
const auto iterable = adjacency_matrix.in_edges(curr);
std::vector<std::size_t> reachable{};
for(auto &&edge: adjacency_matrix.out_edges(curr)) {
reachable.push_back(edge.second);
}
adjacency_list.emplace_back(iterable.cbegin() == iterable.cend(), vertices[curr], std::move(reachable));
}
return adjacency_list;
}
/*! @brief Erases all elements from a container. */
void clear() {
builder.clear();
vertices.clear();
}
private:
std::vector<vertex_data> vertices;
flow builder;
};
} // namespace entt
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,108 @@
#ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
#define ENTT_ENTITY_RUNTIME_VIEW_HPP
#include <iterator>
#include <vector>
#include <utility>
#include <algorithm>
#include <type_traits>
#include "../config/config.h"
#include "sparse_set.hpp"
#include <cstddef>
#include <iterator>
#include <utility>
#include <vector>
#include "entity.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename Set>
class runtime_view_iterator final {
using iterator_type = typename Set::iterator;
[[nodiscard]] bool valid() const {
return (!tombstone_check || *it != tombstone)
&& std::all_of(++pools->begin(), pools->end(), [entt = *it](const auto *curr) { return curr->contains(entt); })
&& std::none_of(filter->cbegin(), filter->cend(), [entt = *it](const auto *curr) { return curr && curr->contains(entt); });
}
public:
using difference_type = typename iterator_type::difference_type;
using value_type = typename iterator_type::value_type;
using pointer = typename iterator_type::pointer;
using reference = typename iterator_type::reference;
using iterator_category = std::bidirectional_iterator_tag;
constexpr runtime_view_iterator() noexcept
: pools{},
filter{},
it{},
tombstone_check{} {}
runtime_view_iterator(const std::vector<Set *> &cpools, const std::vector<Set *> &ignore, iterator_type curr) noexcept
: pools{&cpools},
filter{&ignore},
it{curr},
tombstone_check{pools->size() == 1u && (*pools)[0u]->policy() == deletion_policy::in_place} {
if(it != (*pools)[0]->end() && !valid()) {
++(*this);
}
}
runtime_view_iterator &operator++() {
while(++it != (*pools)[0]->end() && !valid()) {}
return *this;
}
runtime_view_iterator operator++(int) {
runtime_view_iterator orig = *this;
return ++(*this), orig;
}
runtime_view_iterator &operator--() {
while(--it != (*pools)[0]->begin() && !valid()) {}
return *this;
}
runtime_view_iterator operator--(int) {
runtime_view_iterator orig = *this;
return operator--(), orig;
}
[[nodiscard]] pointer operator->() const noexcept {
return it.operator->();
}
[[nodiscard]] reference operator*() const noexcept {
return *operator->();
}
[[nodiscard]] constexpr bool operator==(const runtime_view_iterator &other) const noexcept {
return it == other.it;
}
[[nodiscard]] constexpr bool operator!=(const runtime_view_iterator &other) const noexcept {
return !(*this == other);
}
private:
const std::vector<Set *> *pools;
const std::vector<Set *> *filter;
iterator_type it;
bool tombstone_check;
};
} // namespace internal
/**
* @brief Runtime view.
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Generic runtime view.
*
* Runtime views iterate over those entities that have at least all the given
* components in their bags. During initialization, a runtime view looks at the
@@ -49,125 +134,133 @@ namespace entt {
* have a valid reference and won't be updated accordingly).
*
* @warning
* Lifetime of a view must overcome the one of the registry that generated it.
* Lifetime of a view must not overcome that of the registry that generated it.
* In any other case, attempting to use a view results in undefined behavior.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Type Common base type.
* @tparam Allocator Type of allocator used to manage memory and elements.
*/
template<typename Entity>
template<typename Type, typename Allocator>
class basic_runtime_view {
/*! @brief A registry is allowed to create views. */
friend class basic_registry<Entity>;
using underlying_iterator_type = typename sparse_set<Entity>::iterator_type;
class iterator {
friend class basic_runtime_view<Entity>;
using direct_type = std::vector<const sparse_set<Entity> *>;
iterator(const direct_type *all, underlying_iterator_type curr) ENTT_NOEXCEPT
: pools{all},
it{curr}
{
if(it != (*pools)[0]->end() && !valid()) {
++(*this);
}
}
bool valid() const {
return std::all_of(pools->begin()++, pools->end(), [entt = *it](const auto *curr) {
return curr->has(entt);
});
}
public:
using difference_type = typename underlying_iterator_type::difference_type;
using value_type = typename underlying_iterator_type::value_type;
using pointer = typename underlying_iterator_type::pointer;
using reference = typename underlying_iterator_type::reference;
using iterator_category = std::bidirectional_iterator_tag;
iterator() ENTT_NOEXCEPT = default;
iterator & operator++() {
while(++it != (*pools)[0]->end() && !valid());
return *this;
}
iterator operator++(int) {
iterator orig = *this;
return operator++(), orig;
}
iterator & operator--() ENTT_NOEXCEPT {
while(--it != (*pools)[0]->begin() && !valid());
return *this;
}
iterator operator--(int) ENTT_NOEXCEPT {
iterator orig = *this;
return operator--(), orig;
}
bool operator==(const iterator &other) const ENTT_NOEXCEPT {
return other.it == it;
}
bool operator!=(const iterator &other) const ENTT_NOEXCEPT {
return !(*this == other);
}
pointer operator->() const {
return it.operator->();
}
reference operator*() const {
return *operator->();
}
private:
const direct_type *pools;
underlying_iterator_type it;
};
basic_runtime_view(std::vector<const sparse_set<Entity> *> others) ENTT_NOEXCEPT
: pools{std::move(others)}
{
const auto it = std::min_element(pools.begin(), pools.end(), [](const auto *lhs, const auto *rhs) {
return (!lhs && rhs) || (lhs && rhs && lhs->size() < rhs->size());
});
// brings the best candidate (if any) on front of the vector
std::rotate(pools.begin(), it, pools.end());
}
bool valid() const {
return !pools.empty() && pools.front();
}
using alloc_traits = std::allocator_traits<Allocator>;
static_assert(std::is_same_v<typename alloc_traits::value_type, Type *>, "Invalid value type");
using container_type = std::vector<Type *, Allocator>;
public:
/*! @brief Allocator type. */
using allocator_type = Allocator;
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
using entity_type = typename Type::entity_type;
/*! @brief Unsigned integer type. */
using size_type = std::size_t;
/*! @brief Input iterator type. */
using iterator_type = iterator;
/*! @brief Common type among all storage types. */
using base_type = Type;
/*! @brief Bidirectional iterator type. */
using iterator = internal::runtime_view_iterator<base_type>;
/*! @brief Default constructor to use to create empty, invalid views. */
basic_runtime_view() noexcept
: basic_runtime_view{allocator_type{}} {}
/**
* @brief Estimates the number of entities that have the given components.
* @return Estimated number of entities that have the given components.
* @brief Constructs an empty, invalid view with a given allocator.
* @param allocator The allocator to use.
*/
size_type size() const {
return valid() ? pools.front()->size() : size_type{};
explicit basic_runtime_view(const allocator_type &allocator)
: pools{allocator},
filter{allocator} {}
/*! @brief Default copy constructor. */
basic_runtime_view(const basic_runtime_view &) = default;
/**
* @brief Allocator-extended copy constructor.
* @param other The instance to copy from.
* @param allocator The allocator to use.
*/
basic_runtime_view(const basic_runtime_view &other, const allocator_type &allocator)
: pools{other.pools, allocator},
filter{other.filter, allocator} {}
/*! @brief Default move constructor. */
basic_runtime_view(basic_runtime_view &&) noexcept(std::is_nothrow_move_constructible_v<container_type>) = default;
/**
* @brief Allocator-extended move constructor.
* @param other The instance to move from.
* @param allocator The allocator to use.
*/
basic_runtime_view(basic_runtime_view &&other, const allocator_type &allocator)
: pools{std::move(other.pools), allocator},
filter{std::move(other.filter), allocator} {}
/**
* @brief Default copy assignment operator.
* @return This container.
*/
basic_runtime_view &operator=(const basic_runtime_view &) = default;
/**
* @brief Default move assignment operator.
* @return This container.
*/
basic_runtime_view &operator=(basic_runtime_view &&) noexcept(std::is_nothrow_move_assignable_v<container_type>) = default;
/**
* @brief Exchanges the contents with those of a given view.
* @param other View to exchange the content with.
*/
void swap(basic_runtime_view &other) {
using std::swap;
swap(pools, other.pools);
swap(filter, other.filter);
}
/**
* @brief Checks if the view is definitely empty.
* @return True if the view is definitely empty, false otherwise.
* @brief Returns the associated allocator.
* @return The associated allocator.
*/
bool empty() const {
return !valid() || pools.front()->empty();
[[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
return pools.get_allocator();
}
/*! @brief Clears the view. */
void clear() {
pools.clear();
filter.clear();
}
/**
* @brief Appends an opaque storage object to a runtime view.
* @param base An opaque reference to a storage object.
* @return This runtime view.
*/
basic_runtime_view &iterate(base_type &base) {
if(pools.empty() || !(base.size() < pools[0u]->size())) {
pools.push_back(&base);
} else {
pools.push_back(std::exchange(pools[0u], &base));
}
return *this;
}
/**
* @brief Adds an opaque storage object as a filter of a runtime view.
* @param base An opaque reference to a storage object.
* @return This runtime view.
*/
basic_runtime_view &exclude(base_type &base) {
filter.push_back(&base);
return *this;
}
/**
* @brief Estimates the number of entities iterated by the view.
* @return Estimated number of entities iterated by the view.
*/
[[nodiscard]] size_type size_hint() const {
return pools.empty() ? size_type{} : pools.front()->size();
}
/**
@@ -178,20 +271,10 @@ public:
* components. If the view is empty, the returned iterator will be equal to
* `end()`.
*
* @note
* Input iterators stay true to the order imposed to the underlying data
* structures.
*
* @return An iterator to the first entity that has the given components.
*/
iterator_type begin() const {
iterator_type it{};
if(valid()) {
it = { &pools, pools[0]->begin() };
}
return it;
[[nodiscard]] iterator begin() const {
return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->begin()};
}
/**
@@ -202,32 +285,22 @@ public:
* has the given components. Attempting to dereference the returned iterator
* results in undefined behavior.
*
* @note
* Input iterators stay true to the order imposed to the underlying data
* structures.
*
* @return An iterator to the entity following the last entity that has the
* given components.
*/
iterator_type end() const {
iterator_type it{};
if(valid()) {
it = { &pools, pools[0]->end() };
}
return it;
[[nodiscard]] iterator end() const {
return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->end()};
}
/**
* @brief Checks if a view contains an entity.
* @param entt A valid entity identifier.
* @param entt A valid identifier.
* @return True if the view contains the given entity, false otherwise.
*/
bool contains(const entity_type entt) const {
return valid() && std::all_of(pools.cbegin(), pools.cend(), [entt](const auto *view) {
return view->find(entt) != view->end();
});
[[nodiscard]] bool contains(const entity_type entt) const {
return !pools.empty()
&& std::all_of(pools.cbegin(), pools.cend(), [entt](const auto *curr) { return curr->contains(entt); })
&& std::none_of(filter.cbegin(), filter.cend(), [entt](const auto *curr) { return curr && curr->contains(entt); });
}
/**
@@ -253,11 +326,10 @@ public:
}
private:
std::vector<const sparse_set<Entity> *> pools;
container_type pools;
container_type filter;
};
}
} // namespace entt
#endif

View File

@@ -1,21 +1,23 @@
#ifndef ENTT_ENTITY_SNAPSHOT_HPP
#define ENTT_ENTITY_SNAPSHOT_HPP
#include <array>
#include <cstddef>
#include <utility>
#include <iterator>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include "../config/config.h"
#include "../container/dense_map.hpp"
#include "../core/type_traits.hpp"
#include "component.hpp"
#include "entity.hpp"
#include "fwd.hpp"
#include "view.hpp"
namespace entt {
/**
* @brief Utility class to create snapshots from a registry.
*
@@ -24,99 +26,77 @@ namespace entt {
* This type can be used in both cases if provided with a correctly configured
* output archive.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Registry Basic registry type.
*/
template<typename Entity>
template<typename Registry>
class basic_snapshot {
/*! @brief A registry is allowed to create snapshots. */
friend class basic_registry<Entity>;
using follow_fn_type = Entity(const basic_registry<Entity> &, const Entity);
using traits_type = entt_traits<std::underlying_type_t<Entity>>;
basic_snapshot(const basic_registry<Entity> *source, Entity init, follow_fn_type *fn) ENTT_NOEXCEPT
: reg{source},
seed{init},
follow{fn}
{}
using entity_traits = entt_traits<typename Registry::entity_type>;
template<typename Component, typename Archive, typename It>
void get(Archive &archive, std::size_t sz, It first, It last) const {
archive(typename traits_type::entity_type(sz));
const auto view = reg->template view<const Component>();
archive(typename entity_traits::entity_type(sz));
while(first != last) {
const auto entt = *(first++);
if(reg->template has<Component>(entt)) {
if constexpr(std::is_empty_v<Component>) {
archive(entt);
} else {
archive(entt, reg->template get<Component>(entt));
}
if(reg->template all_of<Component>(entt)) {
std::apply(archive, std::tuple_cat(std::make_tuple(entt), view.get(entt)));
}
}
}
template<typename... Component, typename Archive, typename It, std::size_t... Indexes>
void component(Archive &archive, It first, It last, std::index_sequence<Indexes...>) const {
std::array<std::size_t, sizeof...(Indexes)> size{};
template<typename... Component, typename Archive, typename It, std::size_t... Index>
void component(Archive &archive, It first, It last, std::index_sequence<Index...>) const {
std::array<std::size_t, sizeof...(Index)> size{};
auto begin = first;
while(begin != last) {
const auto entt = *(begin++);
((reg->template has<Component>(entt) ? ++size[Indexes] : size[Indexes]), ...);
((reg->template all_of<Component>(entt) ? ++size[Index] : 0u), ...);
}
(get<Component>(archive, size[Indexes], first, last), ...);
(get<Component>(archive, size[Index], first, last), ...);
}
public:
/*! Basic registry type. */
using registry_type = Registry;
/*! @brief Underlying entity identifier. */
using entity_type = typename registry_type::entity_type;
/**
* @brief Constructs an instance that is bound to a given registry.
* @param source A valid reference to a registry.
*/
basic_snapshot(const registry_type &source) noexcept
: reg{&source} {}
/*! @brief Default move constructor. */
basic_snapshot(basic_snapshot &&) = default;
basic_snapshot(basic_snapshot &&) noexcept = default;
/*! @brief Default move assignment operator. @return This snapshot. */
basic_snapshot & operator=(basic_snapshot &&) = default;
basic_snapshot &operator=(basic_snapshot &&) noexcept = default;
/**
* @brief Puts aside all the entities that are still in use.
* @brief Puts aside all the entities from the underlying registry.
*
* Entities are serialized along with their versions. Destroyed entities are
* not taken in consideration by this function.
* taken in consideration as well by this function.
*
* @tparam Archive Type of output archive.
* @param archive A valid reference to an output archive.
* @return An object of this type to continue creating the snapshot.
*/
template<typename Archive>
const basic_snapshot & entities(Archive &archive) const {
archive(typename traits_type::entity_type(reg->alive()));
reg->each([&archive](const auto entt) { archive(entt); });
return *this;
}
const basic_snapshot &entities(Archive &archive) const {
const auto sz = reg->size();
/**
* @brief Puts aside destroyed entities.
*
* Entities are serialized along with their versions. Entities that are
* still in use are not taken in consideration by this function.
*
* @tparam Archive Type of output archive.
* @param archive A valid reference to an output archive.
* @return An object of this type to continue creating the snapshot.
*/
template<typename Archive>
const basic_snapshot & destroyed(Archive &archive) const {
auto size = reg->size() - reg->alive();
archive(typename traits_type::entity_type(size));
archive(typename entity_traits::entity_type(sz + 1u));
archive(reg->released());
if(size) {
auto curr = seed;
archive(curr);
for(--size; size; --size) {
curr = follow(*reg, curr);
archive(curr);
}
for(auto first = reg->data(), last = first + sz; first != last; ++first) {
archive(*first);
}
return *this;
@@ -134,9 +114,15 @@ public:
* @return An object of this type to continue creating the snapshot.
*/
template<typename... Component, typename Archive>
const basic_snapshot & component(Archive &archive) const {
(component<Component>(archive, reg->template data<Component>(), reg->template data<Component>() + reg->template size<Component>()), ...);
return *this;
const basic_snapshot &component(Archive &archive) const {
if constexpr(sizeof...(Component) == 1u) {
const auto view = reg->template view<const Component...>();
(component<Component>(archive, view.rbegin(), view.rend()), ...);
return *this;
} else {
(component<Component>(archive), ...);
return *this;
}
}
/**
@@ -154,18 +140,15 @@ public:
* @return An object of this type to continue creating the snapshot.
*/
template<typename... Component, typename Archive, typename It>
const basic_snapshot & component(Archive &archive, It first, It last) const {
const basic_snapshot &component(Archive &archive, It first, It last) const {
component<Component...>(archive, first, last, std::index_sequence_for<Component...>{});
return *this;
}
private:
const basic_registry<Entity> *reg;
const Entity seed;
follow_fn_type *follow;
const registry_type *reg;
};
/**
* @brief Utility class to restore a snapshot as a whole.
*
@@ -174,64 +157,59 @@ private:
* originally had.<br/>
* An example of use is the implementation of a save/restore utility.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Registry Basic registry type.
*/
template<typename Entity>
template<typename Registry>
class basic_snapshot_loader {
/*! @brief A registry is allowed to create snapshot loaders. */
friend class basic_registry<Entity>;
using entity_traits = entt_traits<typename Registry::entity_type>;
using force_fn_type = void(basic_registry<Entity> &, const Entity, const bool);
using traits_type = entt_traits<std::underlying_type_t<Entity>>;
template<typename Component, typename Archive>
void assign(Archive &archive) const {
typename entity_traits::entity_type length{};
entity_type entt;
basic_snapshot_loader(basic_registry<Entity> *source, force_fn_type *fn) ENTT_NOEXCEPT
: reg{source},
force{fn}
{
// to restore a snapshot as a whole requires a clean registry
ENTT_ASSERT(reg->empty());
}
template<typename Archive>
void assure(Archive &archive, bool discard) const {
typename traits_type::entity_type length{};
archive(length);
while(length--) {
Entity entt{};
archive(entt);
force(*reg, entt, discard);
}
}
template<typename Type, typename Archive, typename... Args>
void assign(Archive &archive, Args... args) const {
typename traits_type::entity_type length{};
archive(length);
while(length--) {
static constexpr auto discard = false;
Entity entt{};
if constexpr(std::is_empty_v<Type>) {
if constexpr(ignore_as_empty_v<Component>) {
while(length--) {
archive(entt);
force(*reg, entt, discard);
reg->template assign<Type>(args..., entt);
} else {
Type instance{};
const auto entity = reg->valid(entt) ? entt : reg->create(entt);
ENTT_ASSERT(entity == entt, "Entity not available for use");
reg->template emplace<Component>(entt);
}
} else {
Component instance;
while(length--) {
archive(entt, instance);
force(*reg, entt, discard);
reg->template assign<Type>(args..., entt, std::as_const(instance));
const auto entity = reg->valid(entt) ? entt : reg->create(entt);
ENTT_ASSERT(entity == entt, "Entity not available for use");
reg->template emplace<Component>(entt, std::move(instance));
}
}
}
public:
/*! Basic registry type. */
using registry_type = Registry;
/*! @brief Underlying entity identifier. */
using entity_type = typename registry_type::entity_type;
/**
* @brief Constructs an instance that is bound to a given registry.
* @param source A valid reference to a registry.
*/
basic_snapshot_loader(registry_type &source) noexcept
: reg{&source} {
// restoring a snapshot as a whole requires a clean registry
ENTT_ASSERT(reg->empty(), "Registry must be empty");
}
/*! @brief Default move constructor. */
basic_snapshot_loader(basic_snapshot_loader &&) = default;
basic_snapshot_loader(basic_snapshot_loader &&) noexcept = default;
/*! @brief Default move assignment operator. @return This loader. */
basic_snapshot_loader & operator=(basic_snapshot_loader &&) = default;
basic_snapshot_loader &operator=(basic_snapshot_loader &&) noexcept = default;
/**
* @brief Restores entities that were in use during serialization.
@@ -244,26 +222,18 @@ public:
* @return A valid loader to continue restoring data.
*/
template<typename Archive>
const basic_snapshot_loader & entities(Archive &archive) const {
static constexpr auto discard = false;
assure(archive, discard);
return *this;
}
const basic_snapshot_loader &entities(Archive &archive) const {
typename entity_traits::entity_type length{};
archive(length);
std::vector<entity_type> all(length);
for(std::size_t pos{}; pos < length; ++pos) {
archive(all[pos]);
}
reg->assign(++all.cbegin(), all.cend(), all[0u]);
/**
* @brief Restores entities that were destroyed during serialization.
*
* This function restores the entities that were destroyed during
* serialization and gives them the versions they originally had.
*
* @tparam Archive Type of input archive.
* @param archive A valid reference to an input archive.
* @return A valid loader to continue restoring data.
*/
template<typename Archive>
const basic_snapshot_loader & destroyed(Archive &archive) const {
static constexpr auto discard = true;
assure(archive, discard);
return *this;
}
@@ -281,7 +251,7 @@ public:
* @return A valid loader to continue restoring data.
*/
template<typename... Component, typename Archive>
const basic_snapshot_loader & component(Archive &archive) const {
const basic_snapshot_loader &component(Archive &archive) const {
(assign<Component>(archive), ...);
return *this;
}
@@ -296,25 +266,25 @@ public:
*
* @return A valid loader to continue restoring data.
*/
const basic_snapshot_loader & orphans() const {
reg->orphans([this](const auto entt) {
reg->destroy(entt);
const basic_snapshot_loader &orphans() const {
reg->each([this](const auto entt) {
if(reg->orphan(entt)) {
reg->release(entt);
}
});
return *this;
}
private:
basic_registry<Entity> *reg;
force_fn_type *force;
registry_type *reg;
};
/**
* @brief Utility class for _continuous loading_.
*
* A _continuous loader_ is designed to load data from a source registry to a
* (possibly) non-empty destination. The loader can accomodate in a registry
* (possibly) non-empty destination. The loader can accommodate in a registry
* more than one snapshot in a sort of _continuous loading_ that updates the
* destination one step at a time.<br/>
* Identifiers that entities originally had are not transferred to the target.
@@ -324,38 +294,38 @@ private:
* the requirement of transferring somehow parts of the representation side to
* side.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Registry Basic registry type.
*/
template<typename Entity>
template<typename Registry>
class basic_continuous_loader {
using traits_type = entt_traits<std::underlying_type_t<Entity>>;
using entity_traits = entt_traits<typename Registry::entity_type>;
void destroy(Entity entt) {
const auto it = remloc.find(entt);
if(it == remloc.cend()) {
void destroy(typename Registry::entity_type entt) {
if(const auto it = remloc.find(entt); it == remloc.cend()) {
const auto local = reg->create();
remloc.emplace(entt, std::make_pair(local, true));
reg->destroy(local);
}
}
void restore(Entity entt) {
void restore(typename Registry::entity_type entt) {
const auto it = remloc.find(entt);
if(it == remloc.cend()) {
const auto local = reg->create();
remloc.emplace(entt, std::make_pair(local, true));
} else {
remloc[entt].first = reg->valid(remloc[entt].first) ? remloc[entt].first : reg->create();
if(!reg->valid(remloc[entt].first)) {
remloc[entt].first = reg->create();
}
// set the dirty flag
remloc[entt].second = true;
}
}
template<typename Container>
auto update(int, Container &container)
-> decltype(typename Container::mapped_type{}, void()) {
auto update(int, Container &container) -> decltype(typename Container::mapped_type{}, void()) {
// map like container
Container other;
@@ -363,35 +333,35 @@ class basic_continuous_loader {
using first_type = std::remove_const_t<typename std::decay_t<decltype(pair)>::first_type>;
using second_type = typename std::decay_t<decltype(pair)>::second_type;
if constexpr(std::is_same_v<first_type, Entity> && std::is_same_v<second_type, Entity>) {
if constexpr(std::is_same_v<first_type, entity_type> && std::is_same_v<second_type, entity_type>) {
other.emplace(map(pair.first), map(pair.second));
} else if constexpr(std::is_same_v<first_type, Entity>) {
} else if constexpr(std::is_same_v<first_type, entity_type>) {
other.emplace(map(pair.first), std::move(pair.second));
} else {
static_assert(std::is_same_v<second_type, Entity>);
static_assert(std::is_same_v<second_type, entity_type>, "Neither the key nor the value are of entity type");
other.emplace(std::move(pair.first), map(pair.second));
}
}
std::swap(container, other);
using std::swap;
swap(container, other);
}
template<typename Container>
auto update(char, Container &container)
-> decltype(typename Container::value_type{}, void()) {
auto update(char, Container &container) -> decltype(typename Container::value_type{}, void()) {
// vector like container
static_assert(std::is_same_v<typename Container::value_type, Entity>);
static_assert(std::is_same_v<typename Container::value_type, entity_type>, "Invalid value type");
for(auto &&entt: container) {
entt = map(entt);
}
}
template<typename Other, typename Type, typename Member>
void update([[maybe_unused]] Other &instance, [[maybe_unused]] Member Type:: *member) {
if constexpr(!std::is_same_v<Other, Type>) {
template<typename Component, typename Other, typename Member>
void update([[maybe_unused]] Component &instance, [[maybe_unused]] Member Other::*member) {
if constexpr(!std::is_same_v<Component, Other>) {
return;
} else if constexpr(std::is_same_v<Member, Entity>) {
} else if constexpr(std::is_same_v<Member, entity_type>) {
instance.*member = map(instance.*member);
} else {
// maybe a container? let's try...
@@ -399,68 +369,60 @@ class basic_continuous_loader {
}
}
template<typename Archive>
void assure(Archive &archive, void(basic_continuous_loader:: *member)(Entity)) {
typename traits_type::entity_type length{};
archive(length);
while(length--) {
Entity entt{};
archive(entt);
(this->*member)(entt);
}
}
template<typename Component>
void reset() {
void remove_if_exists() {
for(auto &&ref: remloc) {
const auto local = ref.second.first;
if(reg->valid(local)) {
reg->template remove_if_exists<Component>(local);
reg->template remove<Component>(local);
}
}
}
template<typename Other, typename Archive, typename... Type, typename... Member>
void assign(Archive &archive, [[maybe_unused]] Member Type:: *... member) {
typename traits_type::entity_type length{};
template<typename Component, typename Archive, typename... Other, typename... Member>
void assign(Archive &archive, [[maybe_unused]] Member Other::*...member) {
typename entity_traits::entity_type length{};
entity_type entt;
archive(length);
while(length--) {
Entity entt{};
if constexpr(std::is_empty_v<Other>) {
if constexpr(ignore_as_empty_v<Component>) {
while(length--) {
archive(entt);
restore(entt);
reg->template assign_or_replace<Other>(map(entt));
} else {
Other instance{};
reg->template emplace_or_replace<Component>(map(entt));
}
} else {
Component instance;
while(length--) {
archive(entt, instance);
(update(instance, member), ...);
restore(entt);
reg->template assign_or_replace<Other>(map(entt), std::as_const(instance));
reg->template emplace_or_replace<Component>(map(entt), std::move(instance));
}
}
}
public:
/*! Basic registry type. */
using registry_type = Registry;
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
using entity_type = typename registry_type::entity_type;
/**
* @brief Constructs a loader that is bound to a given registry.
* @brief Constructs an instance that is bound to a given registry.
* @param source A valid reference to a registry.
*/
basic_continuous_loader(basic_registry<entity_type> &source) ENTT_NOEXCEPT
: reg{&source}
{}
basic_continuous_loader(registry_type &source) noexcept
: reg{&source} {}
/*! @brief Default move constructor. */
basic_continuous_loader(basic_continuous_loader &&) = default;
/*! @brief Default move assignment operator. @return This loader. */
basic_continuous_loader & operator=(basic_continuous_loader &&) = default;
basic_continuous_loader &operator=(basic_continuous_loader &&) = default;
/**
* @brief Restores entities that were in use during serialization.
@@ -473,24 +435,24 @@ public:
* @return A non-const reference to this loader.
*/
template<typename Archive>
basic_continuous_loader & entities(Archive &archive) {
assure(archive, &basic_continuous_loader::restore);
return *this;
}
basic_continuous_loader &entities(Archive &archive) {
typename entity_traits::entity_type length{};
entity_type entt{};
archive(length);
// discards the head of the list of destroyed entities
archive(entt);
for(std::size_t pos{}, last = length - 1u; pos < last; ++pos) {
archive(entt);
if(const auto entity = entity_traits::to_entity(entt); entity == pos) {
restore(entt);
} else {
destroy(entt);
}
}
/**
* @brief Restores entities that were destroyed during serialization.
*
* This function restores the entities that were destroyed during
* serialization and creates local counterparts for them if required.
*
* @tparam Archive Type of input archive.
* @param archive A valid reference to an input archive.
* @return A non-const reference to this loader.
*/
template<typename Archive>
basic_continuous_loader & destroyed(Archive &archive) {
assure(archive, &basic_continuous_loader::destroy);
return *this;
}
@@ -507,15 +469,15 @@ public:
*
* @tparam Component Type of component to restore.
* @tparam Archive Type of input archive.
* @tparam Type Types of components to update with local counterparts.
* @tparam Other Types of components to update with local counterparts.
* @tparam Member Types of members to update with their local counterparts.
* @param archive A valid reference to an input archive.
* @param member Members to update with their local counterparts.
* @return A non-const reference to this loader.
*/
template<typename... Component, typename Archive, typename... Type, typename... Member>
basic_continuous_loader & component(Archive &archive, Member Type:: *... member) {
(reset<Component>(), ...);
template<typename... Component, typename Archive, typename... Other, typename... Member>
basic_continuous_loader &component(Archive &archive, Member Other::*...member) {
(remove_if_exists<Component>(), ...);
(assign<Component>(archive, member...), ...);
return *this;
}
@@ -528,7 +490,7 @@ public:
*
* @return A non-const reference to this loader.
*/
basic_continuous_loader & shrink() {
basic_continuous_loader &shrink() {
auto it = remloc.begin();
while(it != remloc.cend()) {
@@ -560,9 +522,11 @@ public:
*
* @return A non-const reference to this loader.
*/
basic_continuous_loader & orphans() {
reg->orphans([this](const auto entt) {
reg->destroy(entt);
basic_continuous_loader &orphans() {
reg->each([this](const auto entt) {
if(reg->orphan(entt)) {
reg->release(entt);
}
});
return *this;
@@ -570,19 +534,19 @@ public:
/**
* @brief Tests if a loader knows about a given entity.
* @param entt An entity identifier.
* @param entt A valid identifier.
* @return True if `entity` is managed by the loader, false otherwise.
*/
bool has(entity_type entt) const ENTT_NOEXCEPT {
[[nodiscard]] bool contains(entity_type entt) const noexcept {
return (remloc.find(entt) != remloc.cend());
}
/**
* @brief Returns the identifier to which an entity refers.
* @param entt An entity identifier.
* @param entt A valid identifier.
* @return The local identifier if any, the null entity otherwise.
*/
entity_type map(entity_type entt) const ENTT_NOEXCEPT {
[[nodiscard]] entity_type map(entity_type entt) const noexcept {
const auto it = remloc.find(entt);
entity_type other = null;
@@ -594,12 +558,10 @@ public:
}
private:
std::unordered_map<entity_type, std::pair<entity_type, bool>> remloc;
basic_registry<entity_type> *reg;
dense_map<entity_type, std::pair<entity_type, bool>> remloc;
registry_type *reg;
};
}
} // namespace entt
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,236 @@
#ifndef ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP
#define ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP
#include <utility>
#include "../config/config.h"
#include "../core/any.hpp"
#include "../signal/sigh.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @brief Mixin type used to add signal support to storage types.
*
* The function type of a listener is equivalent to:
*
* @code{.cpp}
* void(basic_registry<entity_type> &, entity_type);
* @endcode
*
* This applies to all signals made available.
*
* @tparam Type The type of the underlying storage.
*/
template<typename Type>
class sigh_storage_mixin final: public Type {
using basic_registry_type = basic_registry<typename Type::entity_type, typename Type::base_type::allocator_type>;
using sigh_type = sigh<void(basic_registry_type &, const typename Type::entity_type), typename Type::allocator_type>;
using basic_iterator = typename Type::basic_iterator;
void pop(basic_iterator first, basic_iterator last) override {
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
for(; first != last; ++first) {
const auto entt = *first;
destruction.publish(*owner, entt);
const auto it = Type::find(entt);
Type::pop(it, it + 1u);
}
}
basic_iterator try_emplace(const typename basic_registry_type::entity_type entt, const bool force_back, const void *value) final {
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
Type::try_emplace(entt, force_back, value);
construction.publish(*owner, entt);
return Type::find(entt);
}
public:
/*! @brief Allocator type. */
using allocator_type = typename Type::allocator_type;
/*! @brief Underlying entity identifier. */
using entity_type = typename Type::entity_type;
/*! @brief Expected registry type. */
using registry_type = basic_registry_type;
/*! @brief Default constructor. */
sigh_storage_mixin()
: sigh_storage_mixin{allocator_type{}} {}
/**
* @brief Constructs an empty storage with a given allocator.
* @param allocator The allocator to use.
*/
explicit sigh_storage_mixin(const allocator_type &allocator)
: Type{allocator},
owner{},
construction{allocator},
destruction{allocator},
update{allocator} {}
/**
* @brief Move constructor.
* @param other The instance to move from.
*/
sigh_storage_mixin(sigh_storage_mixin &&other) noexcept
: Type{std::move(other)},
owner{other.owner},
construction{std::move(other.construction)},
destruction{std::move(other.destruction)},
update{std::move(other.update)} {}
/**
* @brief Allocator-extended move constructor.
* @param other The instance to move from.
* @param allocator The allocator to use.
*/
sigh_storage_mixin(sigh_storage_mixin &&other, const allocator_type &allocator) noexcept
: Type{std::move(other), allocator},
owner{other.owner},
construction{std::move(other.construction), allocator},
destruction{std::move(other.destruction), allocator},
update{std::move(other.update), allocator} {}
/**
* @brief Move assignment operator.
* @param other The instance to move from.
* @return This storage.
*/
sigh_storage_mixin &operator=(sigh_storage_mixin &&other) noexcept {
Type::operator=(std::move(other));
owner = other.owner;
construction = std::move(other.construction);
destruction = std::move(other.destruction);
update = std::move(other.update);
return *this;
}
/**
* @brief Exchanges the contents with those of a given storage.
* @param other Storage to exchange the content with.
*/
void swap(sigh_storage_mixin &other) {
using std::swap;
Type::swap(other);
swap(owner, other.owner);
swap(construction, other.construction);
swap(destruction, other.destruction);
swap(update, other.update);
}
/**
* @brief Returns a sink object.
*
* The sink returned by this function can be used to receive notifications
* whenever a new instance is created and assigned to an entity.<br/>
* Listeners are invoked after the object has been assigned to the entity.
*
* @sa sink
*
* @return A temporary sink object.
*/
[[nodiscard]] auto on_construct() noexcept {
return sink{construction};
}
/**
* @brief Returns a sink object.
*
* The sink returned by this function can be used to receive notifications
* whenever an instance is explicitly updated.<br/>
* Listeners are invoked after the object has been updated.
*
* @sa sink
*
* @return A temporary sink object.
*/
[[nodiscard]] auto on_update() noexcept {
return sink{update};
}
/**
* @brief Returns a sink object.
*
* The sink returned by this function can be used to receive notifications
* whenever an instance is removed from an entity and thus destroyed.<br/>
* Listeners are invoked before the object has been removed from the entity.
*
* @sa sink
*
* @return A temporary sink object.
*/
[[nodiscard]] auto on_destroy() noexcept {
return sink{destruction};
}
/**
* @brief Assigns entities to a storage.
* @tparam Args Types of arguments to use to construct the object.
* @param entt A valid identifier.
* @param args Parameters to use to initialize the object.
* @return A reference to the newly created object.
*/
template<typename... Args>
decltype(auto) emplace(const entity_type entt, Args &&...args) {
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
Type::emplace(entt, std::forward<Args>(args)...);
construction.publish(*owner, entt);
return this->get(entt);
}
/**
* @brief Patches the given instance for an entity.
* @tparam Func Types of the function objects to invoke.
* @param entt A valid identifier.
* @param func Valid function objects.
* @return A reference to the patched instance.
*/
template<typename... Func>
decltype(auto) patch(const entity_type entt, Func &&...func) {
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
Type::patch(entt, std::forward<Func>(func)...);
update.publish(*owner, entt);
return this->get(entt);
}
/**
* @brief Assigns entities to a storage.
* @tparam It Type of input iterator.
* @tparam Args Types of arguments to use to construct the objects assigned
* to the entities.
* @param first An iterator to the first element of the range of entities.
* @param last An iterator past the last element of the range of entities.
* @param args Parameters to use to initialize the objects assigned to the
* entities.
*/
template<typename It, typename... Args>
void insert(It first, It last, Args &&...args) {
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
Type::insert(first, last, std::forward<Args>(args)...);
for(auto it = construction.empty() ? last : first; it != last; ++it) {
construction.publish(*owner, *it);
}
}
/**
* @brief Forwards variables to derived classes, if any.
* @param value A variable wrapped in an opaque container.
*/
void bind(any value) noexcept final {
auto *reg = any_cast<basic_registry_type>(&value);
owner = reg ? reg : owner;
Type::bind(std::move(value));
}
private:
basic_registry_type *owner;
sigh_type construction;
sigh_type destruction;
sigh_type update;
};
} // namespace entt
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +1,64 @@
// IWYU pragma: begin_exports
#include "config/config.h"
#include "config/macro.h"
#include "config/version.h"
#include "container/dense_map.hpp"
#include "container/dense_set.hpp"
#include "core/algorithm.hpp"
#include "core/any.hpp"
#include "core/attribute.h"
#include "core/compressed_pair.hpp"
#include "core/enum.hpp"
#include "core/family.hpp"
#include "core/hashed_string.hpp"
#include "core/ident.hpp"
#include "core/iterator.hpp"
#include "core/memory.hpp"
#include "core/monostate.hpp"
#include "core/tuple.hpp"
#include "core/type_info.hpp"
#include "core/type_traits.hpp"
#include "core/utility.hpp"
#include "entity/actor.hpp"
#include "entity/component.hpp"
#include "entity/entity.hpp"
#include "entity/group.hpp"
#include "entity/handle.hpp"
#include "entity/helper.hpp"
#include "entity/observer.hpp"
#include "entity/organizer.hpp"
#include "entity/registry.hpp"
#include "entity/runtime_view.hpp"
#include "entity/snapshot.hpp"
#include "entity/sparse_set.hpp"
#include "entity/storage.hpp"
#include "entity/storage_mixin.hpp"
#include "entity/view.hpp"
#include "graph/adjacency_matrix.hpp"
#include "graph/dot.hpp"
#include "graph/flow.hpp"
#include "locator/locator.hpp"
#include "meta/adl_pointer.hpp"
#include "meta/container.hpp"
#include "meta/context.hpp"
#include "meta/factory.hpp"
#include "meta/meta.hpp"
#include "meta/node.hpp"
#include "meta/pointer.hpp"
#include "meta/policy.hpp"
#include "meta/range.hpp"
#include "meta/resolve.hpp"
#include "meta/template.hpp"
#include "meta/type_traits.hpp"
#include "meta/utility.hpp"
#include "platform/android-ndk-r17.hpp"
#include "poly/poly.hpp"
#include "process/process.hpp"
#include "process/scheduler.hpp"
#include "resource/cache.hpp"
#include "resource/handle.hpp"
#include "resource/loader.hpp"
#include "resource/resource.hpp"
#include "signal/delegate.hpp"
#include "signal/dispatcher.hpp"
#include "signal/emitter.hpp"
#include "signal/sigh.hpp"
// IWYU pragma: end_exports

View File

@@ -1,3 +1,11 @@
// IWYU pragma: begin_exports
#include "container/fwd.hpp"
#include "core/fwd.hpp"
#include "entity/fwd.hpp"
#include "graph/fwd.hpp"
#include "meta/fwd.hpp"
#include "poly/fwd.hpp"
#include "process/fwd.hpp"
#include "resource/fwd.hpp"
#include "signal/fwd.hpp"
// IWYU pragma: end_exports

View File

@@ -0,0 +1,348 @@
#ifndef ENTT_GRAPH_ADJACENCY_MATRIX_HPP
#define ENTT_GRAPH_ADJACENCY_MATRIX_HPP
#include <cstddef>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector>
#include "../config/config.h"
#include "../core/iterator.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename It>
class edge_iterator {
using size_type = std::size_t;
public:
using value_type = std::pair<size_type, size_type>;
using pointer = input_iterator_pointer<value_type>;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category = std::input_iterator_tag;
constexpr edge_iterator() noexcept
: it{},
vert{},
pos{},
last{},
offset{} {}
constexpr edge_iterator(It base, const size_type vertices, const size_type from, const size_type to, const size_type step) noexcept
: it{std::move(base)},
vert{vertices},
pos{from},
last{to},
offset{step} {
for(; pos != last && !it[pos]; pos += offset) {}
}
constexpr edge_iterator &operator++() noexcept {
for(pos += offset; pos != last && !it[pos]; pos += offset) {}
return *this;
}
constexpr edge_iterator operator++(int) noexcept {
edge_iterator orig = *this;
return ++(*this), orig;
}
[[nodiscard]] constexpr reference operator*() const noexcept {
return *operator->();
}
[[nodiscard]] constexpr pointer operator->() const noexcept {
return std::make_pair<size_type>(pos / vert, pos % vert);
}
template<typename Type>
friend constexpr bool operator==(const edge_iterator<Type> &, const edge_iterator<Type> &) noexcept;
private:
It it;
size_type vert;
size_type pos;
size_type last;
size_type offset{};
};
template<typename Container>
[[nodiscard]] inline constexpr bool operator==(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
return lhs.pos == rhs.pos;
}
template<typename Container>
[[nodiscard]] inline constexpr bool operator!=(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
return !(lhs == rhs);
}
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Basic implementation of a directed adjacency matrix.
* @tparam Category Either a directed or undirected category tag.
* @tparam Allocator Type of allocator used to manage memory and elements.
*/
template<typename Category, typename Allocator>
class adjacency_matrix {
using alloc_traits = std::allocator_traits<Allocator>;
static_assert(std::is_base_of_v<directed_tag, Category>, "Invalid graph category");
static_assert(std::is_same_v<typename alloc_traits::value_type, std::size_t>, "Invalid value type");
using container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
public:
/*! @brief Allocator type. */
using allocator_type = Allocator;
/*! @brief Unsigned integer type. */
using size_type = std::size_t;
/*! @brief Vertex type. */
using vertex_type = size_type;
/*! @brief Edge type. */
using edge_type = std::pair<vertex_type, vertex_type>;
/*! @brief Vertex iterator type. */
using vertex_iterator = iota_iterator<vertex_type>;
/*! @brief Edge iterator type. */
using edge_iterator = internal::edge_iterator<typename container_type::const_iterator>;
/*! @brief Out edge iterator type. */
using out_edge_iterator = edge_iterator;
/*! @brief In edge iterator type. */
using in_edge_iterator = edge_iterator;
/*! @brief Graph category tag. */
using graph_category = Category;
/*! @brief Default constructor. */
adjacency_matrix() noexcept(noexcept(allocator_type{}))
: adjacency_matrix{0u} {}
/**
* @brief Constructs an empty container with a given allocator.
* @param allocator The allocator to use.
*/
explicit adjacency_matrix(const allocator_type &allocator) noexcept
: adjacency_matrix{0u, allocator} {}
/**
* @brief Constructs an empty container with a given allocator and user
* supplied number of vertices.
* @param vertices Number of vertices.
* @param allocator The allocator to use.
*/
adjacency_matrix(const size_type vertices, const allocator_type &allocator = allocator_type{})
: matrix{vertices * vertices, allocator},
vert{vertices} {}
/**
* @brief Copy constructor.
* @param other The instance to copy from.
*/
adjacency_matrix(const adjacency_matrix &other)
: adjacency_matrix{other, other.get_allocator()} {}
/**
* @brief Allocator-extended copy constructor.
* @param other The instance to copy from.
* @param allocator The allocator to use.
*/
adjacency_matrix(const adjacency_matrix &other, const allocator_type &allocator)
: matrix{other.matrix, allocator},
vert{other.vert} {}
/**
* @brief Move constructor.
* @param other The instance to move from.
*/
adjacency_matrix(adjacency_matrix &&other) noexcept
: adjacency_matrix{std::move(other), other.get_allocator()} {}
/**
* @brief Allocator-extended move constructor.
* @param other The instance to move from.
* @param allocator The allocator to use.
*/
adjacency_matrix(adjacency_matrix &&other, const allocator_type &allocator)
: matrix{std::move(other.matrix), allocator},
vert{std::exchange(other.vert, 0u)} {}
/**
* @brief Default copy assignment operator.
* @param other The instance to copy from.
* @return This container.
*/
adjacency_matrix &operator=(const adjacency_matrix &other) {
matrix = other.matrix;
vert = other.vert;
return *this;
}
/**
* @brief Default move assignment operator.
* @param other The instance to move from.
* @return This container.
*/
adjacency_matrix &operator=(adjacency_matrix &&other) noexcept {
matrix = std::move(other.matrix);
vert = std::exchange(other.vert, 0u);
return *this;
}
/**
* @brief Returns the associated allocator.
* @return The associated allocator.
*/
[[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
return matrix.get_allocator();
}
/*! @brief Clears the adjacency matrix. */
void clear() noexcept {
matrix.clear();
vert = {};
}
/**
* @brief Exchanges the contents with those of a given adjacency matrix.
* @param other Adjacency matrix to exchange the content with.
*/
void swap(adjacency_matrix &other) {
using std::swap;
swap(matrix, other.matrix);
swap(vert, other.vert);
}
/**
* @brief Returns the number of vertices.
* @return The number of vertices.
*/
[[nodiscard]] size_type size() const noexcept {
return vert;
}
/**
* @brief Returns an iterable object to visit all vertices of a matrix.
* @return An iterable object to visit all vertices of a matrix.
*/
[[nodiscard]] iterable_adaptor<vertex_iterator> vertices() const noexcept {
return {0u, vert};
}
/**
* @brief Returns an iterable object to visit all edges of a matrix.
* @return An iterable object to visit all edges of a matrix.
*/
[[nodiscard]] iterable_adaptor<edge_iterator> edges() const noexcept {
const auto it = matrix.cbegin();
const auto sz = matrix.size();
return {{it, vert, 0u, sz, 1u}, {it, vert, sz, sz, 1u}};
}
/**
* @brief Returns an iterable object to visit all out edges of a vertex.
* @param vertex The vertex of which to return all out edges.
* @return An iterable object to visit all out edges of a vertex.
*/
[[nodiscard]] iterable_adaptor<out_edge_iterator> out_edges(const vertex_type vertex) const noexcept {
const auto it = matrix.cbegin();
const auto from = vertex * vert;
const auto to = vertex * vert + vert;
return {{it, vert, from, to, 1u}, {it, vert, to, to, 1u}};
}
/**
* @brief Returns an iterable object to visit all in edges of a vertex.
* @param vertex The vertex of which to return all in edges.
* @return An iterable object to visit all in edges of a vertex.
*/
[[nodiscard]] iterable_adaptor<in_edge_iterator> in_edges(const vertex_type vertex) const noexcept {
const auto it = matrix.cbegin();
const auto from = vertex;
const auto to = vert * (vert - 1u) + vertex;
return {{it, vert, from, to, vert}, {it, vert, to, to, vert}};
}
/**
* @brief Resizes an adjacency matrix.
* @param vertices The new number of vertices.
*/
void resize(const size_type vertices) {
adjacency_matrix other{vertices, get_allocator()};
for(auto [lhs, rhs]: edges()) {
other.insert(lhs, rhs);
}
other.swap(*this);
}
/**
* @brief Inserts an edge into the adjacency matrix, if it does not exist.
* @param lhs The left hand vertex of the edge.
* @param rhs The right hand vertex of the edge.
* @return A pair consisting of an iterator to the inserted element (or to
* the element that prevented the insertion) and a bool denoting whether the
* insertion took place.
*/
std::pair<edge_iterator, bool> insert(const vertex_type lhs, const vertex_type rhs) {
const auto pos = lhs * vert + rhs;
if constexpr(std::is_same_v<graph_category, undirected_tag>) {
const auto rev = rhs * vert + lhs;
ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
matrix[rev] = 1u;
}
const auto inserted = !std::exchange(matrix[pos], 1u);
return {edge_iterator{matrix.cbegin(), vert, pos, matrix.size(), 1u}, inserted};
}
/**
* @brief Removes the edge associated with a pair of given vertices.
* @param lhs The left hand vertex of the edge.
* @param rhs The right hand vertex of the edge.
* @return Number of elements removed (either 0 or 1).
*/
size_type erase(const vertex_type lhs, const vertex_type rhs) {
const auto pos = lhs * vert + rhs;
if constexpr(std::is_same_v<graph_category, undirected_tag>) {
const auto rev = rhs * vert + lhs;
ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
matrix[rev] = 0u;
}
return std::exchange(matrix[pos], 0u);
}
/**
* @brief Checks if an adjacency matrix contains a given edge.
* @param lhs The left hand vertex of the edge.
* @param rhs The right hand vertex of the edge.
* @return True if there is such an edge, false otherwise.
*/
[[nodiscard]] bool contains(const vertex_type lhs, const vertex_type rhs) const {
const auto pos = lhs * vert + rhs;
return pos < matrix.size() && matrix[pos];
}
private:
container_type matrix;
size_type vert;
};
} // namespace entt
#endif

58
src/entt/graph/dot.hpp Normal file
View File

@@ -0,0 +1,58 @@
#ifndef ENTT_GRAPH_DOT_HPP
#define ENTT_GRAPH_DOT_HPP
#include <ostream>
#include <type_traits>
#include "fwd.hpp"
namespace entt {
/**
* @brief Outputs a graph in dot format.
* @tparam Graph Graph type, valid as long as it exposes edges and vertices.
* @tparam Writer Vertex decorator type.
* @param out A standard output stream.
* @param graph The graph to output.
* @param writer Vertex decorator object.
*/
template<typename Graph, typename Writer>
void dot(std::ostream &out, const Graph &graph, Writer writer) {
static_assert(std::is_base_of_v<directed_tag, typename Graph::graph_category>, "Invalid graph category");
if constexpr(std::is_same_v<typename Graph::graph_category, undirected_tag>) {
out << "graph{";
} else {
out << "digraph{";
}
for(auto &&vertex: graph.vertices()) {
out << vertex << "[";
writer(out, vertex);
out << "];";
}
for(auto [lhs, rhs]: graph.edges()) {
if constexpr(std::is_same_v<typename Graph::graph_category, undirected_tag>) {
out << lhs << "--" << rhs << ";";
} else {
out << lhs << "->" << rhs << ";";
}
}
out << "}";
}
/**
* @brief Outputs a graph in dot format.
* @tparam Graph Graph type, valid as long as it exposes edges and vertices.
* @param out A standard output stream.
* @param graph The graph to output.
*/
template<typename Graph>
void dot(std::ostream &out, const Graph &graph) {
return dot(out, graph, [](auto &&...) {});
}
} // namespace entt
#endif

327
src/entt/graph/flow.hpp Normal file
View File

@@ -0,0 +1,327 @@
#ifndef ENTT_GRAPH_FLOW_HPP
#define ENTT_GRAPH_FLOW_HPP
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector>
#include "../config/config.h"
#include "../container/dense_map.hpp"
#include "../container/dense_set.hpp"
#include "../core/compressed_pair.hpp"
#include "../core/fwd.hpp"
#include "../core/iterator.hpp"
#include "../core/utility.hpp"
#include "adjacency_matrix.hpp"
#include "fwd.hpp"
namespace entt {
/**
* @brief Utility class for creating task graphs.
* @tparam Allocator Type of allocator used to manage memory and elements.
*/
template<typename Allocator>
class basic_flow {
using alloc_traits = std::allocator_traits<Allocator>;
static_assert(std::is_same_v<typename alloc_traits::value_type, id_type>, "Invalid value type");
using task_container_type = dense_set<id_type, identity, std::equal_to<id_type>, typename alloc_traits::template rebind_alloc<id_type>>;
using ro_rw_container_type = std::vector<std::pair<std::size_t, bool>, typename alloc_traits::template rebind_alloc<std::pair<std::size_t, bool>>>;
using deps_container_type = dense_map<id_type, ro_rw_container_type, identity, std::equal_to<id_type>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, ro_rw_container_type>>>;
void emplace(const id_type res, const bool is_rw) {
ENTT_ASSERT(index.first() < vertices.size(), "Invalid node");
if(!deps.contains(res) && sync_on != vertices.size()) {
deps[res].emplace_back(sync_on, true);
}
deps[res].emplace_back(index.first(), is_rw);
}
public:
/*! @brief Allocator type. */
using allocator_type = Allocator;
/*! @brief Unsigned integer type. */
using size_type = std::size_t;
/*! @brief Iterable task list. */
using iterable = iterable_adaptor<typename task_container_type::const_iterator>;
/*! @brief Default constructor. */
basic_flow()
: basic_flow{allocator_type{}} {}
/**
* @brief Constructs a flow builder with a given allocator.
* @param allocator The allocator to use.
*/
explicit basic_flow(const allocator_type &allocator)
: index{0u, allocator},
vertices{},
deps{},
sync_on{} {}
/*! @brief Default copy constructor. */
basic_flow(const basic_flow &) = default;
/**
* @brief Allocator-extended copy constructor.
* @param other The instance to copy from.
* @param allocator The allocator to use.
*/
basic_flow(const basic_flow &other, const allocator_type &allocator)
: index{other.index.first(), allocator},
vertices{other.vertices, allocator},
deps{other.deps, allocator},
sync_on{other.sync_on} {}
/*! @brief Default move constructor. */
basic_flow(basic_flow &&) noexcept = default;
/**
* @brief Allocator-extended move constructor.
* @param other The instance to move from.
* @param allocator The allocator to use.
*/
basic_flow(basic_flow &&other, const allocator_type &allocator)
: index{other.index.first(), allocator},
vertices{std::move(other.vertices), allocator},
deps{std::move(other.deps), allocator},
sync_on{other.sync_on} {}
/**
* @brief Default copy assignment operator.
* @return This flow builder.
*/
basic_flow &operator=(const basic_flow &) = default;
/**
* @brief Default move assignment operator.
* @return This flow builder.
*/
basic_flow &operator=(basic_flow &&) noexcept = default;
/**
* @brief Returns the associated allocator.
* @return The associated allocator.
*/
[[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
return allocator_type{index.second()};
}
/**
* @brief Returns the identifier at specified location.
* @param pos Position of the identifier to return.
* @return The requested identifier.
*/
[[nodiscard]] id_type operator[](const size_type pos) const {
return vertices.cbegin()[pos];
}
/*! @brief Clears the flow builder. */
void clear() noexcept {
index.first() = sync_on = {};
vertices.clear();
deps.clear();
}
/**
* @brief Exchanges the contents with those of a given flow builder.
* @param other Flow builder to exchange the content with.
*/
void swap(basic_flow &other) {
using std::swap;
std::swap(index, other.index);
std::swap(vertices, other.vertices);
std::swap(deps, other.deps);
std::swap(sync_on, other.sync_on);
}
/**
* @brief Returns the number of tasks.
* @return The number of tasks.
*/
[[nodiscard]] size_type size() const noexcept {
return vertices.size();
}
/**
* @brief Binds a task to a flow builder.
* @param value Task identifier.
* @return This flow builder.
*/
basic_flow &bind(const id_type value) {
sync_on += (sync_on == vertices.size());
const auto it = vertices.emplace(value).first;
index.first() = size_type(it - vertices.begin());
return *this;
}
/**
* @brief Turns the current task into a sync point.
* @return This flow builder.
*/
basic_flow &sync() {
ENTT_ASSERT(index.first() < vertices.size(), "Invalid node");
sync_on = index.first();
for(const auto &elem: deps) {
elem.second.emplace_back(sync_on, true);
}
return *this;
}
/**
* @brief Assigns a resource to the current task with a given access mode.
* @param res Resource identifier.
* @param is_rw Access mode.
* @return This flow builder.
*/
basic_flow &set(const id_type res, bool is_rw = false) {
emplace(res, is_rw);
return *this;
}
/**
* @brief Assigns a read-only resource to the current task.
* @param res Resource identifier.
* @return This flow builder.
*/
basic_flow &ro(const id_type res) {
emplace(res, false);
return *this;
}
/**
* @brief Assigns a range of read-only resources to the current task.
* @tparam It Type of input iterator.
* @param first An iterator to the first element of the range of elements.
* @param last An iterator past the last element of the range of elements.
* @return This flow builder.
*/
template<typename It>
std::enable_if_t<std::is_same_v<std::remove_const_t<typename std::iterator_traits<It>::value_type>, id_type>, basic_flow &>
ro(It first, It last) {
for(; first != last; ++first) {
emplace(*first, false);
}
return *this;
}
/**
* @brief Assigns a writable resource to the current task.
* @param res Resource identifier.
* @return This flow builder.
*/
basic_flow &rw(const id_type res) {
emplace(res, true);
return *this;
}
/**
* @brief Assigns a range of writable resources to the current task.
* @tparam It Type of input iterator.
* @param first An iterator to the first element of the range of elements.
* @param last An iterator past the last element of the range of elements.
* @return This flow builder.
*/
template<typename It>
std::enable_if_t<std::is_same_v<std::remove_const_t<typename std::iterator_traits<It>::value_type>, id_type>, basic_flow &>
rw(It first, It last) {
for(; first != last; ++first) {
emplace(*first, true);
}
return *this;
}
/**
* @brief Generates a task graph for the current content.
* @return The adjacency matrix of the task graph.
*/
[[nodiscard]] adjacency_matrix<directed_tag> graph() const {
const auto length = vertices.size();
adjacency_matrix<directed_tag> matrix{length};
// creates the adjacency matrix
for(const auto &elem: deps) {
const auto last = elem.second.cend();
auto it = elem.second.cbegin();
while(it != last) {
if(it->second) {
// rw item
if(auto curr = it++; it != last) {
if(it->second) {
matrix.insert(curr->first, it->first);
} else if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
for(; it != next; ++it) {
matrix.insert(curr->first, it->first);
matrix.insert(it->first, next->first);
}
} else {
for(; it != next; ++it) {
matrix.insert(curr->first, it->first);
}
}
}
} else {
// ro item (first iteration only)
if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
for(; it != next; ++it) {
matrix.insert(it->first, next->first);
}
} else {
it = last;
}
}
}
}
// computes the transitive closure
for(std::size_t vk{}; vk < length; ++vk) {
for(std::size_t vi{}; vi < length; ++vi) {
for(std::size_t vj{}; vj < length; ++vj) {
if(matrix.contains(vi, vk) && matrix.contains(vk, vj)) {
matrix.insert(vi, vj);
}
}
}
}
// applies the transitive reduction
for(std::size_t vert{}; vert < length; ++vert) {
matrix.erase(vert, vert);
}
for(std::size_t vj{}; vj < length; ++vj) {
for(std::size_t vi{}; vi < length; ++vi) {
if(matrix.contains(vi, vj)) {
for(std::size_t vk{}; vk < length; ++vk) {
if(matrix.contains(vj, vk)) {
matrix.erase(vi, vk);
}
}
}
}
}
return matrix;
}
private:
compressed_pair<size_type, allocator_type> index;
task_container_type vertices;
deps_container_type deps;
size_type sync_on;
};
} // namespace entt
#endif

27
src/entt/graph/fwd.hpp Normal file
View File

@@ -0,0 +1,27 @@
#ifndef ENTT_GRAPH_FWD_HPP
#define ENTT_GRAPH_FWD_HPP
#include <cstddef>
#include <memory>
#include "../core/fwd.hpp"
namespace entt {
/*! @brief Undirected graph category tag. */
struct directed_tag {};
/*! @brief Directed graph category tag. */
struct undirected_tag: directed_tag {};
template<typename, typename = std::allocator<std::size_t>>
class adjacency_matrix;
template<typename = std::allocator<id_type>>
class basic_flow;
/*! @brief Alias declaration for the most common use case. */
using flow = basic_flow<>;
} // namespace entt
#endif

View File

@@ -1,111 +1,135 @@
#ifndef ENTT_LOCATOR_LOCATOR_HPP
#define ENTT_LOCATOR_LOCATOR_HPP
#include <memory>
#include <utility>
#include "../config/config.h"
namespace entt {
/**
* @brief Service locator, nothing more.
*
* A service locator can be used to do what it promises: locate services.<br/>
* A service locator is used to do what it promises: locate services.<br/>
* Usually service locators are tightly bound to the services they expose and
* thus it's hard to define a general purpose class to do that. This template
* based implementation tries to fill the gap and to get rid of the burden of
* defining a different specific locator for each application.
* thus it's hard to define a general purpose class to do that. This tiny class
* tries to fill the gap and to get rid of the burden of defining a different
* specific locator for each application.
*
* @tparam Service Type of service managed by the locator.
* @note
* Users shouldn't retain references to a service. The recommended way is to
* retrieve the service implementation currently set each and every time the
* need for it arises. The risk is to incur in unexpected behaviors otherwise.
*
* @tparam Service Service type.
*/
template<typename Service>
struct service_locator {
/*! @brief Type of service offered. */
using service_type = Service;
class locator final {
class service_handle {
friend class locator<Service>;
std::shared_ptr<Service> value{};
};
public:
/*! @brief Service type. */
using type = Service;
/*! @brief Service node type. */
using node_type = service_handle;
/*! @brief Default constructor, deleted on purpose. */
service_locator() = delete;
locator() = delete;
/*! @brief Default destructor, deleted on purpose. */
~service_locator() = delete;
~locator() = delete;
/**
* @brief Tests if a valid service implementation is set.
* @return True if the service is set, false otherwise.
* @brief Checks whether a service locator contains a value.
* @return True if the service locator contains a value, false otherwise.
*/
static bool empty() ENTT_NOEXCEPT {
return !static_cast<bool>(service);
[[nodiscard]] static bool has_value() noexcept {
return (service != nullptr);
}
/**
* @brief Returns a weak pointer to a service implementation, if any.
*
* Clients of a service shouldn't retain references to it. The recommended
* way is to retrieve the service implementation currently set each and
* every time the need of using it arises. Otherwise users can incur in
* unexpected behaviors.
*
* @return A reference to the service implementation currently set, if any.
*/
static std::weak_ptr<Service> get() ENTT_NOEXCEPT {
return service;
}
/**
* @brief Returns a weak reference to a service implementation, if any.
*
* Clients of a service shouldn't retain references to it. The recommended
* way is to retrieve the service implementation currently set each and
* every time the need of using it arises. Otherwise users can incur in
* unexpected behaviors.
* @brief Returns a reference to a valid service, if any.
*
* @warning
* In case no service implementation has been set, a call to this function
* results in undefined behavior.
* Invoking this function can result in undefined behavior if the service
* hasn't been set yet.
*
* @return A reference to the service implementation currently set, if any.
* @return A reference to the service currently set, if any.
*/
static Service & ref() ENTT_NOEXCEPT {
[[nodiscard]] static Service &value() noexcept {
ENTT_ASSERT(has_value(), "Service not available");
return *service;
}
/**
* @brief Sets or replaces a service.
* @tparam Impl Type of the new service to use.
* @tparam Args Types of arguments to use to construct the service.
* @param args Parameters to use to construct the service.
* @brief Returns a service if available or sets it from a fallback type.
*
* Arguments are used only if a service doesn't already exist. In all other
* cases, they are discarded.
*
* @tparam Args Types of arguments to use to construct the fallback service.
* @tparam Impl Fallback service type.
* @param args Parameters to use to construct the fallback service.
* @return A reference to a valid service.
*/
template<typename Impl = Service, typename... Args>
static void set(Args &&... args) {
service = std::make_shared<Impl>(std::forward<Args>(args)...);
[[nodiscard]] static Service &value_or(Args &&...args) {
return service ? *service : emplace<Impl>(std::forward<Args>(args)...);
}
/**
* @brief Sets or replaces a service.
* @param ptr Service to use to replace the current one.
* @tparam Impl Service type.
* @tparam Args Types of arguments to use to construct the service.
* @param args Parameters to use to construct the service.
* @return A reference to a valid service.
*/
static void set(std::shared_ptr<Service> ptr) {
ENTT_ASSERT(static_cast<bool>(ptr));
service = std::move(ptr);
template<typename Impl = Service, typename... Args>
static Service &emplace(Args &&...args) {
service = std::make_shared<Impl>(std::forward<Args>(args)...);
return *service;
}
/**
* @brief Resets a service.
*
* The service is no longer valid after a reset.
* @brief Sets or replaces a service using a given allocator.
* @tparam Impl Service type.
* @tparam Allocator Type of allocator used to manage memory and elements.
* @tparam Args Types of arguments to use to construct the service.
* @param alloc The allocator to use.
* @param args Parameters to use to construct the service.
* @return A reference to a valid service.
*/
static void reset() {
service.reset();
template<typename Impl = Service, typename Allocator, typename... Args>
static Service &allocate_emplace(Allocator alloc, Args &&...args) {
service = std::allocate_shared<Impl>(alloc, std::forward<Args>(args)...);
return *service;
}
/**
* @brief Returns a handle to the underlying service.
* @return A handle to the underlying service.
*/
static node_type handle() noexcept {
node_type node{};
node.value = service;
return node;
}
/**
* @brief Resets or replaces a service.
* @param other Optional handle with which to replace the service.
*/
static void reset(const node_type &other = {}) noexcept {
service = other.value;
}
private:
inline static std::shared_ptr<Service> service = nullptr;
// std::shared_ptr because of its type erased allocator which is useful here
inline static std::shared_ptr<Service> service{};
};
}
} // namespace entt
#endif

View File

@@ -0,0 +1,35 @@
#ifndef ENTT_META_ADL_POINTER_HPP
#define ENTT_META_ADL_POINTER_HPP
namespace entt {
/**
* @brief ADL based lookup function for dereferencing meta pointer-like types.
* @tparam Type Element type.
* @param value A pointer-like object.
* @return The value returned from the dereferenced pointer.
*/
template<typename Type>
decltype(auto) dereference_meta_pointer_like(const Type &value) {
return *value;
}
/**
* @brief Fake ADL based lookup function for meta pointer-like types.
* @tparam Type Element type.
*/
template<typename Type>
struct adl_meta_pointer_like {
/**
* @brief Uses the default ADL based lookup method to resolve the call.
* @param value A pointer-like object.
* @return The value returned from the dereferenced pointer.
*/
static decltype(auto) dereference(const Type &value) {
return dereference_meta_pointer_like(value);
}
};
} // namespace entt
#endif

247
src/entt/meta/container.hpp Normal file
View File

@@ -0,0 +1,247 @@
#ifndef ENTT_META_CONTAINER_HPP
#define ENTT_META_CONTAINER_HPP
#include <array>
#include <deque>
#include <iterator>
#include <list>
#include <map>
#include <set>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "../container/dense_map.hpp"
#include "../container/dense_set.hpp"
#include "context.hpp"
#include "meta.hpp"
#include "type_traits.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename, typename = void>
struct is_dynamic_sequence_container: std::false_type {};
template<typename Type>
struct is_dynamic_sequence_container<Type, std::void_t<decltype(&Type::clear)>>: std::true_type {};
template<typename, typename = void>
struct is_key_only_meta_associative_container: std::true_type {};
template<typename Type>
struct is_key_only_meta_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {};
template<typename Type>
struct basic_meta_sequence_container_traits {
using iterator = meta_sequence_container::iterator;
using size_type = std::size_t;
[[nodiscard]] static size_type size(const any &container) noexcept {
return any_cast<const Type &>(container).size();
}
[[nodiscard]] static bool resize([[maybe_unused]] any &container, [[maybe_unused]] size_type sz) {
if constexpr(is_dynamic_sequence_container<Type>::value) {
if(auto *const cont = any_cast<Type>(&container); cont) {
cont->resize(sz);
return true;
}
}
return false;
}
[[nodiscard]] static iterator iter(const meta_ctx &ctx, any &container, const bool as_end) {
if(auto *const cont = any_cast<Type>(&container); cont) {
return iterator{ctx, as_end ? cont->end() : cont->begin()};
}
const Type &as_const = any_cast<const Type &>(container);
return iterator{ctx, as_end ? as_const.end() : as_const.begin()};
}
[[nodiscard]] static iterator insert_or_erase([[maybe_unused]] const meta_ctx &ctx, [[maybe_unused]] any &container, [[maybe_unused]] const any &handle, [[maybe_unused]] meta_any &value) {
if constexpr(is_dynamic_sequence_container<Type>::value) {
if(auto *const cont = any_cast<Type>(&container); cont) {
typename Type::const_iterator it{};
if(auto *non_const = any_cast<typename Type::iterator>(&handle); non_const) {
it = *non_const;
} else {
it = any_cast<const typename Type::const_iterator &>(handle);
}
if(value) {
// this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
return iterator{ctx, cont->insert(it, element ? *element : value.cast<typename Type::value_type>())};
}
} else {
return iterator{ctx, cont->erase(it)};
}
}
}
return iterator{};
}
};
template<typename Type>
struct basic_meta_associative_container_traits {
using iterator = meta_associative_container::iterator;
using size_type = std::size_t;
static constexpr auto key_only = is_key_only_meta_associative_container<Type>::value;
[[nodiscard]] static size_type size(const any &container) noexcept {
return any_cast<const Type &>(container).size();
}
[[nodiscard]] static bool clear(any &container) {
if(auto *const cont = any_cast<Type>(&container); cont) {
cont->clear();
return true;
}
return false;
}
[[nodiscard]] static iterator iter(const meta_ctx &ctx, any &container, const bool as_end) {
if(auto *const cont = any_cast<Type>(&container); cont) {
return iterator{ctx, std::bool_constant<key_only>{}, as_end ? cont->end() : cont->begin()};
}
const auto &as_const = any_cast<const Type &>(container);
return iterator{ctx, std::bool_constant<key_only>{}, as_end ? as_const.end() : as_const.begin()};
}
[[nodiscard]] static size_type insert_or_erase(any &container, meta_any &key, meta_any &value) {
if(auto *const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
if(value) {
if constexpr(key_only) {
return cont->insert(key.cast<const typename Type::key_type &>()).second;
} else {
return value.allow_cast<const typename Type::mapped_type &>() && cont->emplace(key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>()).second;
}
} else {
return cont->erase(key.cast<const typename Type::key_type &>());
}
}
return 0u;
}
[[nodiscard]] static iterator find(const meta_ctx &ctx, any &container, meta_any &key) {
if(key.allow_cast<const typename Type::key_type &>()) {
if(auto *const cont = any_cast<Type>(&container); cont) {
return iterator{ctx, std::bool_constant<key_only>{}, cont->find(key.cast<const typename Type::key_type &>())};
}
return iterator{ctx, std::bool_constant<key_only>{}, any_cast<const Type &>(container).find(key.cast<const typename Type::key_type &>())};
}
return iterator{};
}
};
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Meta sequence container traits for `std::vector`s of any type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_sequence_container_traits<std::vector<Args...>>
: internal::basic_meta_sequence_container_traits<std::vector<Args...>> {};
/**
* @brief Meta sequence container traits for `std::array`s of any type.
* @tparam Type Template arguments for the container.
* @tparam N Template arguments for the container.
*/
template<typename Type, auto N>
struct meta_sequence_container_traits<std::array<Type, N>>
: internal::basic_meta_sequence_container_traits<std::array<Type, N>> {};
/**
* @brief Meta sequence container traits for `std::list`s of any type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_sequence_container_traits<std::list<Args...>>
: internal::basic_meta_sequence_container_traits<std::list<Args...>> {};
/**
* @brief Meta sequence container traits for `std::deque`s of any type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_sequence_container_traits<std::deque<Args...>>
: internal::basic_meta_sequence_container_traits<std::deque<Args...>> {};
/**
* @brief Meta associative container traits for `std::map`s of any type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_associative_container_traits<std::map<Args...>>
: internal::basic_meta_associative_container_traits<std::map<Args...>> {};
/**
* @brief Meta associative container traits for `std::unordered_map`s of any
* type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_associative_container_traits<std::unordered_map<Args...>>
: internal::basic_meta_associative_container_traits<std::unordered_map<Args...>> {};
/**
* @brief Meta associative container traits for `std::set`s of any type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_associative_container_traits<std::set<Args...>>
: internal::basic_meta_associative_container_traits<std::set<Args...>> {};
/**
* @brief Meta associative container traits for `std::unordered_set`s of any
* type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_associative_container_traits<std::unordered_set<Args...>>
: internal::basic_meta_associative_container_traits<std::unordered_set<Args...>> {};
/**
* @brief Meta associative container traits for `dense_map`s of any type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_associative_container_traits<dense_map<Args...>>
: internal::basic_meta_associative_container_traits<dense_map<Args...>> {};
/**
* @brief Meta associative container traits for `dense_set`s of any type.
* @tparam Args Template arguments for the container.
*/
template<typename... Args>
struct meta_associative_container_traits<dense_set<Args...>>
: internal::basic_meta_associative_container_traits<dense_set<Args...>> {};
} // namespace entt
#endif

Some files were not shown because too many files have changed in this diff Show More