Squashed 'external/entt/entt/' changes from fef921132..344e03ac6
344e03ac6 update single include file to v3.12.2 da56665b0 registry: make ::valid backward compatible f6f01ef1b snapshot: avoid warnings due to deprecated functions 0ed514628 now working on v3.12.2 a41421d86 update single include file to v3.12.1 c1f6b11f7 snapshot: reintroduce support to storage listeners b2233064a now working on version v3.12.1 cb974bf56 adjacency_matrix: fix in_edges() is off by 1 in some cases (close #1019) 7b7d82e6f doc: snapshot (close #984) 05c6898fc test: self-fixing archive example for snapshot classes 7ffa459a6 snapshot: drop ::get member template parameter 93e8e94e6 test: basic continuous loader c4e241662 snapshot: review basic_continuous_loader (and drop shrink) 9c25419b9 test: more on basic_snapshot_loader 1879830df snapshot: drop pointless assert 29298c0eb test: guarantee code coverage, we'll update the test later on 247abef1d test: rollback for code coverage purposes on the snapshot class 6994d98d2 test: typo 9a600ece2 test: snapshot f91226ef4 snapshot: share ::orphans implementation (to deprecate in future though) e366ffbd3 doc: snapshot 63b300d39 snapshot: again, dense_map::contains is a thing afb70d157 test: avoid warnings due to unused variables 49534eec0 snapshot: dense_map::contains is a thing fortunately 3f1277f7b snapshot: use the right allocator for the remote-local mapping 26fad4c38 test: basic snapshot loader 25b3afacf test: basic snapshot 2d25bbb09 snapshot: check registry type 0eb834582 snapshot: small cleanup 124a44052 test: use the new snapshot get functions in the test suite 5c704636e test: use the new snapshot get functions in the test suite 31fd94cc3 snapshot: cleanup to get ready to drop an internal function 573e43272 snapshot: reduce storage lookups 1d8943481 snapshot: drop useless function e0a1ef7c1 snapshot: check on member type class 48ac0e0eb snapshot: add basic_continuous_loader::get, deprecate ::entities and ::component bcb6234d9 snapshot: add basic_snapshot_loader::get, deprecate ::entities and ::component f96796326 snapshot: reject entity type in the range-get (now get instead of get_sparse) b22c55dd2 doc: typo 4ff5a536c snapshot: add basic_snapshot::get, deprecate ::entities and ::component fff5f578a test: avoid using deprecated functions in an example 0f44c8c92 doc: reflect recent changes 0b6ad0315 snapshot: * single element only archive functions required * avoid iterating elements more than once 2450b0bc6 test: minor changes (waiting for a rework) fc8eebf36 snapshot: use component_traits instead of is_empty_v e4f51f2b7 snapshot: avoid multiple lookups of the same storage 2c2216a89 doc: typo cafe85180 snapshot: deprecate multi-type component loading function 35e338cc9 snapshot: deprecate multi-type component loading function 8feeaaef7 doc: minor changes e7a3c4e37 snapshot: add missing [[deprecate(...)]] ea5c558bd snapshot: cleanup (waiting for further improvements) 94f0ed179 snapshot: deprecate multi-type component loading function 244c35949 snapshot: deprecate multi-type component loading function 1f24fea21 type_traits: formatting 8deaa09b2 test: perform static checks at compile-time 85bffb714 type_traits: std::tuple traits specialization for entt::type_list and entt::value_list (#1011) 325ca310d view: updated ::refresh d903e268f snapshot: minor changes f4b26756c snapshot: improved basic_snapshot::component fb3a34ee9 *: updated TODO 6902bb6c4 doc: typo 379819b2b test: cleanup 59abfbfb5 meta: refine policy check on value types for non-member data 6e2d87184 registry: avoid casting return types directly to better support empty storage 57ec3c85c registry: erase_if (close #977) 4afdf287f doc: minor changes 2810ac7cb registry: suppress a warning on msvc e0d27f9bf *: updated TODO de303c999 test: reverse-each for storage entity 1619e780f test: reverse each for plain storage classes a1e37eca6 storage: reverse-each c345e7456 doc: note on reverse iterations d166c026f snapshot: minor changes 5e639996d doc: minor changes dac2ef5a9 doc: typo 71d7888e8 snapshot: drop redundant check 84a4df9c4 doc: exclude-only views 95bc20319 doc: entity lifecycle 5a9f6d211 doc: cleanup a29302faa test: more on entity signals 75efa72c6 registry: cleanup ::erase 58a84665b registry: cleanup ::remove a5263384d doc: drop redundant comments c0e6759c6 doc: cleanup a little further d754f7431 doc: cleanup 1df539943 doc: drop pointless tags c284e6fee doc: minor changes 500239758 test: typo 319ecd808 organizer: fix organizer::vertex::prepare not creating component pools (#1014) d7891fabc doc: mention named pools support when registering listeners e287dd041 helper: minor changes 4dee9dde1 registry: named pools support for on_construct/on_update/on_destroy 9bae6e67b doc: update connection helper doc aa7a7ce25 doc: minor changes a969468c5 registry: de-deprecate :) on_construct/on_update/on_destroy a1e76fc63 doc: more about entity storage d8ed4ca35 registry: refine how entity storage is used internally 3248e3f91 helper: make sigh_helper work with named pools f00687e6f doc: updated registry documentation 5240c6b60 registry: deprecate on_construct/on_update/on_destroy 67604a88e natvis: update registry snippet 4242dfb8b registry: use entity storage directly as much as possible f96d8ee83 registry: prepare to split component storage and entity storage c147ec37c test: try to make gcc happy again 094ddbba3 meta: avoid shadow warnings 634630ca2 test: add missing template keywords (thanks msvc for ignoring them) d78c26f26 *: updated TODO fabc6c9bd test: full cross-registry entity-copy example with meta (not strictly required) b6e8ddd2a meta: fight against the small nuances of the language :) cf2bbae6e mixin: make it simpler to modify the underlying type 08799616d *: updated TODO 58bebf78d meta: reduce symbols and their sizes if possible d534fad3e doc: more about views 871dc7a40 doc: drop references to storage placeholders 1fe7c78f7 test: minor changes 22a65f80f test: cleanup 756ea8a38 *: updated TODO 12186cb40 registry: drop internal static storage variables from ::assure aa9ffb9ee registry: const ::storage<T>(...) returns a pointer to possibly null storage dcb5aed90 registry: lazily/partially initialize views in the ::view const function 34f6a747a registry: add support for non-existent pools to try_get 912cb2ad5 snapshot: constness review 885488b3d registry: any_of supports non-existing pools now 3d3d3ef2d registry: all_of supports non-existing pools now a7120b340 registry: coding style 51915205b test: cover stable multi-type model 4a3ee042e view: refine ::storage function 88a1b8d0d view: stable multi-type view ::each(cb) function 7e18a0f96 view: update ::use function c367082dd view: unchecked_refresh function 9f94b5306 view: double check on none_of 44ed10c50 view: stable multi type view ::find/::back/::front functions 1b2280941 view: stable multi type view ::begin/::end functions bdabbaa63 view: stable multi type view ::contains function c79c109b7 view: stable multi type view ::size_hint function f1a213382 registry: prepare to remove static storage from const assure 17dc06149 view: stable single type view ::each(cb) function 3b8d82330 view: drop unused return a20829e70 view: ::handle returns a pointer rather than a reference 5be2fdc15 view: stable single type view ::each() function 873b107e6 -: updated TODO 356bbbe53 view: stable single type view ::find function e3ce4e156 view: stable single type view ::front/::back functions e02050c51 view: stable single type view ::rbegin/::rend functions 26930633f view: stable single type view ::begin/::end functions b7a485767 view: stable single type view ::contains function f54cdccd4 view: stable single type view ::empty function 41c9a32f3 view: stable single type view ::size function 736ef3580 view: make operator bool work properly with partially initialized views 0128cbb4f test: minor changes ff0a40715 test: prepare test suite for safe invalid views 34f440386 view: avoid using storage, further prepare for empty safe views b1c78efb6 nativs: updated signal file 28f03ff9c meta: add missing checks on factory<...>::data a5fe61adb *: minor changes 457f5e59e view: rollback handle() usage and prepare to safe empty views 422fd284e group: refine group ::find function 6f3222573 view: refine single type view ::find function 366bbceb0 doc: use doxygen-awesome-css 7b7f81e08 doc: update reference.md cfe955f97 doc: update links.md 684ddc9de doc: minor changes f5d38a9ae doc: drop redundant doxy variable 447e3693f doc: updated doxy file (doxygen 1.9.6) 909490bf6 view: try to make g++ happy again d90363e4a view: make view pack also work with empty views ee5de744c view: add missing [[nodiscard]] d401c88a0 view: assert on null handles 80563b955 view: allow swapping storage elements of a view c74900057 sigh_mixin: avoid shadow warnings 78867d5c9 group: make msvc happy with constness on virtual functions d435fc779 basic_entt_traits: suppress a warning by gcc e6f76e0f9 view: try to make VS happy again :) 1c6b53360 test: minor changes 5c3d8360c view: turn ::use into a self-contained, non-const function 3882c7d9a view: turn ::refresh into a self contained, non-const function 15726218b view: doc 869bfc82c test: minor changes 0eb3d54b2 group: change signature of ::storage to return a (maybe null) pointer rather than a reference f83290f76 view: change signature of ::storage to return a (maybe null) pointer rather than a reference 686a3b9d7 registry: make storage_for_type available to the final user 4d57d5c32 registry: make ::storage<T> return type explicit 36c21cf7f registry: drop redundant traits usage 7ab10e193 test: minor changes 41467d35a -: updated TODO d351252a1 doc: entity storage c6cd4f701 doc: refine storage section 65889cca4 doc: brief mention of void storage f1914fd94 doc: rearrange a few things e53af7bef registry: minor changes b910cd261 *: updated TODO 58d331ca0 registry: minor changes 17f5b0a33 registry: avoid bumping version on destroy if not requested de386292b registry: deprecate ::each 88bf26a2f registry: deprecate ::assign 3caad4100 mixin: common internal owner_or_assert function 916203a24 test: stress assert on entity limit 62f1971f7 test: minor changes 4fde96357 natvis: updated registry snippet c3730b65f group: * unified model * drop group handler's size function (no longer required) 1ea072cd3 group: back to the unified model for group handlers bbe4582ee meta: minor changes 89ab5c328 meta: operator==/!= for meta_func 3a4672793 meta: operator==/!= for meta_prop 0a0446f35 meta: operator==/!= for meta_data (close #1002) fc58ff74b meta: operator==/!= for meta_handle (see #1002) fed6831cd locator: support to opaque structures (close #956) 1605c8d9d natvis: updated entity file d6641c7d8 -: updated TODO file 5079f38e9 storage: allow on_update signals on entity storage 1eab2a4a8 meta: fix constness detection for static functions in meta_type::invoke c33110765 test: cleanup 117b0bd67 test: more about storage<...>::patch 9b4a6f877 storage: use allocator_traits::destroy rather than destroy_at f4e6f2b37 group: suppress shadow warning 5971fb7aa -: updated TODO 10dfe7e93 sigh: allow disconnecting listeners during iterations (close #986) a9208a956 doc: fixed typo 1cc5b32ca test: cleanup f8a972a3c signal: drop sink::before 5b7cc2002 group: rollback some (no longer required) changes to the owning_group_descriptor bd34e7f2c group: drop nested groups support, prepare to the large group review and multi storage support 46fe29c3f group: make matching functions virtual for owning groups c50e2815c group: make owning_group_descriptor depend on the storage base type fbfee632d group: minor changes 77c59aabf group: group_handler::size function for owning groups ebb1e8a72 group: single check function for group handlers 1646217f0 group: make types explicit for the next/prev functions 645edfb2b group: decouple constructing and setting prev/next links 61f28298c group/registry: minor changes d19f97bf2 group: use ::handle() if possible 70c611a84 group: cleanup 286428c19 group: make common_type base of non-owning group handlers 6ec719bcf group: reduce the footprint of non-owning group handlers 11f9bb2d7 registry: use shared_ptr<void> for non-owning groups (prepare to drop the basic handler dependency) 5a1ba5ad7 regisrtry: decouple container types for groups cf094e7ef registry: finally split owning and non-owning groups as it ought to be 31808bd9a sigh: flip the last commit on its head and drop redundant functions rather than merging them 61a5173a7 sigh: merge a couple of functions ed6fe9e65 sigh/sink: refine internal definition e30fa8520 doc: cleanup ca1069e18 snapshot: avoid allocations if possible 70f73a094 snapshot: drop pointless checks 710fff0e3 entity: make get_t, exclude_t and owned_t constexpr constructible 660bc5843 entity: turn get_t, exclude_t and owned_t into proper classes (close #998) 13295a14e type_traits: v141 toolset workaround for value_list_diff 9ce07ff61 type_traits: value_list_diff[_t] b272e04ba type_traits: value_list_contains[_v] 28b11912a test: cleanup b9f096d12 type_traits: value_list_unique[_t] 8c60faa1d type_traits: value_list_index[_v] 1f93ea4ee snapshot: avoid unnecessary lookups 7ca77e53f snapshot: avoid unnecessary lookups 69397f365 snapshot: avoid unnecessary lookups f907bc066 snapshot: drop redundant checks and avoid unnecessary lookups bda52701f snapshot: avoid unnecessary lookups d26f7684c snapshot: minor changes 63d6c2bff snapshot: avoid unnecessary lookups cc45e7341 snapshot: also avoid using views if not required 5d092bcb1 snapshot: avoid unnecessary lookups 295c68841 snapshot: review ::orphans functions 2664b5255 observer: allocator support dd3632833 observer: configurable mask type c8c929e4a group: use type members properly d1ef7bf15 view: use type members properly 1ab23f17d group: early exit on signal races a72eb4693 group: minor changes 67579d062 -: updated TODO 766a233f3 view: base_type -> common_type 905671c23 runtime_view: base_type -> common_type 27c1383e4 group: base_type -> common_type 029ccc8f7 registry: base_type -> common_type cde40d586 group: drop unused using decl 6a16a8a20 group: auto init for owning groups 1a12dede6 group: auto init for non-owning groups 35a78b65e group: cleanup ada19432f group: support for index based sort 4998e9087 doc: minor changes 471c11c6d sparse_set: respect -> sort_as (naming is hard, you know) 3e13e0b59 group: sort/respect -> sort_as (also decoupled from group types) 53cd105f2 group: reuse pools as much as possible 24b31c379 group: reuse pools as much as possible def82b534 group: index based get a424f4ebf view: review get b8f0a8d8e doc: a couple of interesting articles/series (close #994) 7941226ef group: try to reuse pools when sorting and also please all compilers out there at the same time (aka me figthing ICEs again) 86bbb2f6b group: reuse pools when sorting 3c176f725 test: suppress warnings due to unused variables 3642c8a78 registry: drop [[nodiscard]] from ::group (close #991) 0e80d90a7 group: use storage<idx> as much as possible 4fdf2dccd group: update doc f8a997e6c group: minor changes 40f676ed1 test: drop unused include 5e346748e test: code coverage for groups and registry 3ef61fe01 meta: support meta member functions on primitive types 3885d280d test: cleanup f41b91419 meta: allow updating values on meta properties e0684f634 registry: cleanup/minor changes fb980a78c registry: further refine the group function(s) c2430ab48 doc: minor changes d36d9cb39 registry: further cleanup group functions 0017c08bb group: get pools from handlers e737ff747 group: get filter from handlers 945dc4093 group: split group handler functions 7ef008511 registry: drop group_data d2fa68813 registry/group: prepare to get rid of group_data f22a09a9a group: in-between change to simplify dropping group_data b0aba79a5 snapshot: minor changes 7c23e4a2f registry: minor changes 7fe035ce4 group: move group size from registry group_data to basic_group_handler 3e7160eda group: minor changes aaeb686ec group: common base class for group handlers 3fdf4884d group: prepare for group handler common base class 1b23ff4b9 registry: use common group handler types as keys for the group set 88dac318e group: wrap the len of owning groups to avoid changing it by mistake 520c2e660 group: make group handlers work with multiple storage of the same type f5d0d451b group: split pools and filter in the group handlers 8af6fc0cc group: use ::handle internally if possible c04b97a31 group: add ::handle function to all group types 1d85414dc doc: drop refs to registry::version (close #992) c6533827f group: fight with clang format from time to time :) b5803451b group: make owning groups work with their handlers 3417d66b2 group: make non-owning groups work with their handlers 1e61204e8 registry: deduce group handler type from group type 19c4857ef group: cleanup 66ea94898 registry/group: move group handler to group file as it ought to be ced6d21c3 registry: break dependency between registry and group handlers 429c7c45c registry: further cleanup things c03b1111a registry: small cleanup ebd7d3acd registry: storage based model with pools for groups 5aeec60cf registry: prepare to switch to storage based group handlers 620b4f751 registry: pass handlers to group callbacks 6d58004c1 registry: minor changes to simplify the implementation slightly df6d926de registry: prepare for a storage based group handler e63af24cb registry: turn the non-owning group handler in a storage 068d9f8ae registry: discard unused arguments from listeners if possible c19c848c4 test: suppress warnings due to unused variables 0bf0a0a8f doc: delegate 743e8678e delegate: also support functions that skip first elements (on second attempt only) a7ad1c06f delegate: prepare to support filtering on both sides b1af70e70 registry: avoid checking pools in the group handler if possible c87c3533e registry: avoid checking pools in the group handler if possible 4839a0ee6 registry: cleanup a0f0c44e6 registry: minor changes 74691dc1d group: just use meaningful names :) e4957badb registry: split group handler to further refine group management 46791c4c3 registry: turn group handler functions into static ones 56c391784 registry: prepare to rework groups 1fb13d3e9 doc: minor changes 535beb4e2 storage: drop unnecessary use of integral_constant 2d318b88c -: updated TODO b7f0b76ce entity/mixin: add missing include d30312f51 entity/helper: add missing include, drop unnecessary traits calls 30772848e meta: avoid unnecessary calls to std::move eca01a397 doc: add vcpkg badge and vcpkg.link (#985) 35ef0b7ac core: reduces the number of instantiations a bit 19ccba3a6 meta: reduces the number of instantiations a bit 207b7674a doc: fix typo 631c55ba9 storage: minor changes/tests e7b30fd36 storage: return iterator to elements rather than entities and only if it makes sense 3e959007b storage: ::insert returns an iterator to the range of inserted entities 07ec4ca23 -: updated TODO 6e4946b68 storage: uniform interface to simplify mixin implementation 47ea16f17 test: signals on entity creation/destruction 722857fc0 test: get rid of pointless template parameters 2125b3838 test: minor changes 289de7d57 test: exclude only views 25ecd8e79 test: minor changes 319dfdb07 test: filtered registry view 9dbbcac01 -: updated TODO f545c8e05 registry: deprecate ::release c68fa6a65 registry: make ::destroy work without ::release (the latter to be deprecated) d288ecd70 registry: make ::release use ::bump return value 312d3aba8 sparse_set: bump returns the version in use (for convenience) 4d2b2c6de registry: use traits_type::next if possible 80d55a226 test: increase code coverage d86a53935 test: suppress warnings due to unused variables 0f7098d0e -: updated TODO 8c96be1e9 registry: deprecate a bunch of functions because of the entity storage 37f396bfe registry: make entity storage storage as any other 75894dc40 storage: update traits_type for entity storage cdee000ce any: rollback a change that turns vs toolset v141 crazy 54ca62600 dispatcher: refine aggregate check 6f4280ed5 any: refine aggregate check ddf56b78c storage: backward compatibility on component requirements 53a854f54 any: just cleanup the code to make it easier to work with 4896acac7 storage: typo e3defeba2 test: suppress warnings due to unused variables 62079908c storage: use proper value type for entity storage e65a8f2e5 doc: add link to koala engine :) 9f27fb1e5 registry: further prepare to turn the entity storage into a plain pool 04d734e76 registry: prepare to turn the entity pool in a plain storage df50fa1b5 natvis: cleanup 051872b8c natvis: update registry definition 57ab9e7be registry: avoid using assure if not required 69d95ba75 test: more bench to stress a little an upcoming feature 9caf66d7c test: cleanup 74cb0d40c test: internal rework deac7f34b dispatcher: refine aggregate support a9883f27c storage: refine transparent aggregate support 85b1e57d8 sparse_set: drop fast_compact, expect full clear b7d8e0186 storage: make the entity storage perform a full clear rather than a fake one (still viable via erase) 390a56176 -: updated TODO file a1b888cce natvis: add optiona storage length item for entity storage 2107dd689 natvis: fix already existing errors due to renaming or design changes 1fca56afe storage: make it easier to refine the natvis file c0762a6a5 storage: add get/get_as_tuple to entity storage to make it suitable for use with views f48de1bac test: stress get/get_as_tuple for empty types c7dfce89e sigh_mixin: refine pop_all 822fafcd4 view: uniform implementation to simplify upcoming changes 1476d4ea9 sparse_set: refine ::respect c1c63777e -: updated TODO 2fab25ae8 registry: refine internal check 75d449152 -: updated TODO c7866fb21 storage: use entt traits next function if possible 87987bacd entity: added basic_entt_traits::next (with tests) bde0219fe snapshot: review basic_continuous_loader::entities ad64c849b storage: suppress warnings b808bb83b test: suppress warnings d0090d35f snapshot: try to make sizes an opaque value to the caller 7a1a06a24 sigh_mixin: avoid shadow warnings 000b17881 -: updated TODO 068b6ed49 registry: first (almost) backward compatible version with opaque hidden entity storage 0187fb48a test: sigh mixin for entity storage types 35a2b3844 sigh_mixin: also support entity storage types 4747c9a4c registry: extended checks to support swap-only entity storage types 7be8d8327 registry: make a couple of conditions opaque a5d6757d6 registry: prepare to get rid of the vector of entities 3f09d47c8 storage: remove redundant typename keyword 9c06d6ba0 registry: use type member names b7c819bf4 test: entity storage 9f31803ba storage: swap-only entity storage 1e7deff9c test: drop redundant checks 04ac15d8d test: minor changes 376218991 sigh_mixin: make pop_all use narrow view iterators if any 18d6e466d -: [[nodiscard]] as appropriate 095ecf314 group: extended_group_iterator::base to return the underlying iterator 433ed863e view: extended_view_iterator::base to return the underlying iterator 0dba68e75 storage: coding style/minor changes 1ab281582 storage: extended_storage_iterator::base to return the underlying iterator 2af5a725e doc: * updated copyright * udpated TODO list a86bf1332 test: try to make lcov happy 831054bff test: share as much as possible f94de1c06 test: rework lib stuff to share common files a3d9503a1 test: try to make lcov happy 3f2b15f9f test: try to make lcov happy e48817d51 test: try to make lcov happy d11cebe30 view: uniform design to also help natvis without having to poke into stl internals 77a5efb32 natvis: updated to_entity intrinsic 851006efe -: updated TODO 6fc6b2fb3 sigh_mixin: further improve ::pop_all ed17a2c48 sparse_set: ::contiguous function bd00e797a sparse_set: further refine pop_all to make it even faster e645c4928 -: updated TODO a425878e8 sparse_set/storage: clear is backward compatible now f3cd9d374 storage: fixed clear_all counter b3e93b084 registry: naming convention 314c189c4 test: minor changes 2bb2c5566 build: try to make lcov happy again d13c126e9 view: avoid name clashes 9b54ee37a flow: propagate allocator to generated graph + internal rework e1ead9d3e build: update coverage workflow cf61068dc mixin: suppress a warning with gcc11 82863f829 test: code coverage for range functionalities e4de59827 test: try to make lcov happy ccea4c920 memory: code coverage 89166f0e4 build: refine analyzer workflow 7a05a16c5 registry: slightly better destroy (yet not quite there though) d0854646c test: yet another test to stress the upcoming changes 1e9c9fe5f registry: better, faster range-remove + refine range-erase 80fac8d8e test: minor changes c774b9838 -: updated TODO 3fd0403cc registry: faster, better range-erase 6eb3347a3 test: a couple of extra functions to stress the upcoming changes 89bceaff7 -: updated TODO dc25c9c1a sparse_set: invoke release_sparse_pages before clearing the sparse array e68ba5870 sigh_mixin: add a missing include c68cb3375 entity: make deletion_policy publicly available via fwd.hpp 59f807fd0 sparse_set: suppress warnings due to unused expressions 232ffebc1 sparse_set: internal clear_all function 3cea845a0 sparse_set: sparse_set_iterator::data function 295f3b32e registry: a couple of extra move calls here and there 254da2c3c sparse_set: better, faster range remove ecd3b8d93 sparse_set: prevent rework errors as much as possible c673b9b17 sigh_mixin: slightly improved pop + review insert cd28de0d6 test: clear-stable bench 672f6a711 test: minor changes 3b50672b7 storage: restore storage_for/storage_type duality, it turned out to be very useful in practice f0613b1c6 sparse_set/storage: minor changes to reuse type members 2197e160e -: drop file pushed by mistake :) 2dccd9016 handle: discard entity on destruction 2f873f2dd -: storage_mixin.hpp -> mixin.hpp (non-storage mixins are also a thing) fde1a524e sparse_set: ::get -> ::value (to avoid hiding from derived classes) 055801047 doc: drop references to docsforge + minor changes 79a054a52 sigh_mixin: scope base_type properly d94e443a1 doc: drop outdated section 3862184e8 sigh_mixin: support self managed storage classes f40fa3c2f test: * use range destroy * avoid compiler optimizations 01bc93459 test (bench): the new entity storage enables the fast path in all cases 151bd0739 sparse_set: revert optmized range push, it prevents self-managed storage classes 935393aae sparse_set: better, faster range push fbfde4347 snapshot: avoid unused variable warnings 2ffbe115b component_traits: revert entity customization support 645973eb7 sparse_set: insert -> push 133230797 sparse_set: emplace -> push b700f5eb5 doc: typo e60dbdc52 sparse_set/storage: * rename swap_at in swap_or_move to capture the real purpose * define swap_at as a protected function to allow swapping from above c66623b33 sigh_mixin: avoid hiding basic_iterator type meber 62246d879 storage: avoid hiding basic_iterator type meber b35f13130 sparse_set: support swap-only mixins 3dd82633a -: drop storage_mixin.cpp, I forgot to do it a couple of commits ago :) 00231bf8a storage: make swap_at non-final to support checks on derived classes 58d392e81 -: minor changes 1d4d99d09 mixin: sigh_storage_mixin -> sigh_mixin fe3edf2c8 -: minor changes 0864ba042 -: drop useless typename 3a9698001 build: minor changes 423f7a555 is_equality_comparable: detect C-style arrays directly 5db8ad53a build: update gh workflow c2ab35780 view: make also VS toolset v141 happy 4fb558f14 view: further reduce instantiations 5762a8a08 view: reuse internal functions if possible ed4c67521 sparse_set/storage: drop move_element f15789846 config: ENTT_FAIL(msg) -> ENTT_ASSERT(false, msg) 6d20709e0 storage: minor changes a9a9853c0 sigh_storage_mixin: use entity_type from Type af14aa4c9 doc: more about signals (sigh_storage_mixin) 24d6b9881 test: minor changes 899f4baa6 storage: * drop storage_for]_t] * make storage_type[_t] deal with constness c1ab7ba02 sigh_storage_mixin: make all virtual member functions final 9d38f6020 registry: thanks MSVC for accepting invalid C++ code 0efa25cf6 sigh: cool, I keep doing the same error again and again apparently :) 6316b6045 registry: make it work with storage<void> also in C++17 f268fb60a entity: avoid breaking changes due to type members renaming 3520d6915 entity: add base_type 4da7a8451 entity: make checks work with 64b identifiers :) 382dfc3bb entity: strict check on entity/version masks b6dcdc816 entity: * also expose entity_mask and version mask to the final user * avoid default args with entt_traits::construct for backward compatibility c9d544089 doc: review/cleanup entity.md a bit (done) 3eb5faeed doc: review/cleanup entity.md a bit (work in progress) 7a328c7ed doc: updated links 6567aa195 doc: a note about listeners disconnection (close #958) 92319f011 entt_traits: split basic impl, simplify def 782d86b6e entt_traits: value_type -> type (cuz it's not a value type after all) c2cae37c1 entity_traits: make page_size type explicit 1026d26ec entt_traits: drop reserved value 7156803db test: local non-static constexpr variables f54ed5424 helper: local non-static constexpr variables f30b50195 algorithm: local non-static constexpr variables c90ab9aff sparse_set: * break dependency on traits_type::reserved * use a tombstone if all I need is a tombstone c2f6ca43f doc: graph (close #957) 3e5e41d88 test: cover some corner cases of the flow class 9eafc0431 flow: minor changes 0a82b777b component_traits: support specializations based on entity type 32bcc01a4 component: * make component_traits treat void properly * drop ignore_as_empty_v 9c3fe3546 nativs: entity module 83f8aed58 helper: use traits_type from storage class directly 2fd660274 snapshot: use public registry traits_type member type a554d406e registry: * public traits_type member type * break dependency on component_traits * use public storage traits_type member type 5f12f872e test: minor changes be4eb68a3 helper: * break dependency on component_traits * use public storage traits_type member type df5284d9e view: * break dependency on component_traits * use public storage traits_type member type 0e27d33e7 storage: public traits_type member type fe6e6ae73 sparse_set: public traits_type member type 9d29713ea entity: naming convention 270d0277d group: cleanup 0bd06c8d5 hashed_string: naming convention 733f215cc storage: break dependency between component_traits and storage_iterator ad01a69fe *: renaming/coding style dd9c1dade sparse_set: no need to differentiate template args for sparse_set_iterator b8f70519f doc: fixed typo 9b9d212dd *: coding style 3fe15969d doc: cleanup ec4bf222c meta: avoid the +1u trick for 0-sized arrays 1173908ee meta: avoid rebinding when forwarding requests 2595b8a92 doc: sigh_helper f4e2a8c76 sigh_builder: add all missing .template that msvc kindly accepted anyway 66e1a0565 entity: sigh_helper utility with tests (close #928) 87283dc41 storage: simplified impl in order to introduce multi-type storage more easily a802ebffe storage: * move storage_type[_t] and storage_for[_t] to fwd.hpp * no need to include storage.hpp when forward defining views b84b09421 doc: add Arch ECS to references.md (#954) 940fd0939 todo: add a note for a (soon to be released) change 920338be5 doc: add ecsact to links.md (thanks @zaucy for pointing this out) bcd1155b7 gh: add more gcc and clang versions 1dc88109e gh: update workflows 262c1f53c cmake: only enable -Wdocumentation for clang-cl 4af0a3a0d doc: cleanup be1641828 doc: cleanup b54a52fbf doc: fixed typo ae8815995 doc: fixed typo 62c764f68 doc: fixed typo 2c48cc10a cmake: enable documentation diagnostic for clang 82f286678 sigh: drop redundant function d56e5a269 registry: propagate allocator to context 1517b2951 doc: document delegate raw access bea7b43a1 delegate: target member function 2f878f8b5 sigh: refine ::collect fc68c1b29 view/group: cleanup 9081c185d meta: minor changes 7c4493f23 group: make filter storage available da4e73ab8 view: make filter storage available f3e7f98b4 registry: extra check when moving a registry 3925fc612 emitter: extra allocator check when moving c639130c1 dispatcher: extra allocator check when moving 75c311600 registry: cleanup e9e14eb49 meta: [[nodiscard]] d1558304f any: [[nodiscard]] 0531b530b snapshot: minor changes f9d0178dd workflow: bump iwyu version b66b8d37e test: suppress warning 05ef4c29d storage: minor changes 9c3d75669 test: cleanup include directives 93651e46f registry: drop [[deprecated]] functions ea901cbfa test: code coverage d5dc4f43e doc: meta.md 498e02f15 doc: core.md d0ea8f4f9 cmake: suppress some warnings for clang-cl, it goes a little wrong otherwise dec3b7bb3 test: suppress warnings 10bc8b05a test: use /W1 with VS (but for toolset v141, too bugged for that) ad77b54dc cmake: bump version to get some cool feature/update b6724b028 group: pass filter storage to groups (in-between change for full storage access) 54270b103 group: make them easily copyable/movable 31dc732a7 doc: graph.md f0e02d6d3 doc: container.md 156d6e4ea doc: poly.md 4375c1c3d doc: lib.md 24a9cd67e scheduler: forgot to add the fwd file to the previous commit :) ba8d522c1 doc: add the worst engine (love the name) to the list of links 3ae46214a doc: review process.md 5119fe8d7 scheduler: basic type model with default for common cases ed0319cdd view: avoid shadow warnings bc50da6a7 storage: suppress warnings with non copyable nor default constructible types 52b3b4c24 group: suppress warnings for unused variables in case of empty types 74bab529d test: minor changes b1b143917 meta: [[maybe_unused]] variable to avoid warnings with corner cases 7beb4c85c test: suppress a few warnings (entity) f3beb5670 test: suppress a few warnings (container) 446c67b69 test: suppress a few warnings (resource) c4507bd17 test: suppress a few warnings (poly) 61e872bb4 test: suppress a few warnings (meta) 9f22a3e23 test: suppress a few warnings (memory) 653dd5cd4 test: suppress a few warnings (tuple) bc53ed3be test: suppress a few warnings (flow) f935bbcce dense_set: suppress warnings due to possible narrowing conversions c7d505353 dense_map: suppress warnings due to possible narrowing conversions ea78f1d97 now working on version 3.12 REVERT: fef921132 update single include file REVERT: e52a93f8a ready to cut v3.11.1 REVERT: cd541f335 storage: * move storage_type[_t] and storage_for[_t] to fwd.hpp * no need to include storage.hpp when forward defining views REVERT: 255b8be8c view: avoid shadow warnings REVERT: 8cd7f064a storage: suppress warnings with non copyable nor default constructible types REVERT: 58ae4117c group: suppress warnings for unused variables in case of empty types REVERT: cfa1e805b meta: [[maybe_unused]] variable to avoid warnings with corner cases REVERT: ccedacec8 dense_set: suppress warnings due to possible narrowing conversions REVERT: 17578dc8c dense_map: suppress warnings due to possible narrowing conversions git-subtree-dir: external/entt/entt git-subtree-split: 344e03ac64a1f78424ab1150e2d4778e8df8431d
This commit is contained in:
@ -2,8 +2,22 @@
|
||||
# Doxygen configuration (documentation)
|
||||
#
|
||||
|
||||
set(DOXY_DEPS_DIRECTORY ${EnTT_SOURCE_DIR}/deps)
|
||||
FetchContent_Declare(
|
||||
doxygen-awesome-css
|
||||
GIT_REPOSITORY https://github.com/jothepro/doxygen-awesome-css
|
||||
GIT_TAG main
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(doxygen-awesome-css)
|
||||
|
||||
if(NOT doxygen-awesome-css_POPULATED)
|
||||
FetchContent_Populate(doxygen-awesome-css)
|
||||
set(doxygen-awesome-css_INCLUDE_DIR ${doxygen-awesome-css_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
set(DOXY_SOURCE_DIRECTORY ${EnTT_SOURCE_DIR}/src)
|
||||
set(DOXY_CSS_DIRECTORY ${doxygen-awesome-css_INCLUDE_DIR})
|
||||
set(DOXY_DOCS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(DOXY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
|
142
docs/doxy.in
142
docs/doxy.in
@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.9.4
|
||||
# Doxyfile 1.9.6
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
@ -19,7 +19,8 @@
|
||||
# configuration file:
|
||||
# doxygen -x [configFile]
|
||||
# Use doxygen to compare the used configuration file with the template
|
||||
# configuration file without replacing the environment variables:
|
||||
# configuration file without replacing the environment variables or CMake type
|
||||
# replacement variables:
|
||||
# doxygen -x_noenv [configFile]
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@ -85,7 +86,7 @@ CREATE_SUBDIRS = NO
|
||||
# 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.
|
||||
# number of 16 directories.
|
||||
# Minimum value: 0, maximum value: 8, default value: 8.
|
||||
# This tag requires that the tag CREATE_SUBDIRS is set to YES.
|
||||
|
||||
@ -557,7 +558,8 @@ HIDE_UNDOC_MEMBERS = NO
|
||||
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
|
||||
# undocumented classes that are normally visible in the class hierarchy. If set
|
||||
# to NO, these classes will be included in the various overviews. This option
|
||||
# has no effect if EXTRACT_ALL is enabled.
|
||||
# will also hide undocumented C++ concepts if enabled. This option has no effect
|
||||
# if EXTRACT_ALL is enabled.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
@ -595,7 +597,8 @@ INTERNAL_DOCS = NO
|
||||
# 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.
|
||||
# Possible values are: SYSTEM, NO and YES.
|
||||
# The default value is: SYSTEM.
|
||||
|
||||
CASE_SENSE_NAMES = YES
|
||||
|
||||
@ -847,6 +850,14 @@ WARN_IF_INCOMPLETE_DOC = YES
|
||||
|
||||
WARN_NO_PARAMDOC = YES
|
||||
|
||||
# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
|
||||
# undocumented enumeration values. If set to NO, doxygen will accept
|
||||
# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
|
||||
# will automatically be disabled.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_IF_UNDOC_ENUM_VAL = NO
|
||||
|
||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||
# 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
|
||||
@ -905,10 +916,21 @@ INPUT = @DOXY_SOURCE_DIRECTORY@ \
|
||||
# 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.
|
||||
# See also: INPUT_FILE_ENCODING
|
||||
# The default value is: UTF-8.
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
|
||||
# character encoding on a per file pattern basis. Doxygen will compare the file
|
||||
# name with each pattern and apply the encoding instead of the default
|
||||
# INPUT_ENCODING) if there is a match. The character encodings are a list of the
|
||||
# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
|
||||
# "INPUT_ENCODING" for further information on supported encodings.
|
||||
|
||||
INPUT_FILE_ENCODING =
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
|
||||
# *.h) to filter out the source-files in the directories.
|
||||
@ -945,7 +967,7 @@ RECURSIVE = YES
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE = @DOXY_DEPS_DIRECTORY@
|
||||
EXCLUDE =
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
@ -1015,6 +1037,11 @@ IMAGE_PATH =
|
||||
# code is scanned, but not when the output code is generated. If lines are added
|
||||
# or removed, the anchors will not be placed correctly.
|
||||
#
|
||||
# Note that doxygen will use the data processed and written to standard output
|
||||
# for further processing, therefore nothing else, like debug statements or used
|
||||
# commands (so in case of a Windows batch file always use @echo OFF), should be
|
||||
# written to standard output.
|
||||
#
|
||||
# Note that for custom extensions or not directly supported extensions you also
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# properly processed by doxygen.
|
||||
@ -1056,6 +1083,15 @@ FILTER_SOURCE_PATTERNS =
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE = @PROJECT_SOURCE_DIR@/README.md
|
||||
|
||||
# The Fortran standard specifies that for fixed formatted Fortran code all
|
||||
# characters from position 72 are to be considered as comment. A common
|
||||
# extension is to allow longer lines before the automatic comment starts. The
|
||||
# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
|
||||
# be processed before the automatic comment starts.
|
||||
# Minimum value: 7, maximum value: 10000, default value: 72.
|
||||
|
||||
FORTRAN_COMMENT_AFTER = 72
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
@ -1193,10 +1229,11 @@ CLANG_DATABASE_PATH =
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# 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
|
||||
# while generating the index headers.
|
||||
# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
|
||||
# that should be ignored while generating the index headers. The IGNORE_PREFIX
|
||||
# tag works for classes, function and member names. The entity will be placed in
|
||||
# the alphabetical list under the first letter of the entity name that remains
|
||||
# after removing the prefix.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
||||
|
||||
IGNORE_PREFIX =
|
||||
@ -1265,7 +1302,7 @@ HTML_FOOTER =
|
||||
# obsolete.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_STYLESHEET =
|
||||
HTML_STYLESHEET = @DOXY_CSS_DIRECTORY@/doxygen-awesome.css
|
||||
|
||||
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
|
||||
# cascading style sheets that are included after the standard style sheets
|
||||
@ -1275,7 +1312,12 @@ HTML_STYLESHEET =
|
||||
# Doxygen will copy the style sheet files to the output directory.
|
||||
# Note: The order of the extra style sheet files is of importance (e.g. the last
|
||||
# style sheet in the list overrules the setting of the previous ones in the
|
||||
# list). For an example see the documentation.
|
||||
# list).
|
||||
# Note: Since the styling of scrollbars can currently not be overruled in
|
||||
# Webkit/Chromium, the styling will be left out of the default doxygen.css if
|
||||
# one or more extra stylesheets have been specified. So if scrollbar
|
||||
# customization is desired it has to be added explicitly. For an example see the
|
||||
# documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
@ -1290,6 +1332,19 @@ HTML_EXTRA_STYLESHEET =
|
||||
|
||||
HTML_EXTRA_FILES =
|
||||
|
||||
# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
|
||||
# should be rendered with a dark or light theme.
|
||||
# Possible values are: LIGHT always generate light mode output, DARK always
|
||||
# generate dark mode output, AUTO_LIGHT automatically set the mode according to
|
||||
# the user preference, use light mode if no preference is set (the default),
|
||||
# AUTO_DARK automatically set the mode according to the user preference, use
|
||||
# dark mode if no preference is set and TOGGLE allow to user to switch between
|
||||
# light and dark mode via a button.
|
||||
# The default value is: AUTO_LIGHT.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_COLORSTYLE = LIGHT
|
||||
|
||||
# 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 color-wheel, see
|
||||
@ -1653,17 +1708,6 @@ HTML_FORMULA_FORMAT = png
|
||||
|
||||
FORMULA_FONTSIZE = 10
|
||||
|
||||
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
|
||||
# generated for formulas are transparent PNGs. Transparent PNGs are not
|
||||
# supported properly for IE 6.0, but are supported on all modern browsers.
|
||||
#
|
||||
# Note that when changing this option you need to delete any form_*.png files in
|
||||
# the HTML output directory before the changes have effect.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
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.
|
||||
@ -2379,26 +2423,38 @@ HAVE_DOT = YES
|
||||
|
||||
DOT_NUM_THREADS = 0
|
||||
|
||||
# When you want a differently looking font in the dot files that doxygen
|
||||
# generates you can specify the font name using DOT_FONTNAME. You need to make
|
||||
# sure dot is able to find the font, which can be done by putting it in a
|
||||
# standard location or by setting the DOTFONTPATH environment variable or by
|
||||
# setting DOT_FONTPATH to the directory containing the font.
|
||||
# The default value is: Helvetica.
|
||||
# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
|
||||
# subgraphs. When you want a differently looking font in the dot files that
|
||||
# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
|
||||
# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
|
||||
# Edge and Graph Attributes specification</a> You need to make sure dot is able
|
||||
# to find the font, which can be done by putting it in a standard location or by
|
||||
# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
|
||||
# directory containing the font. Default graphviz fontsize is 14.
|
||||
# The default value is: fontname=Helvetica,fontsize=10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
|
||||
|
||||
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
|
||||
# dot graphs.
|
||||
# Minimum value: 4, maximum value: 24, default value: 10.
|
||||
# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
|
||||
# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
|
||||
# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
|
||||
# arrows shapes.</a>
|
||||
# The default value is: labelfontname=Helvetica,labelfontsize=10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
|
||||
|
||||
# By default doxygen will tell dot to use the default font as specified with
|
||||
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
|
||||
# the path where dot can find it using this tag.
|
||||
# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
|
||||
# around nodes set 'shape=plain' or 'shape=plaintext' <a
|
||||
# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
|
||||
# The default value is: shape=box,height=0.2,width=0.4.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
|
||||
|
||||
# You can set the path where dot can find font specified with fontname in
|
||||
# DOT_COMMON_ATTR and others dot attributes.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_FONTPATH =
|
||||
@ -2641,18 +2697,6 @@ DOT_GRAPH_MAX_NODES = 50
|
||||
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
|
||||
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
|
||||
# background. This is disabled by default, because dot on Windows does not seem
|
||||
# to support this out of the box.
|
||||
#
|
||||
# Warning: Depending on the platform used, enabling this option may lead to
|
||||
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
|
||||
# read).
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_TRANSPARENT = NO
|
||||
|
||||
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
|
||||
# files in one run (i.e. multiple -o and -T options on the command line). This
|
||||
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
|
||||
|
@ -17,7 +17,6 @@
|
||||
* [ENTT_DISABLE_ASSERT](#entt_disable_assert)
|
||||
* [ENTT_NO_ETO](#entt_no_eto)
|
||||
* [ENTT_STANDARD_CPP](#entt_standard_cpp)
|
||||
|
||||
<!--
|
||||
@endcond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
|
@ -9,7 +9,6 @@
|
||||
* [Containers](#containers)
|
||||
* [Dense map](#dense-map)
|
||||
* [Dense set](#dense-set)
|
||||
|
||||
<!--
|
||||
@endcond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
@ -21,7 +20,7 @@ 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
|
||||
However, the library also tries to fill a gap in features and functionalities 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
|
||||
@ -40,7 +39,7 @@ 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/>
|
||||
the `std::unordered_map` class.<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/>
|
||||
@ -63,5 +62,5 @@ 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/>
|
||||
library, that is, the `std::unordered_set` class.<br/>
|
||||
Therefore, there is no need to go into the API description.
|
||||
|
279
docs/md/core.md
279
docs/md/core.md
@ -46,25 +46,24 @@
|
||||
# Introduction
|
||||
|
||||
`EnTT` comes with a bunch of core functionalities mostly used by the other parts
|
||||
of the library itself.<br/>
|
||||
Hardly users will include these features in their code, but it's worth
|
||||
describing what `EnTT` offers so as not to reinvent the wheel in case of need.
|
||||
of the library.<br/>
|
||||
Many of these tools are also useful in everyday work. Therefore, it's worth
|
||||
describing them so as not to reinvent the wheel in case of need.
|
||||
|
||||
# Any as in any type
|
||||
|
||||
`EnTT` comes with its own `any` type. It may seem redundant considering that
|
||||
C++17 introduced `std::any`, but it is not (hopefully).<br/>
|
||||
`EnTT` offers its own `any` type. It may seem redundant considering that C++17
|
||||
introduced `std::any`, but it is not (hopefully).<br/>
|
||||
First of all, the _type_ returned by an `std::any` is a const reference to an
|
||||
`std::type_info`, an implementation defined class that's not something everyone
|
||||
wants to see in a software. Furthermore, there is no way to connect it with the
|
||||
type system of the library and therefore with its integrated RTTI support.<br/>
|
||||
Note that this class is largely used internally by the library itself.
|
||||
wants to see in a software. Furthermore, there is no way to bind it to the type
|
||||
system of the library and therefore with its integrated RTTI support.
|
||||
|
||||
The API is very similar to that of its most famous counterpart, mainly because
|
||||
this class serves the same purpose of being an opaque container for any type of
|
||||
value.<br/>
|
||||
Instances of `any` also minimize the number of allocations by relying on a well
|
||||
known technique called _small buffer optimization_ and a fake vtable.
|
||||
The `any` API is very similar to that of its most famous counterpart, mainly
|
||||
because this class serves the same purpose of being an opaque container for any
|
||||
type of value.<br/>
|
||||
Instances also minimize the number of allocations by relying on a well known
|
||||
technique called _small buffer optimization_ and a fake vtable.
|
||||
|
||||
Creating an object of the `any` type, whether empty or not, is trivial:
|
||||
|
||||
@ -93,8 +92,8 @@ Furthermore, an instance of `any` isn't tied to an actual type. Therefore, the
|
||||
wrapper is reconfigured when it's assigned a new object of a type other than
|
||||
the one it contains.
|
||||
|
||||
There exists also a way to directly assign a value to the variable contained by
|
||||
an `entt::any`, without necessarily replacing it. This is especially useful when
|
||||
There is also a way to directly assign a value to the variable contained by an
|
||||
`entt::any`, without necessarily replacing it. This is especially useful when
|
||||
the object is used in _aliasing mode_, as described below:
|
||||
|
||||
```cpp
|
||||
@ -108,15 +107,15 @@ any.assign(value);
|
||||
any.assign(std::move(value));
|
||||
```
|
||||
|
||||
The `any` class will also perform a check on the type information and whether or
|
||||
not the original type was copy or move assignable, as appropriate.<br/>
|
||||
In all cases, the `assign` function returns a boolean value to indicate the
|
||||
success or failure of the operation.
|
||||
The `any` class performs a check on the type information and whether or not the
|
||||
original type was copy or move assignable, as appropriate.<br/>
|
||||
In all cases, the `assign` function returns a boolean value that is true in case
|
||||
of success and false otherwise.
|
||||
|
||||
When in doubt about the type of object contained, the `type` member function of
|
||||
`any` returns a const reference to the `type_info` associated with its element,
|
||||
or `type_id<void>()` if the container is empty. The type is also used internally
|
||||
when comparing two `any` objects:
|
||||
When in doubt about the type of object contained, the `type` member function
|
||||
returns a const reference to the `type_info` associated with its element, or
|
||||
`type_id<void>()` if the container is empty.<br/>
|
||||
The type is also used internally when comparing two `any` objects:
|
||||
|
||||
```cpp
|
||||
if(any == empty) { /* ... */ }
|
||||
@ -125,7 +124,7 @@ if(any == empty) { /* ... */ }
|
||||
In this case, before proceeding with a comparison, it's verified that the _type_
|
||||
of the two objects is actually the same.<br/>
|
||||
Refer to the `EnTT` type system documentation for more details about how
|
||||
`type_info` works and on possible risks of a comparison.
|
||||
`type_info` works and the possible risks of a comparison.
|
||||
|
||||
A particularly interesting feature of this class is that it can also be used as
|
||||
an opaque container for const and non-const references:
|
||||
@ -153,22 +152,19 @@ entt::any ref = other.as_ref();
|
||||
```
|
||||
|
||||
In this case, it doesn't matter if the original container actually holds an
|
||||
object or acts already as a reference for unmanaged elements, the new instance
|
||||
thus created won't create copies and will only serve as a reference for the
|
||||
original item.<br/>
|
||||
This means that, starting from the example above, both `ref` and `other` will
|
||||
point to the same object, whether it's initially contained in `other` or already
|
||||
an unmanaged element.
|
||||
object or is as a reference for unmanaged elements already. The new instance
|
||||
thus created doesn't create copies and only serves as a reference for the
|
||||
original item.
|
||||
|
||||
As a side note, it's worth mentioning that, while everything works transparently
|
||||
when it comes to non-const references, there are some exceptions when it comes
|
||||
to const references.<br/>
|
||||
It's worth mentioning that, while everything works transparently when it comes
|
||||
to non-const references, there are some exceptions when it comes to const
|
||||
references.<br/>
|
||||
In particular, the `data` member function invoked on a non-const instance of
|
||||
`any` that wraps a const reference will return a null pointer in all cases.
|
||||
`any` that wraps a const reference returns a null pointer in all cases.
|
||||
|
||||
To cast an instance of `any` to a type, the library offers a set of `any_cast`
|
||||
functions in all respects similar to their most famous counterparts.<br/>
|
||||
The only difference is that, in the case of `EnTT`, these won't raise exceptions
|
||||
The only difference is that, in the case of `EnTT`, they won't raise exceptions
|
||||
but will only trigger an assert in debug mode, otherwise resulting in undefined
|
||||
behavior in case of misuse in release mode.
|
||||
|
||||
@ -188,31 +184,23 @@ using my_any = entt::basic_any<sizeof(double[4])>;
|
||||
This feature, in addition to allowing the choice of a size that best suits the
|
||||
needs of an application, also offers the possibility of forcing dynamic creation
|
||||
of objects during construction.<br/>
|
||||
In other terms, if the size is 0, `any` avoids the use of any optimization and
|
||||
always dynamically allocates objects (except for aliasing cases).
|
||||
|
||||
Note that the size of the internal storage as well as the alignment requirements
|
||||
are directly part of the type and therefore contribute to define different types
|
||||
that won't be able to interoperate with each other.
|
||||
In other terms, if the size is 0, `any` suppresses the small buffer optimization
|
||||
and always dynamically allocates objects (except for aliasing cases).
|
||||
|
||||
## Alignment requirement
|
||||
|
||||
The alignment requirement is optional and by default the most stringent (the
|
||||
largest) for any object whose size is at most equal to the one provided.<br/>
|
||||
The `basic_any` class template inspects the alignment requirements in each case,
|
||||
even when not provided and may decide not to use the small buffer optimization
|
||||
in order to meet them.
|
||||
|
||||
The alignment requirement is provided as an optional second parameter following
|
||||
the desired size for the internal storage:
|
||||
It's provided as an optional second parameter following the desired size for the
|
||||
internal storage:
|
||||
|
||||
```cpp
|
||||
using my_any = entt::basic_any<sizeof(double[4]), alignof(double[4])>;
|
||||
```
|
||||
|
||||
Note that the alignment requirements as well as the size of the internal storage
|
||||
are directly part of the type and therefore contribute to define different types
|
||||
that won't be able to interoperate with each other.
|
||||
The `basic_any` class template inspects the alignment requirements in each case,
|
||||
even when not provided and may decide not to use the small buffer optimization
|
||||
in order to meet them.
|
||||
|
||||
# Compressed pair
|
||||
|
||||
@ -225,8 +213,8 @@ is more important than having some cool and probably useless feature.
|
||||
|
||||
Although the API is very close to that of `std::pair` (apart from the fact that
|
||||
the template parameters are inferred from the constructor and therefore there is
|
||||
no` entt::make_compressed_pair`), the major difference is that `first` and
|
||||
`second` are functions for implementation needs:
|
||||
no `entt::make_compressed_pair`), the major difference is that `first` and
|
||||
`second` are functions for implementation requirements:
|
||||
|
||||
```cpp
|
||||
entt::compressed_pair pair{0, 3.};
|
||||
@ -239,16 +227,15 @@ intuition. At the end of the day, it's just a pair and nothing more.
|
||||
# Enum as bitmask
|
||||
|
||||
Sometimes it's useful to be able to use enums as bitmasks. However, enum classes
|
||||
aren't really suitable for the purpose out of the box. Main problem is that they
|
||||
don't convert implicitly to their underlying type.<br/>
|
||||
All that remains is to make a choice between using old-fashioned enums (with all
|
||||
their problems that I don't want to discuss here) or writing _ugly_ code.
|
||||
aren't really suitable for the purpose. Main problem is that they don't convert
|
||||
implicitly to their underlying type.<br/>
|
||||
The choice is then between using old-fashioned enums (with all their problems
|
||||
that I don't want to discuss here) or writing _ugly_ code.
|
||||
|
||||
Fortunately, there is also a third way: adding enough operators in the global
|
||||
scope to treat enum classes as bitmask transparently.<br/>
|
||||
The ultimate goal is to be able to write code like the following (or maybe
|
||||
something more meaningful, but this should give a grasp and remain simple at the
|
||||
same time):
|
||||
scope to treat enum classes as bitmasks transparently.<br/>
|
||||
The ultimate goal is to write code like the following (or maybe something more
|
||||
meaningful, but this should give a grasp and remain simple at the same time):
|
||||
|
||||
```cpp
|
||||
enum class my_flag {
|
||||
@ -261,11 +248,11 @@ const my_flag flags = my_flag::enabled;
|
||||
const bool is_enabled = !!(flags & my_flag::enabled);
|
||||
```
|
||||
|
||||
The problem with adding all operators to the global scope is that these will
|
||||
come into play even when not required, with the risk of introducing errors that
|
||||
are difficult to deal with.<br/>
|
||||
The problem with adding all operators to the global scope is that these come
|
||||
into play even when not required, with the risk of introducing errors that are
|
||||
difficult to deal with.<br/>
|
||||
However, C++ offers enough tools to get around this problem. In particular, the
|
||||
library requires users to register all enum classes for which bitmask support
|
||||
library requires users to register the enum classes for which bitmask support
|
||||
should be enabled:
|
||||
|
||||
```cpp
|
||||
@ -276,7 +263,7 @@ struct entt::enum_as_bitmask<my_flag>
|
||||
```
|
||||
|
||||
This is handy when dealing with enum classes defined by third party libraries
|
||||
and over which the users have no control. However, it's also verbose and can be
|
||||
and over which the user has no control. However, it's also verbose and can be
|
||||
avoided by adding a specific value to the enum class itself:
|
||||
|
||||
```cpp
|
||||
@ -289,23 +276,21 @@ enum class my_flag {
|
||||
```
|
||||
|
||||
In this case, there is no need to specialize the `enum_as_bitmask` traits, since
|
||||
`EnTT` will automatically detect the flag and enable the bitmask support.<br/>
|
||||
Once the enum class has been registered (in one way or the other) all the most
|
||||
common operators will be available, such as `&`, `|` but also `&=` and `|=`.
|
||||
`EnTT` automatically detects the flag and enables the bitmask support.<br/>
|
||||
Once the enum class is registered (in one way or the other), the most common
|
||||
operators such as `&`, `|` but also `&=` and `|=` are available for use.
|
||||
|
||||
Refer to the official documentation for the full list of operators.
|
||||
|
||||
# Hashed strings
|
||||
|
||||
A hashed string is a zero overhead unique identifier. Users can use
|
||||
human-readable identifiers in the codebase while using their numeric
|
||||
counterparts at runtime, thus without affecting performance.<br/>
|
||||
Hashed strings are human-readable identifiers in the codebase that turn into
|
||||
numeric values at runtime, thus without affecting performance.<br/>
|
||||
The class has an implicit `constexpr` constructor that chews a bunch of
|
||||
characters. Once created, all what one can do with it is getting back the
|
||||
original string through the `data` member function or converting the instance
|
||||
into a number.<br/>
|
||||
The good part is that a hashed string can be used wherever a constant expression
|
||||
is required and no _string-to-number_ conversion will take place at runtime if
|
||||
used carefully.
|
||||
characters. Once created, one can get the original string by means of the `data`
|
||||
member function or convert the instance into a number.<br/>
|
||||
A hashed string is well suited wherever a constant expression is required. No
|
||||
_string-to-number_ conversion will take place at runtime if used carefully.
|
||||
|
||||
Example of use:
|
||||
|
||||
@ -318,19 +303,18 @@ auto resource = load(entt::hashed_string{"gui/background"});
|
||||
```
|
||||
|
||||
There is also a _user defined literal_ dedicated to hashed strings to make them
|
||||
more user-friendly:
|
||||
more _user-friendly_:
|
||||
|
||||
```cpp
|
||||
using namespace entt::literals;
|
||||
constexpr auto str = "text"_hs;
|
||||
```
|
||||
|
||||
To use it, remember that all user defined literals in `EnTT` are enclosed in the
|
||||
`entt::literals` namespace. Therefore, the entire namespace or selectively the
|
||||
literal of interest must be explicitly included before each use, a bit like
|
||||
`std::literals`.<br/>
|
||||
Finally, in case users need to create hashed strings at runtime, this class also
|
||||
offers the necessary functionalities:
|
||||
User defined literals in `EnTT` are enclosed in the `entt::literals` namespace.
|
||||
Therefore, the entire namespace or selectively the literal of interest must be
|
||||
explicitly included before each use, a bit like `std::literals`.<br/>
|
||||
The class also offers the necessary functionalities to create hashed strings at
|
||||
runtime:
|
||||
|
||||
```cpp
|
||||
std::string orig{"text"};
|
||||
@ -343,16 +327,14 @@ const auto hash = entt::hashed_string::value(orig.c_str());
|
||||
```
|
||||
|
||||
This possibility shouldn't be exploited in tight loops, since the computation
|
||||
takes place at runtime and no longer at compile-time and could therefore impact
|
||||
takes place at runtime and no longer at compile-time. It could therefore affect
|
||||
performance to some degrees.
|
||||
|
||||
## Wide characters
|
||||
|
||||
The hashed string has a design that is close to that of an `std::basic_string`.
|
||||
It means that `hashed_string` is nothing more than an alias for
|
||||
`basic_hashed_string<char>`. For those who want to use the C++ type for wide
|
||||
character representation, there exists also the alias `hashed_wstring` for
|
||||
`basic_hashed_string<wchar_t>`.<br/>
|
||||
The `hashed_string` class is an alias for `basic_hashed_string<char>`. To use
|
||||
the C++ type for wide character representations, there exists also the alias
|
||||
`hashed_wstring` for `basic_hashed_string<wchar_t>`.<br/>
|
||||
In this case, the user defined literal to use to create hashed strings on the
|
||||
fly is `_hws`:
|
||||
|
||||
@ -360,16 +342,15 @@ fly is `_hws`:
|
||||
constexpr auto str = L"text"_hws;
|
||||
```
|
||||
|
||||
Note that the hash type of the `hashed_wstring` is the same of its counterpart.
|
||||
The hash type of `hashed_wstring` is the same as its counterpart.
|
||||
|
||||
## Conflicts
|
||||
|
||||
The hashed string class uses internally FNV-1a to compute the numeric
|
||||
counterpart of a string. Because of the _pigeonhole principle_, conflicts are
|
||||
possible. This is a fact.<br/>
|
||||
The hashed string class uses FNV-1a internally to hash strings. Because of the
|
||||
_pigeonhole principle_, conflicts are possible. This is a fact.<br/>
|
||||
There is no silver bullet to solve the problem of conflicts when dealing with
|
||||
hashing functions. In this case, the best solution seemed to be to give up.
|
||||
That's all.<br/>
|
||||
hashing functions. In this case, the best solution is likely to give up. That's
|
||||
all.<br/>
|
||||
After all, human-readable unique identifiers aren't something strictly defined
|
||||
and over which users have not the control. Choosing a slightly different
|
||||
identifier is probably the best solution to make the conflict disappear in this
|
||||
@ -377,8 +358,8 @@ case.
|
||||
|
||||
# Iterators
|
||||
|
||||
Writing and working with iterators isn't always easy and more often than not
|
||||
leads to duplicated code.<br/>
|
||||
Writing and working with iterators isn't always easy. More often than not it
|
||||
also leads to duplicated code.<br/>
|
||||
`EnTT` tries to overcome this problem by offering some utilities designed to
|
||||
make this hard work easier.
|
||||
|
||||
@ -431,7 +412,7 @@ user.
|
||||
## Iterable adaptor
|
||||
|
||||
Typically, a container class provides `begin` and `end` member functions (with
|
||||
their const counterparts) to be iterated by the user.<br/>
|
||||
their const counterparts) for iteration.<br/>
|
||||
However, it can happen that a class offers multiple iteration methods or allows
|
||||
users to iterate different sets of _elements_.
|
||||
|
||||
@ -452,8 +433,8 @@ by returning an iterable object for the purpose.
|
||||
There are a handful of tools within `EnTT` to interact with memory in one way or
|
||||
another.<br/>
|
||||
Some are geared towards simplifying the implementation of (internal or external)
|
||||
allocator aware containers. Others, on the other hand, are designed to help the
|
||||
developer with everyday problems.
|
||||
allocator aware containers. Others are designed to help the developer with
|
||||
everyday problems.
|
||||
|
||||
The former are very specific and for niche problems. These are tools designed to
|
||||
unwrap fancy or plain pointers (`to_address`) or to help forget the meaning of
|
||||
@ -481,7 +462,7 @@ modulus and for this reason preferred in many areas.
|
||||
|
||||
A nasty thing in C++ (at least up to C++20) is the fact that shared pointers
|
||||
support allocators while unique pointers don't.<br/>
|
||||
There is a proposal at the moment that also shows among the other things how
|
||||
There is a proposal at the moment that also shows (among the other things) how
|
||||
this can be implemented without any compiler support.
|
||||
|
||||
The `allocate_unique` function follows this proposal, making a virtue out of
|
||||
@ -498,13 +479,16 @@ the same feature.
|
||||
# Monostate
|
||||
|
||||
The monostate pattern is often presented as an alternative to a singleton based
|
||||
configuration system. This is exactly its purpose in `EnTT`. Moreover, this
|
||||
implementation is thread safe by design (hopefully).<br/>
|
||||
Keys are represented by hashed strings, values are basic types like `int`s or
|
||||
`bool`s. Values of different types can be associated to each key, even more than
|
||||
one at a time. Because of this, users must pay attention to use the same type
|
||||
both during an assignment and when they try to read back their data. Otherwise,
|
||||
they will probably incur in unexpected results.
|
||||
configuration system.<br/>
|
||||
This is exactly its purpose in `EnTT`. Moreover, this implementation is thread
|
||||
safe by design (hopefully).
|
||||
|
||||
Keys are integral values (easily obtained by hashed strings), values are basic
|
||||
types like `int`s or `bool`s. Values of different types can be associated with
|
||||
each key, even more than one at a time.<br/>
|
||||
Because of this, one should pay attention to use the same type both during an
|
||||
assignment and when trying to read back the data. Otherwise, there is the risk
|
||||
to incur in unexpected results.
|
||||
|
||||
Example of use:
|
||||
|
||||
@ -542,17 +526,10 @@ Basically, the whole system relies on a handful of classes. In particular:
|
||||
auto index = entt::type_index<a_type>::value();
|
||||
```
|
||||
|
||||
The returned value isn't guaranteed to be stable across different runs.
|
||||
The returned value isn't guaranteed to be stable across different runs.<br/>
|
||||
However, it can be very useful as index in associative and unordered
|
||||
associative containers or for positional accesses in a vector or an array.
|
||||
|
||||
So as not to conflict with the other tools available, the `family` class isn't
|
||||
used to generate these indexes. Therefore, the numeric identifiers returned by
|
||||
the two tools may differ.<br/>
|
||||
On the other hand, this leaves users with full powers over the `family` class
|
||||
and therefore the generation of custom runtime sequences of indices for their
|
||||
own purposes, if necessary.
|
||||
|
||||
An external generator can also be used if needed. In fact, `type_index` can be
|
||||
specialized by type and is also _sfinae-friendly_ in order to allow more
|
||||
refined specializations such as:
|
||||
@ -566,7 +543,7 @@ Basically, the whole system relies on a handful of classes. In particular:
|
||||
};
|
||||
```
|
||||
|
||||
Note that indexes **must** still be generated sequentially in this case.<br/>
|
||||
Indexes **must** be sequentially generated in this case.<br/>
|
||||
The tool is widely used within `EnTT`. Generating indices not sequentially
|
||||
would break an assumption and would likely lead to undesired behaviors.
|
||||
|
||||
@ -583,14 +560,14 @@ Basically, the whole system relies on a handful of classes. In particular:
|
||||
This function **can** use non-standard features of the language for its own
|
||||
purposes. This makes it possible to provide compile-time identifiers that
|
||||
remain stable across different runs.<br/>
|
||||
In all cases, users can prevent the library from using these features by means
|
||||
of the `ENTT_STANDARD_CPP` definition. In this case, there is no guarantee
|
||||
that identifiers remain stable across executions. Moreover, they are generated
|
||||
Users can prevent the library from using these features by means of the
|
||||
`ENTT_STANDARD_CPP` definition. In this case, there is no guarantee that
|
||||
identifiers remain stable across executions. Moreover, they are generated
|
||||
at runtime and are no longer a compile-time thing.
|
||||
|
||||
As for `type_index`, also `type_hash` is a _sfinae-friendly_ class that can be
|
||||
specialized in order to customize its behavior globally or on a per-type or
|
||||
per-traits basis.
|
||||
As it happens with `type_index`, also `type_hash` is a _sfinae-friendly_ class
|
||||
that can be specialized in order to customize its behavior globally or on a
|
||||
per-type or per-traits basis.
|
||||
|
||||
* The name associated with a given type:
|
||||
|
||||
@ -598,10 +575,9 @@ Basically, the whole system relies on a handful of classes. In particular:
|
||||
auto name = entt::type_name<a_type>::value();
|
||||
```
|
||||
|
||||
The name associated with a type is extracted from some information generally
|
||||
made available by the compiler in use. Therefore, it may differ depending on
|
||||
the compiler and may be empty in the event that this information isn't
|
||||
available.<br/>
|
||||
This value is extracted from some information generally made available by the
|
||||
compiler in use. Therefore, it may differ depending on the compiler and may be
|
||||
empty in the event that this information isn't available.<br/>
|
||||
For example, given the following class:
|
||||
|
||||
```cpp
|
||||
@ -612,21 +588,20 @@ Basically, the whole system relies on a handful of classes. In particular:
|
||||
when MSVC is in use.<br/>
|
||||
Most of the time the name is also retrieved at compile-time and is therefore
|
||||
always returned through an `std::string_view`. Users can easily access it and
|
||||
modify it as needed, for example by removing the word `struct` to standardize
|
||||
the result. `EnTT` won't do this for obvious reasons, since it requires
|
||||
copying and creating a new string potentially at runtime.
|
||||
modify it as needed, for example by removing the word `struct` to normalize
|
||||
the result. `EnTT` doesn't do this for obvious reasons, since it would be
|
||||
creating a new string at runtime otherwise.
|
||||
|
||||
This function **can** use non-standard features of the language for its own
|
||||
purposes. Users can prevent the library from using non-standard features by
|
||||
means of the `ENTT_STANDARD_CPP` definition. In this case, the name will be
|
||||
empty by default.
|
||||
purposes. Users can prevent the library from using these features by means of
|
||||
the `ENTT_STANDARD_CPP` definition. In this case, the name is just empty.
|
||||
|
||||
As for `type_index`, also `type_name` is a _sfinae-friendly_ class that can be
|
||||
specialized in order to customize its behavior globally or on a per-type or
|
||||
per-traits basis.
|
||||
As it happens with `type_index`, also `type_name` is a _sfinae-friendly_ class
|
||||
that can be specialized in order to customize its behavior globally or on a
|
||||
per-type or per-traits basis.
|
||||
|
||||
These are then combined into utilities that aim to offer an API that is somewhat
|
||||
similar to that offered by the language.
|
||||
similar to that made available by the standard library.
|
||||
|
||||
### Type info
|
||||
|
||||
@ -708,8 +683,8 @@ In fact, although this is quite rare, it's not entirely excluded.
|
||||
|
||||
Another case where two types are assigned the same identifier is when classes
|
||||
from different contexts (for example two or more libraries loaded at runtime)
|
||||
have the same fully qualified name. In this case, also `type_name` will return
|
||||
the same value for the two types.<br/>
|
||||
have the same fully qualified name. In this case, `type_name` returns the same
|
||||
value for the two types.<br/>
|
||||
Fortunately, there are several easy ways to deal with this:
|
||||
|
||||
* The most trivial one is to define the `ENTT_STANDARD_CPP` macro. Runtime
|
||||
@ -739,9 +714,9 @@ offered by this module.
|
||||
|
||||
### Size of
|
||||
|
||||
The standard operator `sizeof` complains when users provide it for example with
|
||||
function or incomplete types. On the other hand, it's guaranteed that its result
|
||||
is always nonzero, even if applied to an empty class type.<br/>
|
||||
The standard operator `sizeof` complains if users provide it with functions or
|
||||
incomplete types. On the other hand, it's guaranteed that its result is always
|
||||
non-zero, even if applied to an empty class type.<br/>
|
||||
This small class combines the two and offers an alternative to `sizeof` that
|
||||
works under all circumstances, returning zero if the type isn't supported:
|
||||
|
||||
@ -777,8 +752,8 @@ A utility to easily transfer the constness of a type to another type:
|
||||
using type = entt::constness_as_t<dst_type, const src_type>;
|
||||
```
|
||||
|
||||
The trait is subject to the rules of the language. Therefore, for example,
|
||||
transferring constness between references won't give the desired effect.
|
||||
The trait is subject to the rules of the language. For example, _transferring_
|
||||
constness between references won't give the desired effect.
|
||||
|
||||
### Member class type
|
||||
|
||||
@ -798,7 +773,7 @@ A utility to quickly find the n-th argument of a function, member function or
|
||||
data member (for blind operations on opaque types):
|
||||
|
||||
```cpp
|
||||
using type = entt::nt_argument_t<1u, &clazz::member>;
|
||||
using type = entt::nth_argument_t<1u, &clazz::member>;
|
||||
```
|
||||
|
||||
Disambiguation of overloaded functions is the responsibility of the user, should
|
||||
@ -825,8 +800,8 @@ registry.emplace<enemy_tag>(entity);
|
||||
|
||||
### Tag
|
||||
|
||||
Since `id_type` is very important and widely used in `EnTT`, there is a more
|
||||
user-friendly shortcut for the creation of integral constants based on it.<br/>
|
||||
Type `id_type` is very important and widely used in `EnTT`. Therefore, there is
|
||||
a more user-friendly shortcut for the creation of constants based on it.<br/>
|
||||
This shortcut is the alias template `entt::tag`.
|
||||
|
||||
If used in combination with hashed strings, it helps to use human-readable names
|
||||
@ -918,8 +893,8 @@ Perhaps a bit ugly to see in a codebase but it gets the job done at least.
|
||||
|
||||
## Runtime generator
|
||||
|
||||
To generate sequential numeric identifiers at runtime, `EnTT` offers the
|
||||
`family` class template:
|
||||
The `family` class template helps to generate sequential numeric identifiers for
|
||||
types at runtime:
|
||||
|
||||
```cpp
|
||||
// defines a custom generator
|
||||
@ -936,8 +911,8 @@ numeric identifier for the given type.<br/>
|
||||
The generator is customizable, so as to get different _sequences_ for different
|
||||
purposes if needed.
|
||||
|
||||
Please, note that identifiers aren't guaranteed to be stable across different
|
||||
runs. Indeed it mostly depends on the flow of execution.
|
||||
Identifiers aren't guaranteed to be stable across different runs. Indeed it
|
||||
mostly depends on the flow of execution.
|
||||
|
||||
# Utilities
|
||||
|
||||
|
1512
docs/md/entity.md
1512
docs/md/entity.md
File diff suppressed because it is too large
Load Diff
@ -193,7 +193,7 @@ to mitigate the problem makes it manageable.
|
||||
|
||||
## Which functions trigger which signals
|
||||
|
||||
The `registry` class offers three signals that are emitted following specific
|
||||
Storage classes offer 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:
|
||||
|
||||
|
175
docs/md/graph.md
175
docs/md/graph.md
@ -14,7 +14,6 @@
|
||||
* [Fake resources and order of execution](#fake-resources-and-order-of-execution)
|
||||
* [Sync points](#sync-points)
|
||||
* [Execution graph](#execution-graph)
|
||||
|
||||
<!--
|
||||
@endcond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
@ -23,15 +22,15 @@
|
||||
|
||||
`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_.
|
||||
Quite the opposite is true though. 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
|
||||
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.
|
||||
@ -49,7 +48,7 @@ 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
|
||||
and modification of an element takes place via the `contains`, `insert` and
|
||||
`erase` functions rather than a double call to an `operator[]`:
|
||||
|
||||
```cpp
|
||||
@ -60,14 +59,14 @@ if(adjacency_matrix.contains(0u, 1u)) {
|
||||
}
|
||||
```
|
||||
|
||||
Both `insert` and` erase` are idempotent functions which have no effect if the
|
||||
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).
|
||||
a boolean value indicating whether the element was newly inserted or not. The
|
||||
second one 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:
|
||||
An adjacency matrix is 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};
|
||||
@ -82,8 +81,8 @@ 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:
|
||||
The same result is obtained with the following snippet, since the vertices are
|
||||
plain unsigned integral values:
|
||||
|
||||
```cpp
|
||||
for(auto last = adjacency_matrix.size(), pos = {}; pos < last; ++pos) {
|
||||
@ -93,8 +92,8 @@ 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:
|
||||
`edges` function returns an iterable object that is used to get them as pairs of
|
||||
vertices:
|
||||
|
||||
```cpp
|
||||
for(auto [lhs, rhs]: adjacency_matrix.edges()) {
|
||||
@ -102,8 +101,8 @@ 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:
|
||||
If the goal is to visit all the in- or out-edges of a given vertex instead, the
|
||||
`in_edges` and `out_edges` functions are meant for that:
|
||||
|
||||
```cpp
|
||||
for(auto [lhs, rhs]: adjacency_matrix.out_edges(3u)) {
|
||||
@ -111,11 +110,11 @@ 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/>
|
||||
Both the 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.
|
||||
the functionalities one would expect from this type of containers, such as
|
||||
`clear` or 'get_allocator` and so on.
|
||||
|
||||
## Graphviz dot language
|
||||
|
||||
@ -129,19 +128,19 @@ 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:
|
||||
It's also possible to provide a callback to which the vertices are passed and
|
||||
which can be used to add (`dot`) properties to the output as needed:
|
||||
|
||||
```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.
|
||||
externally managed data to the graph being converted.
|
||||
|
||||
# Flow builder
|
||||
|
||||
@ -155,42 +154,42 @@ 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/>
|
||||
Once all tasks are 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.
|
||||
_vertices_. The _vertex_ itself is 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/>
|
||||
In other terms, 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:
|
||||
Once a flow builder is created (which requires no constructor arguments), the
|
||||
first thing to do is to bind a task. This tells to the builder _who_ intends to
|
||||
consume the resources that are 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,
|
||||
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 isn't 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.
|
||||
own tools if necessary.
|
||||
|
||||
Once a task has been associated with the flow builder, it can be assigned
|
||||
read-only or read-write resources, as appropriate:
|
||||
Once a task is associated with the flow builder, it's also assigned read-only or
|
||||
read-write resources as appropriate:
|
||||
|
||||
```cpp
|
||||
builder
|
||||
@ -203,13 +202,87 @@ builder
|
||||
|
||||
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
|
||||
Also in the case of resources, they 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.
|
||||
|
||||
### Rebinding
|
||||
|
||||
The `flow` class is resource based rather than task based. This means that graph
|
||||
generation is driven by resources and not by the order of _appearance_ of tasks
|
||||
during flow definition.<br/>
|
||||
Although this concept is particularly important, it's almost irrelevant for the
|
||||
vast majority of cases. However, it becomes relevant when _rebinding_ resources
|
||||
or tasks.
|
||||
|
||||
In fact, nothing prevents rebinding elements to a flow.<br/>
|
||||
However, the behavior changes slightly from case to case and has some nuances
|
||||
that it's worth knowing about.
|
||||
|
||||
Directly rebinding a resource without the task being replaced trivially results
|
||||
in the task's access mode for that resource being updated:
|
||||
|
||||
```cpp
|
||||
builder.bind("task"_hs).rw("resource"_hs).ro("resource"_hs)
|
||||
```
|
||||
|
||||
In this case, the resource is accessed in read-only mode, regardless of the
|
||||
first call to `rw`.<br/>
|
||||
Behind the scenes, the call doesn't actually _replace_ the previous one but is
|
||||
queued after it instead, overwriting it when generating the graph. Thus, a large
|
||||
number of resource rebindings may even impact processing times (very difficult
|
||||
to observe but theoretically possible).
|
||||
|
||||
Rebinding resources and also combining it with changes to tasks has far more
|
||||
implications instead.<br/>
|
||||
As mentioned, graph generation takes place starting from resources and not from
|
||||
tasks. Therefore, the result may not be as expected:
|
||||
|
||||
```cpp
|
||||
builder
|
||||
.bind("task_1"_hs)
|
||||
.ro("resource"_hs)
|
||||
.bind("task_2"_hs)
|
||||
.ro("resource"_hs)
|
||||
.bind("task_1"_hs)
|
||||
.rw("resource"_hs);
|
||||
```
|
||||
|
||||
What happens here is that the resource first _sees_ a read-only access request
|
||||
from the first task, then a read-write request from the second task and finally
|
||||
a new read-only request from the first task.<br/>
|
||||
Although this definition would probably be counted as an error, the resulting
|
||||
graph may be unexpected. This in fact consists of a single edge outgoing from
|
||||
the second task and directed to the first task.<br/>
|
||||
To intuitively understand what happens, it's enough to think of the fact that a
|
||||
task never has an edge pointing to itself.
|
||||
|
||||
While not obvious, this approach has its pros and cons like any other solution.
|
||||
For example, creating loops is actually simple in the context of resource-based
|
||||
graph generations:
|
||||
|
||||
```cpp
|
||||
builder
|
||||
.bind("task_1"_hs)
|
||||
.rw("resource"_hs)
|
||||
.bind("task_2"_hs)
|
||||
.rw("resource"_hs)
|
||||
.bind("task_1"_hs)
|
||||
.rw("resource"_hs);
|
||||
```
|
||||
|
||||
As expected, this definition leads to the creation of two edges that define a
|
||||
loop between the two tasks.
|
||||
|
||||
As a general rule, rebinding resources and tasks is highly discouraged because
|
||||
it could lead to subtle bugs if users don't know what they're doing.<br/>
|
||||
However, once the mechanisms of resource-based graph generation are understood,
|
||||
it can offer to the expert user a flexibility and a range of possibilities
|
||||
otherwise inaccessible.
|
||||
|
||||
## Fake resources and order of execution
|
||||
|
||||
The flow builder doesn't offer the ability to specify when a task should execute
|
||||
@ -217,10 +290,10 @@ 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/>
|
||||
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:
|
||||
than parallel scheduling, it's possible to make use of fake resources to rule on
|
||||
the execution order:
|
||||
|
||||
```cpp
|
||||
builder
|
||||
@ -235,10 +308,10 @@ builder
|
||||
.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
|
||||
This snippet forces the execution of `task_1` **before** `task_2` and `task_3`.
|
||||
This is due to the fact that the former 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:
|
||||
Similarly, it's possible to force a task to run **after** a certain group:
|
||||
|
||||
```cpp
|
||||
builder
|
||||
@ -261,7 +334,7 @@ others tasks.
|
||||
|
||||
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
|
||||
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
|
||||
@ -283,7 +356,7 @@ all specified constraints to return the best scheduling for the vertices:
|
||||
entt::adjacency_matrix<entt::directed_tag> graph = builder.graph();
|
||||
```
|
||||
|
||||
The search for the main vertices, that is those without in-edges, is usually the
|
||||
Searching for the main vertices (that is, those without in-edges) is usually the
|
||||
first thing required:
|
||||
|
||||
```cpp
|
||||
@ -294,6 +367,6 @@ for(auto &&vertex: graph) {
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
Then it's possible to instantiate an execution graph by means of other functions
|
||||
such as `out_edges` to retrieve the children of a given task or `edges` to get
|
||||
the identifiers.
|
||||
|
@ -19,14 +19,12 @@
|
||||
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 with different types.<br/>
|
||||
Fortunately, nowadays using `EnTT` across boundaries is much easier.
|
||||
Fortunately, nowadays `EnTT` works smoothly across boundaries.
|
||||
|
||||
## Smooth until proven otherwise
|
||||
|
||||
Many classes in `EnTT` make extensive use of type erasure for their purposes.
|
||||
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/>
|
||||
This raises the need to identify objects whose type has been erased.<br/>
|
||||
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
|
||||
@ -36,13 +34,13 @@ 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.
|
||||
|
||||
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/>
|
||||
`ENTT_API_IMPORT` are 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.
|
||||
|
||||
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/>
|
||||
For those who need more details, the test suite contains many 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.
|
||||
|
||||
@ -70,8 +68,8 @@ entt::locator<entt::meta_ctx>::reset(handle);
|
||||
|
||||
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
|
||||
Note that _replacing_ the main context doesn't also propagate changes across
|
||||
boundaries. In other words, replacing a context results in the decoupling of the
|
||||
two sides and therefore a divergence in the contents.
|
||||
|
||||
## Memory Management
|
||||
|
@ -1,5 +1,22 @@
|
||||
# EnTT in Action
|
||||
|
||||
<!--
|
||||
@cond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
# Table of Contents
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [EnTT in Action](#entt-in-action)
|
||||
* [Games](#games)
|
||||
* [Engines and the like](#engines-and-the-like)
|
||||
* [Articles, videos and blog posts](#articles-videos-and-blog-posts)
|
||||
* [Any Other Business](#any-other-business)
|
||||
<!--
|
||||
@endcond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
|
||||
# Introduction
|
||||
|
||||
`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
|
||||
@ -7,13 +24,18 @@ 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
|
||||
documented but the authors didn't make explicit announcements or contacted me
|
||||
directly.
|
||||
a reference.<br/>
|
||||
Where I put the word _apparently_ means that the use of `EnTT` is documented but
|
||||
the authors didn't make explicit announcements or contacted me directly.
|
||||
|
||||
I hope this list can grow much more in the future:
|
||||
If you know of other resources out there that are about `EnTT`, feel free to
|
||||
open an issue or a PR and I'll be glad to add them to this page.<br/>
|
||||
I hope the following lists can grow much more in the future.
|
||||
|
||||
# EnTT in Action
|
||||
|
||||
## Games
|
||||
|
||||
* Games:
|
||||
* [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.
|
||||
@ -103,7 +125,8 @@ I hope this list can grow much more in the future:
|
||||
* [Confetti Party](https://github.com/hexerei/entt-confetti): C++ sample
|
||||
application as a starting point using `EnTT` and `SDL2`.
|
||||
|
||||
* Engines and the like:
|
||||
## 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
|
||||
@ -168,8 +191,19 @@ I hope this list can grow much more in the future:
|
||||
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.
|
||||
* [The Worst Engine](https://github.com/Parasik72/TWE): a game engine based on
|
||||
OpenGL.
|
||||
* [Ecsact](https://ecsact.dev/): a language aimed at describing ECS, with a
|
||||
[runtime implementation](https://github.com/ecsact-dev/ecsact_rt_entt) based
|
||||
on `EnTT`.
|
||||
* [AGE (Arc Game Engine)](https://github.com/MohitSethi99/ArcGameEngine): an
|
||||
open-source engine for building 2D & 3D real-time rendering and interactive
|
||||
contents.
|
||||
* [Kengine](https://github.com/phisko/kengine): the _Koala engine_ is a game
|
||||
engine entirely implemented as an entity-component-ystem.
|
||||
|
||||
## Articles, videos 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.
|
||||
@ -193,6 +227,12 @@ I hope this list can grow much more in the future:
|
||||
- ... And so on.
|
||||
[Check out](https://www.youtube.com/channel/UCQ-W1KE9EYfdxhL6S4twUNw) the
|
||||
_Game Engine Series_ by The Cherno for more videos.
|
||||
* [Warmonger Dynasty devlog series](https://david-delassus.medium.com/list/warmonger-dynasty-devlogs-f64b71f556de)
|
||||
by [linkdd](https://github.com/linkdd): an interesting walkthrough of
|
||||
developing a game (also) with EnTT.
|
||||
* [Use EnTT When You Need An ECS](https://www.codingwiththomas.com/blog/use-entt-when-you-need-an-ecs)
|
||||
by [Thomas](https://www.codingwiththomas.com/): I couldn't have said it
|
||||
better.
|
||||
* [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
|
||||
@ -219,7 +259,8 @@ I hope this list can grow much more in the future:
|
||||
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:
|
||||
## Any Other Business:
|
||||
|
||||
* [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
|
||||
@ -261,6 +302,3 @@ I hope this list can grow much more in the future:
|
||||
* GitHub contains also
|
||||
[many other examples](https://github.com/search?o=desc&q=%22skypjack%2Fentt%22&s=indexed&type=Code)
|
||||
of use of `EnTT` from which to take inspiration if interested.
|
||||
|
||||
If you know of other resources out there that are about `EnTT`, feel free to
|
||||
open an issue or a PR and I'll be glad to add them to this page.
|
||||
|
420
docs/md/meta.md
420
docs/md/meta.md
@ -67,17 +67,15 @@ recommended.
|
||||
|
||||
# Reflection in a nutshell
|
||||
|
||||
Reflection always starts from real types (users cannot reflect imaginary types
|
||||
and it would not make much sense, we wouldn't be talking about reflection
|
||||
anymore).<br/>
|
||||
To create a meta node, the library provides the `meta` function that accepts a
|
||||
type to reflect as a template parameter:
|
||||
Reflection always starts from actual C++ types. Users cannot reflect _imaginary_
|
||||
types.<br/>
|
||||
The `meta` function is where it all starts:
|
||||
|
||||
```cpp
|
||||
auto factory = entt::meta<my_type>();
|
||||
```
|
||||
|
||||
The returned value is a factory object to use to continue building the meta
|
||||
The returned value is a _factory object_ to use to continue building the meta
|
||||
type.
|
||||
|
||||
By default, a meta type is associated with the identifier returned by the
|
||||
@ -88,45 +86,42 @@ However, it's also possible to assign custom identifiers to meta types:
|
||||
auto factory = entt::meta<my_type>().type("reflected_type"_hs);
|
||||
```
|
||||
|
||||
Identifiers are important because users can retrieve meta types at runtime by
|
||||
searching for them by _name_ other than by type.<br/>
|
||||
On the other hand, there are cases in which users can be interested in adding
|
||||
features to a reflected type so that the reflection system can use it correctly
|
||||
under the hood, but they don't want to also make the type _searchable_. In this
|
||||
case, it's sufficient not to invoke `type`.
|
||||
Identifiers are used to _retrieve_ meta types at runtime by _name_ other than by
|
||||
type.<br/>
|
||||
However, users can be interested in adding features to a reflected type so that
|
||||
the reflection system can use it correctly under the hood, while they don't want
|
||||
to also make the type _searchable_. In this case, it's sufficient not to invoke
|
||||
`type`.
|
||||
|
||||
A factory is such that all its member functions return the factory itself or a
|
||||
decorated version of it. This object can be used to add the following:
|
||||
A factory is such that all its member functions return the factory itself. It's
|
||||
generally used to create the following:
|
||||
|
||||
* _Constructors_. Actual constructors can be assigned to a reflected type by
|
||||
specifying their list of arguments. Free functions (namely, factories) can be
|
||||
used as well, as long as the return type is the expected one. From a client's
|
||||
point of view, nothing changes if a constructor is a free function or an
|
||||
actual constructor.<br/>
|
||||
Use the `ctor` member function for this purpose:
|
||||
* _Constructors_. A constructors is assigned to a reflected type by specifying
|
||||
its _list of arguments_. Free functions are also accepted if the return type
|
||||
is the expected one. From a client perspective, nothing changes between a free
|
||||
function or an actual constructor:
|
||||
|
||||
```cpp
|
||||
entt::meta<my_type>().ctor<int, char>().ctor<&factory>();
|
||||
```
|
||||
|
||||
* _Destructors_. Free functions and member functions can be used as destructors
|
||||
of reflected types. The purpose is to give users the ability to free up
|
||||
resources that require special treatment before an object is actually
|
||||
destroyed.<br/>
|
||||
Use the `dtor` member function for this purpose:
|
||||
Meta default constructors are implicitly generated, if possible.
|
||||
|
||||
* _Destructors_. Both free functions and member functions are valid destructors:
|
||||
|
||||
```cpp
|
||||
entt::meta<my_type>().dtor<&destroy>();
|
||||
```
|
||||
|
||||
The purpose is to offer the possibility to free up resources that require
|
||||
_special treatment_ before an object is actually destroyed.<br/>
|
||||
A function should neither delete nor explicitly invoke the destructor of a
|
||||
given instance.
|
||||
|
||||
* _Data members_. Both real data members of the underlying type and static and
|
||||
global variables, as well as constants of any kind, can be attached to a meta
|
||||
type. From the point of view of the client, all the variables associated with
|
||||
the reflected type will appear as if they were part of the type itself.<br/>
|
||||
Use the `data` member function for this purpose:
|
||||
* _Data members_. Meta data members are actual data members of the underlying
|
||||
type but also static and global variables or constants of any kind. From the
|
||||
point of view of the client, all the variables associated with the reflected
|
||||
type appear as if they were part of the type itself:
|
||||
|
||||
```cpp
|
||||
entt::meta<my_type>()
|
||||
@ -135,13 +130,11 @@ decorated version of it. This object can be used to add the following:
|
||||
.data<&global_variable>("global"_hs);
|
||||
```
|
||||
|
||||
The function requires as an argument the identifier to give to the meta data
|
||||
once created. Users can then access meta data at runtime by searching for them
|
||||
by _name_.<br/>
|
||||
Data members can also be defined by means of a setter and getter pair. Setters
|
||||
and getters can be either free functions, class members or a mix of them, as
|
||||
long as they respect the required signatures. This approach is also convenient
|
||||
to create a read-only variable from a non-const data member:
|
||||
The `data` function requires the identifier to use for the meta data member.
|
||||
Users can then access it by _name_ at runtime.<br/>
|
||||
Data members are also defined by means of a setter and getter pair. These are
|
||||
either free functions, class members or a mix of them. This approach is also
|
||||
convenient to create read-only properties from a non-const data member:
|
||||
|
||||
```cpp
|
||||
entt::meta<my_type>().data<nullptr, &my_type::data_member>("member"_hs);
|
||||
@ -153,13 +146,10 @@ decorated version of it. This object can be used to add the following:
|
||||
entt::meta<my_type>().data<entt::value_list<&from_int, &from_string>, &my_type::data_member>("member"_hs);
|
||||
```
|
||||
|
||||
Refer to the inline documentation for all the details.
|
||||
|
||||
* _Member functions_. Both real member functions of the underlying type and free
|
||||
functions can be attached to a meta type. From the point of view of the
|
||||
client, all the functions associated with the reflected type will appear as if
|
||||
they were part of the type itself.<br/>
|
||||
Use the `func` member function for this purpose:
|
||||
* _Member functions_. Meta member functions are actual member functions of the
|
||||
underlying type but also plain free functions. From the point of view of the
|
||||
client, all the functions associated with the reflected type appear as if they
|
||||
were part of the type itself:
|
||||
|
||||
```cpp
|
||||
entt::meta<my_type>()
|
||||
@ -168,40 +158,31 @@ decorated version of it. This object can be used to add the following:
|
||||
.func<&free_function>("free"_hs);
|
||||
```
|
||||
|
||||
The function requires as an argument the identifier to give to the meta
|
||||
function once created. Users can then access meta functions at runtime by
|
||||
searching for them by _name_.<br/>
|
||||
The `func` function requires the identifier to use for the meta data function.
|
||||
Users can then access it by _name_ at runtime.<br/>
|
||||
Overloading of meta functions is supported. Overloaded functions are resolved
|
||||
at runtime by the reflection system according to the types of the arguments.
|
||||
|
||||
* _Base classes_. A base class is such that the underlying type is actually
|
||||
derived from it. In this case, the reflection system tracks the relationship
|
||||
and allows for implicit casts at runtime when required.<br/>
|
||||
Use the `base` member function for this purpose:
|
||||
derived from it:
|
||||
|
||||
```cpp
|
||||
entt::meta<derived_type>().base<base_type>();
|
||||
```
|
||||
|
||||
From now on, wherever a `base_type` is required, an instance of `derived_type`
|
||||
will also be accepted.
|
||||
The reflection system tracks the relationship and allows for implicit casts at
|
||||
runtime when required. In other terms, wherever a `base_type` is required, an
|
||||
instance of `derived_type` is also accepted.
|
||||
|
||||
* _Conversion functions_. Actual types can be converted, this is a fact. Just
|
||||
think of the relationship between a `double` and an `int` to see it. Similar
|
||||
to bases, conversion functions allow users to define conversions that will be
|
||||
implicitly performed by the reflection system when required.<br/>
|
||||
Use the `conv` member function for this purpose:
|
||||
* _Conversion functions_. Conversion functions allow users to define conversions
|
||||
that are implicitly performed by the reflection system when required:
|
||||
|
||||
```cpp
|
||||
entt::meta<double>().conv<int>();
|
||||
```
|
||||
|
||||
That's all, everything users need to create meta types and enjoy the reflection
|
||||
system. At first glance it may not seem that much, but users usually learn to
|
||||
appreciate it over time.<br/>
|
||||
Also, do not forget what these few lines hide under the hood: a built-in,
|
||||
non-intrusive and macro-free system for reflection in C++. Features that are
|
||||
definitely worth the price, at least for me.
|
||||
This is everything users need to create meta types. Refer to the inline
|
||||
documentation for further details.
|
||||
|
||||
## Any to the rescue
|
||||
|
||||
@ -214,13 +195,13 @@ The API is very similar to that of the `any` type. The class `meta_any` _wraps_
|
||||
many of the feature to infer a meta node, before forwarding some or all of the
|
||||
arguments to the underlying storage.<br/>
|
||||
Among the few relevant differences, `meta_any` adds support for containers and
|
||||
pointer-like types (see the following sections for more details), while `any`
|
||||
does not.<br/>
|
||||
Similar to `any`, this class can also be used to create _aliases_ for unmanaged
|
||||
pointer-like types, while `any` doesn't.<br/>
|
||||
Similar to `any`, this class is also used to create _aliases_ for unmanaged
|
||||
objects either with `forward_as_meta` or using the `std::in_place_type<T &>`
|
||||
disambiguation tag, as well as from an existing object by means of the `as_ref`
|
||||
member function. However, unlike `any`, `meta_any` treats an empty instance and
|
||||
one initialized with `void` differently:
|
||||
member function.<br/>
|
||||
Unlike `any` instead, `meta_any` treats an empty instance and one initialized
|
||||
with `void` differently:
|
||||
|
||||
```cpp
|
||||
entt::meta_any empty{};
|
||||
@ -229,21 +210,19 @@ entt::meta_any other{std::in_place_type<void>};
|
||||
|
||||
While `any` considers both as empty, `meta_any` treats objects initialized with
|
||||
`void` as if they were _valid_ ones. This allows to differentiate between failed
|
||||
function calls and function calls that are successful but return nothing.<br/>
|
||||
function calls and function calls that are successful but return nothing.
|
||||
|
||||
Finally, the member functions `try_cast`, `cast` and `allow_cast` are used to
|
||||
cast the underlying object to a given type (either a reference or a value type)
|
||||
or to _convert_ a `meta_any` in such a way that a cast becomes viable for the
|
||||
resulting object. There is in fact no `any_cast` equivalent for `meta_any`.
|
||||
resulting object.<br/>
|
||||
There is in fact no `any_cast` equivalent for `meta_any`.
|
||||
|
||||
## Enjoy the runtime
|
||||
|
||||
Once the web of reflected types has been constructed, it's a matter of using it
|
||||
at runtime where required.<br/>
|
||||
All this has the great merit that the reflection system stands in fact as a
|
||||
non-intrusive tool for the runtime, unlike the vast majority of the things
|
||||
offered by this library and closely linked to the compile-time.
|
||||
|
||||
To search for a reflected type there are a few options:
|
||||
Once the web of reflected types is constructed, it's a matter of using it at
|
||||
runtime where required.<br/>
|
||||
There are a few options to search for a reflected type:
|
||||
|
||||
```cpp
|
||||
// direct access to a reflected type
|
||||
@ -257,8 +236,8 @@ auto by_type_id = entt::resolve(entt::type_id<my_type>());
|
||||
```
|
||||
|
||||
There exists also an overload of the `resolve` function to use to iterate all
|
||||
the reflected types at once. It returns an iterable object that can be used in a
|
||||
range-for loop:
|
||||
reflected types at once. It returns an iterable object to be used in a range-for
|
||||
loop:
|
||||
|
||||
```cpp
|
||||
for(auto &&[id, type]: entt::resolve()) {
|
||||
@ -270,9 +249,7 @@ In all cases, the returned value is an instance of `meta_type` (possibly with
|
||||
its id). This kind of objects offer an API to know their _runtime identifiers_,
|
||||
to iterate all the meta objects associated with them and even to build instances
|
||||
of the underlying type.<br/>
|
||||
Refer to the inline documentation for all the details.
|
||||
|
||||
Meta data members and functions are accessed by name among the other things:
|
||||
Meta data members and functions are accessed by name:
|
||||
|
||||
* Meta data members:
|
||||
|
||||
@ -297,11 +274,11 @@ Meta data members and functions are accessed by name among the other things:
|
||||
A meta function object offers an API to query the underlying type (for
|
||||
example, to know if it's a const or a static function), to know the number of
|
||||
arguments, the meta return type and the meta types of the parameters. In
|
||||
addition, a meta function object can be used to invoke the underlying function
|
||||
and then get the return value in the form of a `meta_any` object.
|
||||
addition, a meta function object is used to invoke the underlying function and
|
||||
then get the return value in the form of a `meta_any` object.
|
||||
|
||||
All the meta objects thus obtained as well as the meta types can be explicitly
|
||||
converted to a boolean value to check if they are valid:
|
||||
All the meta objects thus obtained as well as the meta types explicitly convert
|
||||
to a boolean value to check for validity:
|
||||
|
||||
```cpp
|
||||
if(auto func = entt::resolve<my_type>().func("member"_hs); func) {
|
||||
@ -319,26 +296,23 @@ for(auto &&[id, type]: entt::resolve<my_type>().base()) {
|
||||
}
|
||||
```
|
||||
|
||||
A meta type can also be used to `construct` actual instances of the underlying
|
||||
Meta type are also used to `construct` actual instances of the underlying
|
||||
type.<br/>
|
||||
In particular, the `construct` member function accepts a variable number of
|
||||
arguments and searches for a match. It then returns a `meta_any` object that may
|
||||
or may not be initialized, depending on whether a suitable constructor has been
|
||||
found or not.
|
||||
or may not be initialized, depending on whether a suitable constructor was found
|
||||
or not.
|
||||
|
||||
There is no object that wraps the destructor of a meta type nor a `destroy`
|
||||
member function in its API. Destructors are invoked implicitly by `meta_any`
|
||||
behind the scenes and users have not to deal with them explicitly. Furthermore,
|
||||
they have no name, cannot be searched and wouldn't have member functions to
|
||||
expose anyway.<br/>
|
||||
Similarly, conversion functions aren't directly accessible. They are used
|
||||
they've no name, cannot be searched and wouldn't have member functions to expose
|
||||
anyway.<br/>
|
||||
Similarly, conversion functions aren't directly accessible. They're used
|
||||
internally by `meta_any` and the meta objects when needed.
|
||||
|
||||
Meta types and meta objects in general contain much more than what is said: a
|
||||
plethora of functions in addition to those listed whose purposes and uses go
|
||||
unfortunately beyond the scope of this document.<br/>
|
||||
I invite anyone interested in the subject to look at the code, experiment and
|
||||
read the inline documentation to get the best out of this powerful tool.
|
||||
Meta types and meta objects in general contain much more than what was said.
|
||||
Refer to the inline documentation for further details.
|
||||
|
||||
## Container support
|
||||
|
||||
@ -349,7 +323,7 @@ meta system in many cases.
|
||||
|
||||
To make a container be recognized as such by the meta system, users are required
|
||||
to provide specializations for either the `meta_sequence_container_traits` class
|
||||
or the `meta_associative_container_traits` class, according to the actual type
|
||||
or the `meta_associative_container_traits` class, according to the actual _type_
|
||||
of the container.<br/>
|
||||
`EnTT` already exports the specializations for some common classes. In
|
||||
particular:
|
||||
@ -386,11 +360,10 @@ if(any.type().is_sequence_container()) {
|
||||
|
||||
The method to use to get a proxy object for associative containers is
|
||||
`as_associative_container` instead.<br/>
|
||||
It goes without saying that it's not necessary to perform a double check.
|
||||
Instead, it's sufficient to query the meta type or verify that the proxy object
|
||||
is valid. In fact, proxies are contextually convertible to bool to know if they
|
||||
are valid. For example, invalid proxies are returned when the wrapped object
|
||||
isn't a container.<br/>
|
||||
It's not necessary to perform a double check actually. Instead, it's enough to
|
||||
query the meta type or verify that the proxy object is valid. In fact, proxies
|
||||
are contextually convertible to bool to check for validity. For example, invalid
|
||||
proxies are returned when the wrapped object isn't a container.<br/>
|
||||
In all cases, users aren't expected to _reflect_ containers explicitly. It's
|
||||
sufficient to assign a container for which a specialization of the traits
|
||||
classes exists to a `meta_any` object to be able to get its proxy object.
|
||||
@ -402,32 +375,18 @@ to case. In particular:
|
||||
* The `value_type` member function returns the meta type of the elements.
|
||||
|
||||
* The `size` member function returns the number of elements in the container as
|
||||
an unsigned integer value:
|
||||
|
||||
```cpp
|
||||
const auto size = view.size();
|
||||
```
|
||||
an unsigned integer value.
|
||||
|
||||
* The `resize` member function allows to resize the wrapped container and
|
||||
returns true in case of success:
|
||||
|
||||
```cpp
|
||||
const bool ok = view.resize(3u);
|
||||
```
|
||||
|
||||
returns true in case of success.<br/>
|
||||
For example, it's not possible to resize fixed size containers.
|
||||
|
||||
* The `clear` member function allows to clear the wrapped container and returns
|
||||
true in case of success:
|
||||
|
||||
```cpp
|
||||
const bool ok = view.clear();
|
||||
```
|
||||
|
||||
true in case of success.<br/>
|
||||
For example, it's not possible to clear fixed size containers.
|
||||
|
||||
* The `begin` and `end` member functions return opaque iterators that can be
|
||||
used to iterate the container directly:
|
||||
* The `begin` and `end` member functions return opaque iterators that is used to
|
||||
iterate the container directly:
|
||||
|
||||
```cpp
|
||||
for(entt::meta_any element: view) {
|
||||
@ -441,7 +400,7 @@ to case. In particular:
|
||||
All meta iterators are input iterators and don't offer an indirection operator
|
||||
on purpose.
|
||||
|
||||
* The `insert` member function can be used to add elements to the container. It
|
||||
* The `insert` member function is used to add elements to the container. It
|
||||
accepts a meta iterator and the element to insert:
|
||||
|
||||
```cpp
|
||||
@ -451,15 +410,15 @@ to case. In particular:
|
||||
```
|
||||
|
||||
This function returns a meta iterator pointing to the inserted element and a
|
||||
boolean value to indicate whether the operation was successful or not. Note
|
||||
that a call to `insert` may silently fail in case of fixed size containers or
|
||||
whether the arguments aren't at least convertible to the required types.<br/>
|
||||
Since the meta iterators are contextually convertible to bool, users can rely
|
||||
on them to know if the operation has failed on the actual container or
|
||||
upstream, for example for an argument conversion problem.
|
||||
boolean value to indicate whether the operation was successful or not. A call
|
||||
to `insert` may silently fail in case of fixed size containers or whether the
|
||||
arguments aren't at least convertible to the required types.<br/>
|
||||
Since meta iterators are contextually convertible to bool, users can rely on
|
||||
them to know if the operation failed on the actual container or upstream, for
|
||||
example due to an argument conversion problem.
|
||||
|
||||
* The `erase` member function can be used to remove elements from the container.
|
||||
It accepts a meta iterator to the element to remove:
|
||||
* The `erase` member function is used to remove elements from the container. It
|
||||
accepts a meta iterator to the element to remove:
|
||||
|
||||
```cpp
|
||||
auto first = view.begin();
|
||||
@ -468,11 +427,11 @@ to case. In particular:
|
||||
```
|
||||
|
||||
This function returns a meta iterator following the last removed element and a
|
||||
boolean value to indicate whether the operation was successful or not. Note
|
||||
that a call to `erase` may silently fail in case of fixed size containers.
|
||||
boolean value to indicate whether the operation was successful or not. A call
|
||||
to `erase` may silently fail in case of fixed size containers.
|
||||
|
||||
* The `operator[]` can be used to access elements in a container. It accepts a
|
||||
single argument, that is the position of the element to return:
|
||||
* The `operator[]` is used to access container elements. It accepts a single
|
||||
argument, the position of the element to return:
|
||||
|
||||
```cpp
|
||||
for(std::size_t pos{}, last = view.size(); pos < last; ++pos) {
|
||||
@ -482,8 +441,8 @@ to case. In particular:
|
||||
```
|
||||
|
||||
The function returns instances of `meta_any` that directly refer to the actual
|
||||
elements. Modifying the returned object will then directly modify the element
|
||||
inside the container.<br/>
|
||||
elements. Modifying the returned object directly modifies the element inside
|
||||
the container.<br/>
|
||||
Depending on the underlying sequence container, this operation may not be as
|
||||
efficient. For example, in the case of an `std::list`, a positional access
|
||||
translates to a linear visit of the list itself (probably not what the user
|
||||
@ -508,21 +467,13 @@ differences in behavior in the case of key-only containers. In particular:
|
||||
`std::map<int, char>`.
|
||||
|
||||
* The `size` member function returns the number of elements in the container as
|
||||
an unsigned integer value:
|
||||
|
||||
```cpp
|
||||
const auto size = view.size();
|
||||
```
|
||||
an unsigned integer value.
|
||||
|
||||
* The `clear` member function allows to clear the wrapped container and returns
|
||||
true in case of success:
|
||||
true in case of success.
|
||||
|
||||
```cpp
|
||||
const bool ok = view.clear();
|
||||
```
|
||||
|
||||
* The `begin` and `end` member functions return opaque iterators that can be
|
||||
used to iterate the container directly:
|
||||
* The `begin` and `end` member functions return opaque iterators that are used
|
||||
to iterate the container directly:
|
||||
|
||||
```cpp
|
||||
for(std::pair<entt::meta_any, entt::meta_any> element: view) {
|
||||
@ -539,11 +490,11 @@ differences in behavior in the case of key-only containers. In particular:
|
||||
|
||||
While the accessed key is usually constant in the associative containers and
|
||||
is therefore returned by copy, the value (if any) is wrapped by an instance of
|
||||
`meta_any` that directly refers to the actual element. Modifying it will then
|
||||
directly modify the element inside the container.
|
||||
`meta_any` that directly refers to the actual element. Modifying it directly
|
||||
modifies the element inside the container.
|
||||
|
||||
* The `insert` member function can be used to add elements to the container. It
|
||||
accepts two arguments, respectively the key and the value to be inserted:
|
||||
* The `insert` member function is used to add elements to a container. It gets
|
||||
two arguments, respectively the key and the value to insert:
|
||||
|
||||
```cpp
|
||||
auto last = view.end();
|
||||
@ -552,39 +503,39 @@ differences in behavior in the case of key-only containers. In particular:
|
||||
```
|
||||
|
||||
This function returns a boolean value to indicate whether the operation was
|
||||
successful or not. Note that a call to `insert` may fail when the arguments
|
||||
aren't at least convertible to the required types.
|
||||
successful or not. A call to `insert` may fail when the arguments aren't at
|
||||
least convertible to the required types.
|
||||
|
||||
* The `erase` member function can be used to remove elements from the container.
|
||||
It accepts a single argument, that is the key to be removed:
|
||||
* The `erase` member function is used to remove elements from a container. It
|
||||
gets a single argument, the key to remove:
|
||||
|
||||
```cpp
|
||||
view.erase(42);
|
||||
```
|
||||
|
||||
This function returns a boolean value to indicate whether the operation was
|
||||
successful or not. Note that a call to `erase` may fail when the argument
|
||||
isn't at least convertible to the required type.
|
||||
successful or not. A call to `erase` may fail when the argument isn't at least
|
||||
convertible to the required type.
|
||||
|
||||
* The `operator[]` can be used to access elements in a container. It accepts a
|
||||
single argument, that is the key of the element to return:
|
||||
* The `operator[]` is used to access elements in a container. It gets a single
|
||||
argument, the key of the element to return:
|
||||
|
||||
```cpp
|
||||
entt::meta_any value = view[42];
|
||||
```
|
||||
|
||||
The function returns instances of `meta_any` that directly refer to the actual
|
||||
elements. Modifying the returned object will then directly modify the element
|
||||
inside the container.
|
||||
elements. Modifying the returned object directly modifies the element inside
|
||||
the container.
|
||||
|
||||
Container support is minimal but likely sufficient to satisfy all needs.
|
||||
|
||||
## Pointer-like types
|
||||
|
||||
As with containers, it's also possible to communicate to the meta system which
|
||||
types to consider _pointers_. This will allow to dereference instances of
|
||||
`meta_any`, thus obtaining light _references_ to the pointed objects that are
|
||||
also correctly associated with their meta types.<br/>
|
||||
As with containers, it's also possible to _tell_ to the meta system which types
|
||||
are _pointers_. This makes it possible to dereference instances of `meta_any`,
|
||||
thus obtaining light _references_ to pointed objects that are also correctly
|
||||
associated with their meta types.<br/>
|
||||
To make the meta system recognize a type as _pointer-like_, users can specialize
|
||||
the `is_meta_pointer_like` class. `EnTT` already exports the specializations for
|
||||
some common classes. In particular:
|
||||
@ -614,13 +565,12 @@ if(any.type().is_pointer_like()) {
|
||||
}
|
||||
```
|
||||
|
||||
Of course, it's not necessary to perform a double check. Instead, it's enough to
|
||||
query the meta type or verify that the returned object is valid. For example,
|
||||
invalid instances are returned when the wrapped object isn't a pointer-like
|
||||
type.<br/>
|
||||
Note that dereferencing a pointer-like object returns an instance of `meta_any`
|
||||
which refers to the pointed object and allows users to modify it directly
|
||||
(unless the returned element is const, of course).
|
||||
It's not necessary to perform a double check. Instead, it's enough to query the
|
||||
meta type or verify that the returned object is valid. For example, invalid
|
||||
instances are returned when the wrapped object isn't a pointer-like type.<br/>
|
||||
Dereferencing a pointer-like object returns an instance of `meta_any` which
|
||||
_refers_ to the pointed object. Modifying it means modifying the pointed object
|
||||
directly (unless the returned element is const).
|
||||
|
||||
In general, _dereferencing_ a pointer-like type boils down to a `*ptr`. However,
|
||||
`EnTT` also supports classes that don't offer an `operator*`. In particular:
|
||||
@ -648,12 +598,12 @@ In general, _dereferencing_ a pointer-like type boils down to a `*ptr`. However,
|
||||
};
|
||||
```
|
||||
|
||||
In all other cases, that is, when dereferencing a pointer works as expected and
|
||||
regardless of the pointed type, no user intervention is required.
|
||||
In all other cases and when dereferencing a pointer works as expected regardless
|
||||
of the pointed type, no user intervention is required.
|
||||
|
||||
## Template information
|
||||
|
||||
Meta types also provide a minimal set of information about the nature of the
|
||||
Meta types also provide a minimal set of information about the _nature_ of the
|
||||
original type in case it's a class template.<br/>
|
||||
By default, this works out of the box and requires no user action. However, it's
|
||||
important to include the header file `template.hpp` to make this information
|
||||
@ -688,9 +638,9 @@ template<typename Ret, typename... Args>
|
||||
struct function_type<Ret(Args...)> {};
|
||||
```
|
||||
|
||||
In this case, rather than the function type, the user might want the return type
|
||||
and unpacked arguments as if they were different template parameters for the
|
||||
original class template.<br/>
|
||||
In this case, rather than the function type, it might be useful to provide the
|
||||
return type and unpacked arguments as if they were different template parameters
|
||||
for the original class template.<br/>
|
||||
To achieve this, users must enter the library internals and provide their own
|
||||
specialization for the class template `entt::meta_template_traits`, such as:
|
||||
|
||||
@ -704,8 +654,8 @@ struct entt::meta_template_traits<function_type<Ret(Args...)>> {
|
||||
|
||||
The reflection system doesn't verify the accuracy of the information nor infer a
|
||||
correspondence between real types and meta types.<br/>
|
||||
Therefore, the specialization will be used as is and the information it contains
|
||||
will be associated with the appropriate type when required.
|
||||
Therefore, the specialization is used as is and the information it contains is
|
||||
associated with the appropriate type when required.
|
||||
|
||||
## Automatic conversions
|
||||
|
||||
@ -752,29 +702,29 @@ any.allow_cast(type);
|
||||
int value = any.cast<int>();
|
||||
```
|
||||
|
||||
This should make working with arithmetic types and scoped or unscoped enums as
|
||||
easy as it is in C++.<br/>
|
||||
It's also worth noting that it's still possible to set up conversion functions
|
||||
manually and these will always be preferred over the automatic ones.
|
||||
This makes working with arithmetic types and scoped or unscoped enums as easy as
|
||||
it is in C++.<br/>
|
||||
It's still possible to set up conversion functions manually and these are always
|
||||
preferred over the automatic ones.
|
||||
|
||||
## Implicitly generated default constructor
|
||||
|
||||
In many cases, it's useful to be able to create objects of default constructible
|
||||
types through the reflection system, while not having to explicitly register the
|
||||
meta type or the default constructor.<br/>
|
||||
Creating objects of default constructible types through the reflection system
|
||||
while not having to explicitly register the meta type or its default constructor
|
||||
is also possible.<br/>
|
||||
For example, in the case of primitive types like `int` or `char`, but not just
|
||||
them.
|
||||
|
||||
For this reason and only for default constructible types, default constructors
|
||||
are automatically defined and associated with their meta types, whether they are
|
||||
explicitly or implicitly generated.<br/>
|
||||
For default constructible types only, default constructors are automatically
|
||||
defined and associated with their meta types, whether they are explicitly or
|
||||
implicitly generated.<br/>
|
||||
Therefore, this is all is needed to construct an integer from its meta type:
|
||||
|
||||
```cpp
|
||||
entt::resolve<int>().construct();
|
||||
```
|
||||
|
||||
Where the meta type can be for example the one returned from a meta container,
|
||||
Where the meta type is for example the one returned from a meta container,
|
||||
useful for building keys without knowing or having to register the actual types.
|
||||
|
||||
In all cases, when users register default constructors, they are preferred both
|
||||
@ -783,8 +733,8 @@ during searches and when the `construct` member function is invoked.
|
||||
## From void to any
|
||||
|
||||
Sometimes all a user has is an opaque pointer to an object of a known meta type.
|
||||
It would be handy in this case to be able to construct a `meta_any` object from
|
||||
them.<br/>
|
||||
It would be handy in this case to be able to construct a `meta_any` element from
|
||||
it.<br/>
|
||||
For this purpose, the `meta_type` class offers a `from_void` member function
|
||||
designed to convert an opaque pointer into a `meta_any`:
|
||||
|
||||
@ -792,9 +742,8 @@ designed to convert an opaque pointer into a `meta_any`:
|
||||
entt::meta_any any = entt::resolve(id).from_void(element);
|
||||
```
|
||||
|
||||
It goes without saying that it's not possible to do a check on the actual type.
|
||||
Therefore, this call can be considered as a _static cast_ with all the problems
|
||||
and undefined behaviors of the case following errors.<br/>
|
||||
Unfortunately, it's not possible to do a check on the actual type. Therefore,
|
||||
this call can be considered as a _static cast_ with all its _problems_.<br/>
|
||||
On the other hand, the ability to construct a `meta_any` from an opaque pointer
|
||||
opens the door to some pretty interesting uses that are worth exploring.
|
||||
|
||||
@ -826,17 +775,17 @@ There are a few alternatives available at the moment:
|
||||
entt::meta<my_type>().func<&my_type::member_function, entt::as_void_t>("member"_hs);
|
||||
```
|
||||
|
||||
If the use with functions is obvious, it must be said that it's also possible
|
||||
to use this policy with constructors and data members. In the first case, the
|
||||
constructor will be invoked but the returned wrapper will actually be empty.
|
||||
In the second case, instead, the property will not be accessible for reading.
|
||||
If the use with functions is obvious, perhaps less so is use with constructors
|
||||
and data members. In the first case, the returned wrapper is always empty even
|
||||
though the constructor is still invoked. In the second case, the property
|
||||
isn't accessible for reading instead.
|
||||
|
||||
* The _as-ref_ and _as-cref_ policies, associated with the types
|
||||
`entt::as_ref_t` and `entt::as_cref_t`.<br/>
|
||||
They allow to build wrappers that act as references to unmanaged objects.
|
||||
Accessing the object contained in the wrapper for which the _reference_ was
|
||||
requested will make it possible to directly access the instance used to
|
||||
initialize the wrapper itself:
|
||||
requested makes it possible to directly access the instance used to initialize
|
||||
the wrapper itself:
|
||||
|
||||
```cpp
|
||||
entt::meta<my_type>().data<&my_type::data_member, entt::as_ref_t>("member"_hs);
|
||||
@ -854,21 +803,16 @@ obvious corner cases that can in turn be solved with the use of policies.
|
||||
|
||||
## Named constants and enums
|
||||
|
||||
A special mention should be made for constant values and enums. It wouldn't be
|
||||
necessary, but it will help distracted readers.
|
||||
|
||||
As mentioned, the `data` member function can be used to reflect constants of any
|
||||
type among the other things.<br/>
|
||||
This allows users to create meta types for enums that will work exactly like any
|
||||
other meta type built from a class. Similarly, arithmetic types can be enriched
|
||||
As mentioned, the `data` member function is used to reflect constants of any
|
||||
type.<br/>
|
||||
This allows users to create meta types for enums that work exactly like any
|
||||
other meta type built from a class. Similarly, arithmetic types are _enriched_
|
||||
with constants of special meaning where required.<br/>
|
||||
Personally, I find it very useful not to export what is the difference between
|
||||
enums and classes in C++ directly in the space of the reflected types.
|
||||
All values thus exported appear to users as if they were constant data members
|
||||
of the reflected types. This avoids the need to _export_ what is the difference
|
||||
between enums and classes in C++ directly in the space of the reflected types.
|
||||
|
||||
All the values thus exported will appear to users as if they were constant data
|
||||
members of the reflected types.
|
||||
|
||||
Exporting constant values or elements from an enum is as simple as ever:
|
||||
Exposing constant values or elements from an enum is quite simple:
|
||||
|
||||
```cpp
|
||||
entt::meta<my_enum>()
|
||||
@ -878,28 +822,22 @@ entt::meta<my_enum>()
|
||||
entt::meta<int>().data<2048>("max_int"_hs);
|
||||
```
|
||||
|
||||
It goes without saying that accessing them is trivial as well. It's a matter of
|
||||
doing the following, as with any other data member of a meta type:
|
||||
Accessing them is trivial as well. It's a matter of doing the following, as with
|
||||
any other data member of a meta type:
|
||||
|
||||
```cpp
|
||||
auto value = entt::resolve<my_enum>().data("a_value"_hs).get({}).cast<my_enum>();
|
||||
auto max = entt::resolve<int>().data("max_int"_hs).get({}).cast<int>();
|
||||
```
|
||||
|
||||
As a side note, remember that all this happens behind the scenes without any
|
||||
allocation because of the small object optimization performed by the `meta_any`
|
||||
class.
|
||||
All this happens behind the scenes without any allocation because of the small
|
||||
object optimization performed by the `meta_any` class.
|
||||
|
||||
## Properties and meta objects
|
||||
|
||||
Sometimes (for example, when it comes to creating an editor) it might be useful
|
||||
to attach properties to the meta objects created. Fortunately, this is possible
|
||||
for most of them.<br/>
|
||||
For the meta objects that support properties, the member functions of the
|
||||
factory used for registering them will return an extended version of the factory
|
||||
itself. The latter can be used to attach properties to the last created meta
|
||||
object.<br/>
|
||||
Apparently, it's more difficult to say than to do:
|
||||
for most of them:
|
||||
|
||||
```cpp
|
||||
entt::meta<my_type>().type("reflected_type"_hs).prop("tooltip"_hs, "message");
|
||||
@ -914,10 +852,10 @@ Key only properties are also supported out of the box:
|
||||
entt::meta<my_type>().type("reflected_type"_hs).prop(my_enum::key_only);
|
||||
```
|
||||
|
||||
To attach multiple properties to a meta object, it's possible to invoke `prop`
|
||||
more than once.<br/>
|
||||
It's also possible to invoke `prop` at different times, as long as the factory
|
||||
is reset to the meta object of interest.
|
||||
To attach multiple properties to a meta object, just invoke `prop` more than
|
||||
once.<br/>
|
||||
It's also possible to call `prop` at different times, as long as the factory is
|
||||
reset to the meta object of interest.
|
||||
|
||||
The meta objects for which properties are supported are currently meta types,
|
||||
meta data and meta functions.<br/>
|
||||
@ -940,7 +878,7 @@ form of a `meta_any` object.
|
||||
|
||||
## Unregister types
|
||||
|
||||
A type registered with the reflection system can also be unregistered. This
|
||||
A type registered with the reflection system can also be _unregistered_. This
|
||||
means unregistering all its data members, member functions, conversion functions
|
||||
and so on. However, base classes aren't unregistered as well, since they don't
|
||||
necessarily depend on it.<br/>
|
||||
@ -969,7 +907,7 @@ A type can be re-registered later with a completely different name and form.
|
||||
## Meta context
|
||||
|
||||
All meta types and their parts are created at runtime and stored in a default
|
||||
_context_. This can be reached via a service locator as:
|
||||
_context_. This is obtained via a service locator as:
|
||||
|
||||
```cpp
|
||||
auto &&context = entt::locator<entt::meta_context>::value_or();
|
||||
@ -984,8 +922,8 @@ auto &&context = entt::locator<entt::meta_context>::value_or();
|
||||
std::swap(context, other);
|
||||
```
|
||||
|
||||
This can be useful for testing purposes or to define multiple contexts with
|
||||
different meta objects to be used as appropriate.
|
||||
This is useful for testing purposes or to define multiple context objects with
|
||||
different meta type to use as appropriate.
|
||||
|
||||
If _replacing_ the default context isn't enough, `EnTT` also offers the ability
|
||||
to use multiple and externally managed contexts with the runtime reflection
|
||||
@ -998,16 +936,16 @@ entt::meta_ctx context{};
|
||||
auto factory = entt::meta<my_type>(context).type("reflected_type"_hs);
|
||||
```
|
||||
|
||||
By doing so, the new meta type won't be available in the default context but
|
||||
will be usable by passing around the new context when needed, such as when
|
||||
creating a new `meta_any` object:
|
||||
By doing so, the new meta type isn't available in the default context but is
|
||||
usable by passing around the new context when needed, such as when creating a
|
||||
new `meta_any` object:
|
||||
|
||||
```cpp
|
||||
entt::meta_any any{context, std::in_place_type<my_type>};
|
||||
```
|
||||
|
||||
Similarly, to search for meta types in a context other than the default one, it
|
||||
will be necessary to pass it to the `resolve` function:
|
||||
Similarly, to search for meta types in a context other than the default one,
|
||||
it's necessary to pass it to the `resolve` function:
|
||||
|
||||
```cpp
|
||||
entt::meta_type type = entt::resolve(context, "reflected_type"_hs)
|
||||
|
@ -26,17 +26,16 @@ 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
|
||||
Among others, this is 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.
|
||||
The result is an object to pass around as such and not through a reference or a
|
||||
pointer, as it 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/>
|
||||
supports most of its feature. For example, 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.
|
||||
@ -44,7 +43,7 @@ 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:
|
||||
The ones that I like more are:
|
||||
|
||||
* [`dyno`](https://github.com/ldionne/dyno): runtime polymorphism done right.
|
||||
* [`Poly`](https://github.com/facebook/folly/blob/master/folly/docs/Poly.md):
|
||||
@ -69,18 +68,18 @@ 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
|
||||
is convenient and allows users to write less code in most cases, it 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/>
|
||||
Once the interface is defined, a generic implementation is needed to fulfill the
|
||||
concept itself.<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:
|
||||
This is how a concept with a deduced interface is defined:
|
||||
|
||||
```cpp
|
||||
struct Drawable: entt::type_list<> {
|
||||
@ -108,12 +107,12 @@ struct Drawable: entt::type_list<> {
|
||||
};
|
||||
```
|
||||
|
||||
In this case, all parameters must be passed to `invoke` after the reference to
|
||||
In this case, all parameters are 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
|
||||
the language. However, there also exists an alternative that goes through an
|
||||
external call:
|
||||
|
||||
```cpp
|
||||
@ -165,12 +164,12 @@ struct Drawable: entt::type_list<bool(int) const> {
|
||||
|
||||
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.
|
||||
In fact, this is 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:
|
||||
`void()`, a concept is satisfied:
|
||||
|
||||
* Either by a class that exposes a member function with the same name and the
|
||||
same signature.
|
||||
@ -179,7 +178,7 @@ If the concept exposes a member function called `draw` with function type
|
||||
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/>
|
||||
interface, even if they're part of 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.
|
||||
@ -200,8 +199,8 @@ struct Drawable: entt::type_list<> {
|
||||
};
|
||||
```
|
||||
|
||||
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/>
|
||||
In this case, it's stated that the `draw` method of a generic type is enough to
|
||||
satisfy the requirements of the `Drawable` concept.<br/>
|
||||
Both member functions and free functions are supported to fulfill concepts:
|
||||
|
||||
```cpp
|
||||
@ -251,15 +250,15 @@ struct DrawableAndErasable: entt::type_list<> {
|
||||
```
|
||||
|
||||
The static virtual table is empty and must remain so.<br/>
|
||||
On the other hand, `type` no longer inherits from `Base` and instead forwards
|
||||
On the other hand, `type` no longer inherits from `Base`. Instead, it 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/>
|
||||
_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/>
|
||||
As for a defined concept instead, the list of types is _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:
|
||||
|
||||
@ -268,8 +267,8 @@ 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:
|
||||
The definition isn't strictly required, since the function is only used through
|
||||
a `decltype` as it follows:
|
||||
|
||||
```cpp
|
||||
struct DrawableAndErasable: entt::type_list_cat_t<
|
||||
@ -286,9 +285,8 @@ 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:
|
||||
Once the _concept_ and implementation are defined, it's possible to use the
|
||||
`poly` class template to _wrap_ instances that meet the requirements:
|
||||
|
||||
```cpp
|
||||
using drawable = entt::poly<Drawable>;
|
||||
@ -310,9 +308,9 @@ 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/>
|
||||
This class offers a wide range of constructors, from the default one (which
|
||||
returns 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):
|
||||
|
||||
@ -329,14 +327,14 @@ 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.
|
||||
doesn'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.
|
||||
Therefore, where `instance.data()` invokes the `data` member function of the
|
||||
poly object, `instance->data()` maps directly to the functionality exposed by
|
||||
the underlying concept.
|
||||
|
||||
# Storage size and alignment requirement
|
||||
|
||||
@ -351,9 +349,9 @@ 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/>
|
||||
an integer. The alignment requirement is optional 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.
|
||||
|
@ -15,18 +15,17 @@
|
||||
|
||||
# Introduction
|
||||
|
||||
Sometimes processes are a useful tool to work around the strict definition of a
|
||||
system and introduce logic in a different way, usually without resorting to the
|
||||
introduction of other components.
|
||||
|
||||
`EnTT` offers a minimal support to this paradigm by introducing a few classes
|
||||
that users can use to define and execute cooperative processes.
|
||||
Processes are a useful tool to work around the strict definition of a system and
|
||||
introduce logic in a different way, usually without resorting to other component
|
||||
types.<br/>
|
||||
`EnTT` offers minimal support to this paradigm by introducing a few classes used
|
||||
to define and execute cooperative processes.
|
||||
|
||||
# The process
|
||||
|
||||
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 typical task inherits from the `process` class template that stays true to the
|
||||
CRTP idiom. Moreover, derived classes specify what the intended type for elapsed
|
||||
times is.
|
||||
|
||||
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
|
||||
@ -34,39 +33,38 @@ to _override_ the default behavior):
|
||||
|
||||
* `void update(Delta, void *);`
|
||||
|
||||
It's invoked once per tick until a process is explicitly aborted or it
|
||||
terminates either with or without errors. Even though it's not mandatory to
|
||||
declare this member function, as a rule of thumb each process should at
|
||||
least define it to work properly. The `void *` parameter is an opaque pointer
|
||||
to user data (if any) forwarded directly to the process during an update.
|
||||
This is invoked once per tick until a process is explicitly aborted or ends
|
||||
either with or without errors. Even though it's not mandatory to declare this
|
||||
member function, as a rule of thumb each process should at least define it to
|
||||
work _properly_. The `void *` parameter is an opaque pointer to user data (if
|
||||
any) forwarded directly to the process during an update.
|
||||
|
||||
* `void init();`
|
||||
|
||||
It's invoked when the process joins the running queue of a scheduler. This
|
||||
happens as soon as it's attached to the scheduler if the process is a top
|
||||
level one, otherwise when it replaces its parent if the process is a
|
||||
continuation.
|
||||
This is invoked when the process joins the running queue of a scheduler. It
|
||||
happens usually as soon as the process is attached to the scheduler if it's a
|
||||
top level one, otherwise when it replaces its parent if it's a _continuation_.
|
||||
|
||||
* `void succeeded();`
|
||||
|
||||
It's invoked in case of success, immediately after an update and during the
|
||||
This is invoked in case of success, immediately after an update and during the
|
||||
same tick.
|
||||
|
||||
* `void failed();`
|
||||
|
||||
It's invoked in case of errors, immediately after an update and during the
|
||||
This is invoked in case of errors, immediately after an update and during the
|
||||
same tick.
|
||||
|
||||
* `void aborted();`
|
||||
|
||||
It's invoked only if a process is explicitly aborted. There is no guarantee
|
||||
that it executes in the same tick, this depends solely on whether the
|
||||
process is aborted immediately or not.
|
||||
This is invoked only if a process is explicitly aborted. There is no guarantee
|
||||
that it executes in the same tick, it depends solely on whether the process is
|
||||
aborted immediately or not.
|
||||
|
||||
Derived classes can also change the internal state of a process by invoking
|
||||
`succeed` and `fail`, as well as `pause` and `unpause` the process itself. All
|
||||
these are protected member functions made available to be able to manage the
|
||||
life cycle of a process from a derived class.
|
||||
`succeed` and `fail`, as well as `pause` and `unpause` the process itself.<br/>
|
||||
All these are protected member functions made available to manage the life cycle
|
||||
of a process from a derived class.
|
||||
|
||||
Here is a minimal example for the sake of curiosity:
|
||||
|
||||
@ -95,14 +93,14 @@ private:
|
||||
|
||||
## Adaptor
|
||||
|
||||
Lambdas and functors can't be used directly with a scheduler for they are not
|
||||
Lambdas and functors can't be used directly with a scheduler because they aren't
|
||||
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.
|
||||
|
||||
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
|
||||
call whenever a process is terminated with success or with an error:
|
||||
function of a process but for the fact that it receives two extra callbacks to
|
||||
invoke whenever a process terminates with success or with an error:
|
||||
|
||||
```cpp
|
||||
void(Delta delta, void *data, auto succeed, auto fail);
|
||||
@ -127,9 +125,9 @@ A cooperative scheduler runs different processes and helps managing their life
|
||||
cycles.
|
||||
|
||||
Each process is invoked once per tick. If it terminates, it's removed
|
||||
automatically from the scheduler and it's never invoked again. Otherwise it's
|
||||
automatically from the scheduler and it's never invoked again. Otherwise, it's
|
||||
a good candidate to run one more time the next tick.<br/>
|
||||
A process can also have a child. In this case, the parent process is replaced
|
||||
A process can also have a _child_. In this case, the parent process is replaced
|
||||
with its child when it terminates and only if it returns with success. In case
|
||||
of errors, both the parent process and its child are discarded. This way, it's
|
||||
easy to create chain of processes to run sequentially.
|
||||
@ -138,18 +136,25 @@ Using a scheduler is straightforward. To create it, users must provide only the
|
||||
type for the elapsed times and no arguments at all:
|
||||
|
||||
```cpp
|
||||
entt::scheduler<std::uint32_t> scheduler;
|
||||
entt::basic_scheduler<std::uint64_t> scheduler;
|
||||
```
|
||||
|
||||
It has member functions to query its internal data structures, like `empty` or
|
||||
`size`, as well as a `clear` utility to reset it to a clean state:
|
||||
Otherwise, the `scheduler` alias is also available for the most common cases. It
|
||||
uses `std::uint32_t` as a default type:
|
||||
|
||||
```cpp
|
||||
entt::scheduler scheduler;
|
||||
```
|
||||
|
||||
The class has member functions to query its internal data structures, like
|
||||
`empty` or `size`, as well as a `clear` utility to reset it to a clean state:
|
||||
|
||||
```cpp
|
||||
// checks if there are processes still running
|
||||
const auto empty = scheduler.empty();
|
||||
|
||||
// gets the number of processes still running
|
||||
entt::scheduler<std::uint32_t>::size_type size = scheduler.size();
|
||||
entt::scheduler::size_type size = scheduler.size();
|
||||
|
||||
// resets the scheduler to its initial state and discards all the processes
|
||||
scheduler.clear();
|
||||
@ -173,7 +178,7 @@ To attach a process to a scheduler there are mainly two ways:
|
||||
```
|
||||
|
||||
In both cases, the return value is an opaque object that offers a `then` member
|
||||
function to use to create chains of processes to run sequentially.<br/>
|
||||
function used to create chains of processes to run sequentially.<br/>
|
||||
As a minimal example of use:
|
||||
|
||||
```cpp
|
||||
@ -201,7 +206,7 @@ scheduler.update(delta, &data);
|
||||
```
|
||||
|
||||
In addition to these functions, the scheduler offers an `abort` member function
|
||||
that can be used to discard all the running processes at once:
|
||||
that is used to discard all the running processes at once:
|
||||
|
||||
```cpp
|
||||
// aborts all the processes abruptly ...
|
||||
|
@ -1,18 +1,35 @@
|
||||
# Similar projects
|
||||
|
||||
<!--
|
||||
@cond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
# Table of Contents
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Similar projects](#similar-projects)
|
||||
<!--
|
||||
@endcond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
|
||||
# Introduction
|
||||
|
||||
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 you know of other similar projects out there, feel free to open an issue or a
|
||||
PR and I'll be glad to add them to this page.<br/>
|
||||
I hope the following lists can grow much more in the future.
|
||||
|
||||
# Similar projects
|
||||
|
||||
Below an incomplete list of similar projects 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.
|
||||
@ -34,6 +51,8 @@ I hope this list can grow much more in the future:
|
||||
solution between an ECS and dynamic mixins.
|
||||
|
||||
* C#
|
||||
* [Arch](https://github.com/genaray/Arch): a simple, fast and _unity entities_
|
||||
inspired archetype ECS with optional multithreading.
|
||||
* [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
|
||||
@ -70,6 +89,3 @@ I hope this list can grow much more in the future:
|
||||
|
||||
* 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.
|
||||
|
@ -9,6 +9,7 @@
|
||||
* [Delegate](#delegate)
|
||||
* [Runtime arguments](#runtime-arguments)
|
||||
* [Lambda support](#lambda-support)
|
||||
* [Raw access](#raw-access)
|
||||
* [Signals](#signals)
|
||||
* [Event dispatcher](#event-dispatcher)
|
||||
* [Named queues](#named-queues)
|
||||
@ -38,7 +39,7 @@ 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 member functions provided along with an instance on which to
|
||||
free functions, lambdas and members 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
|
||||
@ -92,9 +93,9 @@ delegate.connect<&g>(c);
|
||||
delegate(42);
|
||||
```
|
||||
|
||||
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.<br/>
|
||||
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.<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:
|
||||
|
||||
@ -105,9 +106,15 @@ delegate(42);
|
||||
```
|
||||
|
||||
Where the function type of the delegate is `void(int)` as above. It goes without
|
||||
saying that the extra arguments are silently discarded internally.<br/>
|
||||
This is a nice-to-have feature in a lot of cases, as an example when the
|
||||
`delegate` class is used as a building block of a signal-slot system.
|
||||
saying that the extra arguments are silently discarded internally. This is a
|
||||
nice-to-have feature in a lot of cases, as an example when the `delegate` class
|
||||
is used as a building block of a signal-slot system.<br/>
|
||||
In fact, this filtering works both ways. The class tries to pass its first
|
||||
_count_ arguments **first**, then the last _count_. Watch out for conversion
|
||||
rules if in doubt when connecting a listener!<br/>
|
||||
Arbitrary functions that pull random arguments from the delegate list aren't
|
||||
supported instead. Other feature were preferred, such as support for functions
|
||||
with compatible argument lists although not equal to those of the delegate.
|
||||
|
||||
To create and initialize a delegate at once, there are a few specialized
|
||||
constructors. Because of the rules of the language, the listener is provided by
|
||||
@ -231,6 +238,24 @@ 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)`.
|
||||
|
||||
## Raw access
|
||||
|
||||
While not recommended, a delegate also allows direct access to the stored
|
||||
callable function target and underlying data, if any.<br/>
|
||||
This makes it possible to bypass the behavior of the delegate itself and force
|
||||
calls on different instances:
|
||||
|
||||
```cpp
|
||||
my_struct other;
|
||||
delegate.target(&other, 42);
|
||||
```
|
||||
|
||||
It goes without saying that this type of approach is **very** risky, especially
|
||||
since there is no way of knowing whether the contained function was originally a
|
||||
member function of some class, a free function or a lambda.<br/>
|
||||
Another possible (and meaningful) use of this feature is that of identifying a
|
||||
particular delegate through its descriptive _traits_ instead.
|
||||
|
||||
# Signals
|
||||
|
||||
Signal handlers work with references to classes, function pointers and pointers
|
||||
@ -290,7 +315,7 @@ sink.disconnect<&foo>();
|
||||
sink.disconnect<&listener::bar>(instance);
|
||||
|
||||
// disconnect all member functions of an instance, if any
|
||||
sink.disconnect(instance);
|
||||
sink.disconnect(&instance);
|
||||
|
||||
// discards all listeners at once
|
||||
sink.disconnect();
|
||||
@ -300,15 +325,6 @@ 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 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
|
||||
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.<br/>
|
||||
@ -409,7 +425,7 @@ of them at once:
|
||||
|
||||
```cpp
|
||||
dispatcher.sink<an_event>().disconnect<&listener::receive>(listener);
|
||||
dispatcher.sink<another_event>().disconnect(listener);
|
||||
dispatcher.sink<another_event>().disconnect(&listener);
|
||||
```
|
||||
|
||||
The `trigger` member function serves the purpose of sending an immediate event
|
||||
|
Reference in New Issue
Block a user