654 lines
80 KiB
HTML
654 lines
80 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
|
|
<meta name="generator" content="Doxygen 1.13.2"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
<title>EnTT: Crash Course: core functionalities</title>
|
|
<link href="tabs.css" rel="stylesheet" type="text/css"/>
|
|
<script type="text/javascript" src="jquery.js"></script>
|
|
<script type="text/javascript" src="dynsections.js"></script>
|
|
<script type="text/javascript" src="clipboard.js"></script>
|
|
<link href="navtree.css" rel="stylesheet" type="text/css"/>
|
|
<script type="text/javascript" src="resize.js"></script>
|
|
<script type="text/javascript" src="cookie.js"></script>
|
|
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
|
<script type="text/javascript" src="search/searchdata.js"></script>
|
|
<script type="text/javascript" src="search/search.js"></script>
|
|
<link href="doxygen-awesome.css" rel="stylesheet" type="text/css" />
|
|
</head>
|
|
<body>
|
|
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
|
<div id="titlearea">
|
|
<table cellspacing="0" cellpadding="0">
|
|
<tbody>
|
|
<tr id="projectrow">
|
|
<td id="projectalign">
|
|
<div id="projectname">EnTT<span id="projectnumber"> 3.15.0</span>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<!-- end header part -->
|
|
<!-- Generated by Doxygen 1.13.2 -->
|
|
<script type="text/javascript">
|
|
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|
var searchBox = new SearchBox("searchBox", "search/",'.html');
|
|
/* @license-end */
|
|
</script>
|
|
<script type="text/javascript">
|
|
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|
$(function() { codefold.init(0); });
|
|
/* @license-end */
|
|
</script>
|
|
<script type="text/javascript" src="menudata.js"></script>
|
|
<script type="text/javascript" src="menu.js"></script>
|
|
<script type="text/javascript">
|
|
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|
$(function() {
|
|
initMenu('',true,false,'search.php','Search',false);
|
|
$(function() { init_search(); });
|
|
});
|
|
/* @license-end */
|
|
</script>
|
|
<div id="main-nav"></div>
|
|
<script type="text/javascript">
|
|
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|
$(function(){ initResizable(false); });
|
|
/* @license-end */
|
|
</script>
|
|
<!-- window showing the filter options -->
|
|
<div id="MSearchSelectWindow"
|
|
onmouseover="return searchBox.OnSearchSelectShow()"
|
|
onmouseout="return searchBox.OnSearchSelectHide()"
|
|
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
|
</div>
|
|
|
|
<!-- iframe showing the search results (closed by default) -->
|
|
<div id="MSearchResultsWindow">
|
|
<div id="MSearchResults">
|
|
<div class="SRPage">
|
|
<div id="SRIndex">
|
|
<div id="SRResults"></div>
|
|
<div class="SRStatus" id="Loading">Loading...</div>
|
|
<div class="SRStatus" id="Searching">Searching...</div>
|
|
<div class="SRStatus" id="NoMatches">No Matches</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- top -->
|
|
<div id="doc-content">
|
|
<div><div class="header">
|
|
<div class="headertitle"><div class="title">Crash Course: core functionalities</div></div>
|
|
</div><!--header-->
|
|
<div class="contents">
|
|
<div class="textblock"><p><a class="anchor" id="crash-course-core-functionalities"></a></p>
|
|
<h1><a class="anchor" id="table-of-contents-2"></a>
|
|
Table of Contents</h1>
|
|
<ul>
|
|
<li><a class="el" href="md_docs_2md_2config.html#introduction">Introduction</a></li>
|
|
<li><a class="el" href="#any-as-in-any-type">Any as in any type</a><ul>
|
|
<li><a class="el" href="#small-buffer-optimization">Small buffer optimization</a></li>
|
|
<li><a class="el" href="#alignment-requirement">Alignment requirement</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="el" href="#bit">Bit</a></li>
|
|
<li><a class="el" href="#compressed-pair">Compressed pair</a></li>
|
|
<li><a class="el" href="#enum-as-bitmask">Enum as bitmask</a></li>
|
|
<li><a class="el" href="#hashed-strings">Hashed strings</a><ul>
|
|
<li><a class="el" href="#wide-characters">Wide characters</a></li>
|
|
<li><a class="el" href="#conflicts">Conflicts</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="el" href="#iterators">Iterators</a><ul>
|
|
<li><a class="el" href="#input-iterator-pointer">Input iterator pointer</a></li>
|
|
<li><a class="el" href="#iota-iterator">Iota iterator</a></li>
|
|
<li><a class="el" href="#iterable-adaptor">Iterable adaptor</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="el" href="#memory">Memory</a><ul>
|
|
<li><a class="el" href="#allocator-aware-unique-pointers">Allocator aware unique pointers</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="el" href="#monostate">Monostate</a></li>
|
|
<li><a class="el" href="#type-support">Type support</a><ul>
|
|
<li><a class="el" href="#built-in-rtti-support">Built-in RTTI support</a><ul>
|
|
<li><a class="el" href="#type-info">Type info</a></li>
|
|
<li><a class="el" href="#almost-unique-identifiers">Almost unique identifiers</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="el" href="#type-traits">Type traits</a><ul>
|
|
<li><a class="el" href="#size-of">Size of</a></li>
|
|
<li><a class="el" href="#is-applicable">Is applicable</a></li>
|
|
<li><a class="el" href="#constness-as">Constness as</a></li>
|
|
<li><a class="el" href="#member-class-type">Member class type</a></li>
|
|
<li><a class="el" href="#n-th-argument">N-th argument</a></li>
|
|
<li><a class="el" href="#integral-constant">Integral constant</a></li>
|
|
<li><a class="el" href="#tag">Tag</a></li>
|
|
<li><a class="el" href="#type-list-and-value-list">Type list and value list</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="el" href="#unique-sequential-identifiers">Unique sequential identifiers</a><ul>
|
|
<li><a class="el" href="#compile-time-generator">Compile-time generator</a></li>
|
|
<li><a class="el" href="#runtime-generator">Runtime generator</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="el" href="#utilities">Utilities</a></li>
|
|
</ul>
|
|
<h1><a class="anchor" id="introduction-2"></a>
|
|
Introduction</h1>
|
|
<p><code>EnTT</code> comes with a bunch of core functionalities mostly used by the other parts of the library.<br />
|
|
Many of these tools are also useful in everyday work. Therefore, it is worth describing them so as not to reinvent the wheel in case of need.</p>
|
|
<h1><a class="anchor" id="any-as-in-any-type"></a>
|
|
Any as in any type</h1>
|
|
<p><code>EnTT</code> offers its own <code>any</code> type. It may seem redundant considering that C++17 introduced <code>std::any</code>, but it is not (hopefully).<br />
|
|
First of all, the <em>type</em> returned by an <code>std::any</code> is a const reference to an <code>std::type_info</code>, an implementation defined class that is not something everyone 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.</p>
|
|
<p>The <code>any</code> 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 <em>small buffer optimization</em> and a fake vtable.</p>
|
|
<p>Creating an object of the <code>any</code> type, whether empty or not, is trivial:</p>
|
|
<div class="fragment"><div class="line"><span class="comment">// an empty container</span></div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> empty{};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// a container for an int</span></div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> any{0};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// in place type construction</span></div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> in_place_type{std::in_place_type<int>, 42};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// take ownership of already existing, dynamically allocated objects</span></div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> <a class="code hl_enumvalue" href="namespaceentt.html#abc4d0fa77fae26e7c01793990996c581aa49f99ae99ae9daddd1fb79b73d2db28">in_place</a>{std::in_place, std::make_unique<int>(42).release()};</div>
|
|
<div class="ttc" id="anamespaceentt_html_a74619fe0ddf5ff5ea9cf98812a3d70ce"><div class="ttname"><a href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a></div><div class="ttdeci">basic_any<> any</div><div class="ttdoc">Alias declaration for the most common use case.</div><div class="ttdef"><b>Definition</b> <a href="core_2fwd_8hpp_source.html#l00032">fwd.hpp:32</a></div></div>
|
|
<div class="ttc" id="anamespaceentt_html_abc4d0fa77fae26e7c01793990996c581aa49f99ae99ae9daddd1fb79b73d2db28"><div class="ttname"><a href="namespaceentt.html#abc4d0fa77fae26e7c01793990996c581aa49f99ae99ae9daddd1fb79b73d2db28">entt::deletion_policy::in_place</a></div><div class="ttdeci">@ in_place</div><div class="ttdoc">In-place deletion policy.</div><div class="ttdef"><b>Definition</b> <a href="entity_2fwd_8hpp_source.html#l00021">fwd.hpp:21</a></div></div>
|
|
</div><!-- fragment --><p>Alternatively, the <code>make_any</code> function serves the same purpose. It requires to always be explicit about the type and does not support taking ownership:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> any = <a class="code hl_function" href="namespaceentt.html#adb86dc3145589485c094960a089eb953">entt::make_any<int></a>(42);</div>
|
|
<div class="ttc" id="anamespaceentt_html_adb86dc3145589485c094960a089eb953"><div class="ttname"><a href="namespaceentt.html#adb86dc3145589485c094960a089eb953">entt::make_any</a></div><div class="ttdeci">basic_any< Len, Align > make_any(Args &&...args)</div><div class="ttdoc">Constructs a wrapper from a given type, passing it all arguments.</div><div class="ttdef"><b>Definition</b> <a href="any_8hpp_source.html#l00525">any.hpp:525</a></div></div>
|
|
</div><!-- fragment --><p>In all cases, the <code>any</code> class takes the burden of destroying the contained element when required, regardless of the storage strategy used for the specific object.<br />
|
|
Furthermore, an instance of <code>any</code> is not tied to an actual type. Therefore, the wrapper is reconfigured when it is assigned a new object of a type other than the one it contains.</p>
|
|
<p>There is also a way to directly assign a value to the variable contained by an <code><a class="el" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce" title="Alias declaration for the most common use case.">entt::any</a></code>, without necessarily replacing it. This is especially useful when the object is used in <em>aliasing mode</em>, as described below:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> any{42};</div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> value{3};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// assigns by copy</span></div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">any</a>.<a class="code hl_function" href="classentt_1_1basic__any.html#a4fc7178c09a4c7fc57891183800d1688">assign</a>(value);</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// assigns by move</span></div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">any</a>.<a class="code hl_function" href="classentt_1_1basic__any.html#a4fc7178c09a4c7fc57891183800d1688">assign</a>(std::move(value));</div>
|
|
<div class="ttc" id="aclassentt_1_1basic__any_html_a4fc7178c09a4c7fc57891183800d1688"><div class="ttname"><a href="classentt_1_1basic__any.html#a4fc7178c09a4c7fc57891183800d1688">entt::basic_any::assign</a></div><div class="ttdeci">bool assign(const basic_any &other)</div><div class="ttdoc">Assigns a value to the contained object without replacing it.</div><div class="ttdef"><b>Definition</b> <a href="any_8hpp_source.html#l00352">any.hpp:352</a></div></div>
|
|
</div><!-- fragment --><p>The <code>any</code> 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 <code>assign</code> function returns a boolean value that is true in case of success and false otherwise.</p>
|
|
<p>When in doubt about the type of object contained, the <code>type</code> member function returns a const reference to the <code>type_info</code> associated with its element, or <code>type_id<void>()</code> if the container is empty.<br />
|
|
The type is also used internally when comparing two <code>any</code> objects:</p>
|
|
<div class="fragment"><div class="line"><span class="keywordflow">if</span>(any == empty) { <span class="comment">/* ... */</span> }</div>
|
|
</div><!-- fragment --><p>In this case, before proceeding with a comparison, it is verified that the <em>type</em> of the two objects is actually the same.<br />
|
|
Refer to the <code>EnTT</code> type system documentation for more details about how <code>type_info</code> works and the possible risks of a comparison.</p>
|
|
<p>A particularly interesting feature of this class is that it can also be used as an opaque container for const and non-const references:</p>
|
|
<div class="fragment"><div class="line"><span class="keywordtype">int</span> value = 42;</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> any{std::in_place_type<int &>(value)};</div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> cany = <a class="code hl_function" href="namespaceentt.html#adb86dc3145589485c094960a089eb953">entt::make_any<const int &></a>(value);</div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> fwd = <a class="code hl_function" href="namespaceentt.html#af02fa96c663a6706416e47a3a6658328">entt::forward_as_any</a>(value);</div>
|
|
<div class="line"> </div>
|
|
<div class="line">any.<a class="code hl_function" href="classentt_1_1basic__any.html#a612abee6a4ebf016df27929668839fc0">emplace</a><<span class="keyword">const</span> <span class="keywordtype">int</span> &>(value);</div>
|
|
<div class="ttc" id="aclassentt_1_1basic__any_html_a612abee6a4ebf016df27929668839fc0"><div class="ttname"><a href="classentt_1_1basic__any.html#a612abee6a4ebf016df27929668839fc0">entt::basic_any::emplace</a></div><div class="ttdeci">void emplace(Args &&...args)</div><div class="ttdoc">Replaces the contained object by creating a new instance directly.</div><div class="ttdef"><b>Definition</b> <a href="any_8hpp_source.html#l00342">any.hpp:342</a></div></div>
|
|
<div class="ttc" id="anamespaceentt_html_af02fa96c663a6706416e47a3a6658328"><div class="ttname"><a href="namespaceentt.html#af02fa96c663a6706416e47a3a6658328">entt::forward_as_any</a></div><div class="ttdeci">basic_any< Len, Align > forward_as_any(Type &&value)</div><div class="ttdoc">Forwards its argument and avoids copies for lvalue references.</div><div class="ttdef"><b>Definition</b> <a href="any_8hpp_source.html#l00538">any.hpp:538</a></div></div>
|
|
</div><!-- fragment --><p>In other words, whenever <code>any</code> is explicitly told to construct an <em>alias</em>, it acts as a pointer to the original instance rather than making a copy of it or moving it internally. The contained object is never destroyed, and users must ensure that its lifetime exceeds that of the container.<br />
|
|
Similarly, it is possible to create non-owning copies of <code>any</code> from an existing object:</p>
|
|
<div class="fragment"><div class="line"><span class="comment">// aliasing constructor</span></div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a74619fe0ddf5ff5ea9cf98812a3d70ce">entt::any</a> ref = other.as_ref();</div>
|
|
</div><!-- fragment --><p>In this case, it does not matter if the original container actually holds an object or is as a reference for unmanaged elements already. The new instance thus created does not create copies and only serves as a reference for the original item.</p>
|
|
<p>It is 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 <code>data</code> member function invoked on a non-const instance of <code>any</code> that wraps a const reference returns a null pointer in all cases.</p>
|
|
<p>To cast an instance of <code>any</code> to a type, the library offers a set of <code>any_cast</code> functions in all respects similar to their most famous counterparts.<br />
|
|
The only difference is that, in the case of <code>EnTT</code>, they will not raise exceptions but will only trigger an assert in debug mode, otherwise resulting in undefined behavior in case of misuse in release mode.</p>
|
|
<h2><a class="anchor" id="small-buffer-optimization"></a>
|
|
Small buffer optimization</h2>
|
|
<p>The <code>any</code> class uses a technique called <em>small buffer optimization</em> to reduce the number of allocations where possible.<br />
|
|
The default reserved size for an instance of <code>any</code> is <code>sizeof(double[2])</code>. However, this is also configurable if needed. In fact, <code>any</code> is defined as an alias for <code>basic_any<Len></code>, where <code>Len</code> is the size above.<br />
|
|
Users can easily set a custom size or define their own aliases:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">using </span>my_any = <a class="code hl_class" href="classentt_1_1basic__any.html">entt::basic_any</a><<span class="keyword">sizeof</span>(<span class="keywordtype">double</span>[4])>;</div>
|
|
<div class="ttc" id="aclassentt_1_1basic__any_html"><div class="ttname"><a href="classentt_1_1basic__any.html">entt::basic_any</a></div><div class="ttdoc">A SBO friendly, type-safe container for single values of any type.</div><div class="ttdef"><b>Definition</b> <a href="any_8hpp_source.html#l00038">any.hpp:38</a></div></div>
|
|
</div><!-- fragment --><p>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, <code>any</code> suppresses the small buffer optimization and always dynamically allocates objects (except for aliasing cases).</p>
|
|
<h2><a class="anchor" id="alignment-requirement"></a>
|
|
Alignment requirement</h2>
|
|
<p>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 />
|
|
It is provided as an optional second parameter following the desired size for the internal storage:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">using </span>my_any = <a class="code hl_class" href="classentt_1_1basic__any.html">entt::basic_any</a><<span class="keyword">sizeof</span>(<span class="keywordtype">double</span>[4]), <span class="keyword">alignof</span>(<span class="keywordtype">double</span>[4])>;</div>
|
|
</div><!-- fragment --><p>The <code>basic_any</code> 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.</p>
|
|
<h1><a class="anchor" id="bit"></a>
|
|
Bit</h1>
|
|
<p>Finding out the population count of an unsigned integral value (<code>popcount</code>), whether a number is a power of two or not (<code>has_single_bit</code>) as well as the next power of two given a random value (<code>next_power_of_two</code>) can be useful.<br />
|
|
For example, it helps to allocate memory in pages having a size suitable for the fast modulus:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">const</span> std::size_t result = <a class="code hl_function" href="namespaceentt.html#a1ae98eeee0b0cb3e94d97d08a74a06f0">entt::fast_mod</a>(value, modulus);</div>
|
|
<div class="ttc" id="anamespaceentt_html_a1ae98eeee0b0cb3e94d97d08a74a06f0"><div class="ttname"><a href="namespaceentt.html#a1ae98eeee0b0cb3e94d97d08a74a06f0">entt::fast_mod</a></div><div class="ttdeci">constexpr std::enable_if_t< std::is_unsigned_v< Type >, Type > fast_mod(const Type value, const std::size_t mod) noexcept</div><div class="ttdoc">Fast module utility function (powers of two only).</div><div class="ttdef"><b>Definition</b> <a href="bit_8hpp_source.html#l00063">bit.hpp:63</a></div></div>
|
|
</div><!-- fragment --><p>Where <code>modulus</code> is necessarily a power of two. Perhaps not everyone knows that this type of operation is far superior in terms of performance to the basic modulus and for this reason preferred in many areas.</p>
|
|
<h1><a class="anchor" id="compressed-pair"></a>
|
|
Compressed pair</h1>
|
|
<p>Primarily designed for internal use and far from being feature complete, the <code>compressed_pair</code> class does exactly what it promises: it tries to reduce the size of a pair by exploiting <em>Empty Base Class Optimization</em> (or <em>EBCO</em>).<br />
|
|
This class <b>is not</b> a drop-in replacement for <code>std::pair</code>. However, it offers enough functionalities to be a good alternative for when reducing memory usage is more important than having some cool and probably useless feature.</p>
|
|
<p>Although the API is very close to that of <code>std::pair</code> (apart from the fact that the template parameters are inferred from the constructor and therefore there is no <code>entt::make_compressed_pair</code>), the major difference is that <code>first</code> and <code>second</code> are functions for implementation requirements:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_class" href="classentt_1_1compressed__pair.html">entt::compressed_pair</a> pair{0, 3.};</div>
|
|
<div class="line">pair.<a class="code hl_function" href="classentt_1_1compressed__pair.html#a6551d4795fa99d140d5c8eb8e55d9d38">first</a>() = 42;</div>
|
|
<div class="ttc" id="aclassentt_1_1compressed__pair_html"><div class="ttname"><a href="classentt_1_1compressed__pair.html">entt::compressed_pair</a></div><div class="ttdoc">A compressed pair.</div><div class="ttdef"><b>Definition</b> <a href="compressed__pair_8hpp_source.html#l00085">compressed_pair.hpp:87</a></div></div>
|
|
<div class="ttc" id="aclassentt_1_1compressed__pair_html_a6551d4795fa99d140d5c8eb8e55d9d38"><div class="ttname"><a href="classentt_1_1compressed__pair.html#a6551d4795fa99d140d5c8eb8e55d9d38">entt::compressed_pair::first</a></div><div class="ttdeci">constexpr first_type & first() noexcept</div><div class="ttdoc">Returns the first element that a pair stores.</div><div class="ttdef"><b>Definition</b> <a href="compressed__pair_8hpp_source.html#l00167">compressed_pair.hpp:167</a></div></div>
|
|
</div><!-- fragment --><p>There is not much to describe then. It is recommended to rely on documentation and intuition. At the end of the day, it is just a pair and nothing more.</p>
|
|
<h1><a class="anchor" id="enum-as-bitmask"></a>
|
|
Enum as bitmask</h1>
|
|
<p>Sometimes it is useful to be able to use enums as bitmasks. However, enum classes are not really suitable for the purpose. Main problem is that they do not convert implicitly to their underlying type.<br />
|
|
The choice is then between using old-fashioned enums (with all their problems that I do not want to discuss here) or writing <em>ugly</em> code.</p>
|
|
<p>Fortunately, there is also a third way: adding enough operators in the global 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):</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">enum class</span> my_flag {</div>
|
|
<div class="line"> unknown = 0x01,</div>
|
|
<div class="line"> enabled = 0x02,</div>
|
|
<div class="line"> disabled = 0x04</div>
|
|
<div class="line">};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="keyword">const</span> my_flag flags = my_flag::enabled;</div>
|
|
<div class="line"><span class="keyword">const</span> <span class="keywordtype">bool</span> is_enabled = !!(flags & my_flag::enabled);</div>
|
|
</div><!-- fragment --><p>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 the enum classes for which bitmask support should be enabled:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">template</span><></div>
|
|
<div class="line"><span class="keyword">struct </span><a class="code hl_struct" href="structentt_1_1enum__as__bitmask.html">entt::enum_as_bitmask</a><my_flag></div>
|
|
<div class="line"> : std::true_type</div>
|
|
<div class="line">{};</div>
|
|
<div class="ttc" id="astructentt_1_1enum__as__bitmask_html"><div class="ttname"><a href="structentt_1_1enum__as__bitmask.html">entt::enum_as_bitmask</a></div><div class="ttdoc">Enable bitmask support for enum classes.</div><div class="ttdef"><b>Definition</b> <a href="enum_8hpp_source.html#l00013">enum.hpp:13</a></div></div>
|
|
</div><!-- fragment --><p>This is handy when dealing with enum classes defined by third party libraries and over which the user has no control. However, it is also verbose and can be avoided by adding a specific value to the enum class itself:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">enum class</span> my_flag {</div>
|
|
<div class="line"> unknown = 0x01,</div>
|
|
<div class="line"> enabled = 0x02,</div>
|
|
<div class="line"> disabled = 0x04,</div>
|
|
<div class="line"> _entt_enum_as_bitmask</div>
|
|
<div class="line">};</div>
|
|
</div><!-- fragment --><p>In this case, there is no need to specialize the <code>enum_as_bitmask</code> traits, since <code>EnTT</code> 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 <code>&</code>, <code>|</code> but also <code>&=</code> and <code>|=</code> are available for use.</p>
|
|
<p>Refer to the official documentation for the full list of operators.</p>
|
|
<h1><a class="anchor" id="hashed-strings"></a>
|
|
Hashed strings</h1>
|
|
<p>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 <code>constexpr</code> constructor that chews a bunch of characters. Once created, one can get the original string by means of the <code>data</code> member function or convert the instance into a number.<br />
|
|
A hashed string is well suited wherever a constant expression is required. No <em>string-to-number</em> conversion will take place at runtime if used carefully.</p>
|
|
<p>Example of use:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> load(<a class="code hl_typedef" href="classentt_1_1basic__hashed__string.html#a7b625799426407d8083f7d418e2c6a9e">entt::hashed_string::hash_type</a> resource) {</div>
|
|
<div class="line"> <span class="comment">// uses the numeric representation of the resource to load and return it</span></div>
|
|
<div class="line">}</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="keyword">auto</span> resource = load(<a class="code hl_typedef" href="namespaceentt.html#a1a4c166c8989e0afebf8180e6c85683a">entt::hashed_string</a>{<span class="stringliteral">"gui/background"</span>});</div>
|
|
<div class="ttc" id="aclassentt_1_1basic__hashed__string_html_a7b625799426407d8083f7d418e2c6a9e"><div class="ttname"><a href="classentt_1_1basic__hashed__string.html#a7b625799426407d8083f7d418e2c6a9e">entt::basic_hashed_string< char >::hash_type</a></div><div class="ttdeci">typename base_type::hash_type hash_type</div><div class="ttdef"><b>Definition</b> <a href="hashed__string_8hpp_source.html#l00088">hashed_string.hpp:88</a></div></div>
|
|
<div class="ttc" id="anamespaceentt_html_a1a4c166c8989e0afebf8180e6c85683a"><div class="ttname"><a href="namespaceentt.html#a1a4c166c8989e0afebf8180e6c85683a">entt::hashed_string</a></div><div class="ttdeci">basic_hashed_string< char > hashed_string</div><div class="ttdoc">Aliases for common character types.</div><div class="ttdef"><b>Definition</b> <a href="core_2fwd_8hpp_source.html#l00041">fwd.hpp:41</a></div></div>
|
|
</div><!-- fragment --><p>There is also a <em>user defined literal</em> dedicated to hashed strings to make them more <em>user-friendly</em>:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">using namespace </span>entt::literals;</div>
|
|
<div class="line"><span class="keyword">constexpr</span> <span class="keyword">auto</span> str = <span class="stringliteral">"text"</span>_hs;</div>
|
|
</div><!-- fragment --><p>User defined literals in <code>EnTT</code> are enclosed in the <code>entt::literals</code> namespace. Therefore, the entire namespace or selectively the literal of interest must be explicitly included before each use, a bit like <code>std::literals</code>.<br />
|
|
The class also offers the necessary functionalities to create hashed strings at runtime:</p>
|
|
<div class="fragment"><div class="line">std::string orig{<span class="stringliteral">"text"</span>};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// create a full-featured hashed string...</span></div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#a1a4c166c8989e0afebf8180e6c85683a">entt::hashed_string</a> str{orig.c_str()};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// ... or compute only the unique identifier</span></div>
|
|
<div class="line"><span class="keyword">const</span> <span class="keyword">auto</span> hash = <a class="code hl_function" href="classentt_1_1basic__hashed__string.html#a3dfc8c9301c62d82add17de1cb4ffc7c">entt::hashed_string::value</a>(orig.c_str());</div>
|
|
<div class="ttc" id="aclassentt_1_1basic__hashed__string_html_a3dfc8c9301c62d82add17de1cb4ffc7c"><div class="ttname"><a href="classentt_1_1basic__hashed__string.html#a3dfc8c9301c62d82add17de1cb4ffc7c">entt::basic_hashed_string< char >::value</a></div><div class="ttdeci">constexpr hash_type value() const noexcept</div><div class="ttdef"><b>Definition</b> <a href="hashed__string_8hpp_source.html#l00175">hashed_string.hpp:175</a></div></div>
|
|
</div><!-- fragment --><p>This possibility should not be exploited in tight loops, since the computation takes place at runtime and no longer at compile-time. It could therefore affect performance to some degrees.</p>
|
|
<h2><a class="anchor" id="wide-characters"></a>
|
|
Wide characters</h2>
|
|
<p>The <code>hashed_string</code> class is an alias for <code>basic_hashed_string<char></code>. To use the C++ type for wide character representations, there exists also the alias <code>hashed_wstring</code> for <code>basic_hashed_string<wchar_t></code>.<br />
|
|
In this case, the user defined literal to use to create hashed strings on the fly is <code>_hws</code>:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">constexpr</span> <span class="keyword">auto</span> str = L<span class="stringliteral">"text"</span>_hws;</div>
|
|
</div><!-- fragment --><p>The hash type of <code>hashed_wstring</code> is the same as its counterpart.</p>
|
|
<h2><a class="anchor" id="conflicts"></a>
|
|
Conflicts</h2>
|
|
<p>The hashed string class uses FNV-1a internally to hash strings. Because of the <em>pigeonhole principle</em>, 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 is likely to give up. That is all.<br />
|
|
After all, human-readable unique identifiers are not 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 case.</p>
|
|
<h1><a class="anchor" id="iterators"></a>
|
|
Iterators</h1>
|
|
<p>Writing and working with iterators is not always easy. More often than not it also leads to duplicated code.<br />
|
|
<code>EnTT</code> tries to overcome this problem by offering some utilities designed to make this hard work easier.</p>
|
|
<h2><a class="anchor" id="input-iterator-pointer"></a>
|
|
Input iterator pointer</h2>
|
|
<p>When writing an input iterator that returns in-place constructed values if dereferenced, it is not always straightforward to figure out what <code>value_type</code> is and how to make it behave like a full-fledged pointer.<br />
|
|
Conversely, it would be very useful to have an <code>operator-></code> available on the iterator itself that always works without too much complexity.</p>
|
|
<p>The input iterator pointer is meant for this. It is a small class that wraps the in-place constructed value and adds some functions on top of it to make it suitable for use with input iterators:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">struct </span>iterator_type {</div>
|
|
<div class="line"> <span class="keyword">using </span>value_type = std::pair<first_type, second_type>;</div>
|
|
<div class="line"> <span class="keyword">using </span>pointer = <a class="code hl_struct" href="structentt_1_1input__iterator__pointer.html">input_iterator_pointer<value_type></a>;</div>
|
|
<div class="line"> <span class="keyword">using </span>reference = value_type;</div>
|
|
<div class="line"> <span class="keyword">using </span>difference_type = std::ptrdiff_t;</div>
|
|
<div class="line"> <span class="keyword">using </span>iterator_category = std::input_iterator_tag;</div>
|
|
<div class="line"> </div>
|
|
<div class="line"> <span class="comment">// ...</span></div>
|
|
<div class="line">}</div>
|
|
<div class="ttc" id="astructentt_1_1input__iterator__pointer_html"><div class="ttname"><a href="structentt_1_1input__iterator__pointer.html">entt::input_iterator_pointer</a></div><div class="ttdoc">Helper type to use as pointer with input iterators.</div><div class="ttdef"><b>Definition</b> <a href="iterator_8hpp_source.html#l00016">iterator.hpp:16</a></div></div>
|
|
</div><!-- fragment --><p>The library makes extensive use of this class internally. In many cases, the <code>value_type</code> of the returned iterators is just an input iterator pointer.</p>
|
|
<h2><a class="anchor" id="iota-iterator"></a>
|
|
Iota iterator</h2>
|
|
<p>Waiting for C++20, this iterator accepts an integral value and returns all elements in a certain range:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_class" href="classentt_1_1iota__iterator.html">entt::iota_iterator</a> first{0};</div>
|
|
<div class="line"><a class="code hl_class" href="classentt_1_1iota__iterator.html">entt::iota_iterator</a> last{100};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="keywordflow">for</span>(; first != last; ++first) {</div>
|
|
<div class="line"> <span class="keywordtype">int</span> value = *first;</div>
|
|
<div class="line"> <span class="comment">// ...</span></div>
|
|
<div class="line">}</div>
|
|
<div class="ttc" id="aclassentt_1_1iota__iterator_html"><div class="ttname"><a href="classentt_1_1iota__iterator.html">entt::iota_iterator</a></div><div class="ttdoc">Plain iota iterator (waiting for C++20).</div><div class="ttdef"><b>Definition</b> <a href="iterator_8hpp_source.html#l00056">iterator.hpp:56</a></div></div>
|
|
</div><!-- fragment --><p>In the future, views will replace this class. Meanwhile, the library makes some interesting uses of it when a range of integral values is to be returned to the user.</p>
|
|
<h2><a class="anchor" id="iterable-adaptor"></a>
|
|
Iterable adaptor</h2>
|
|
<p>Typically, a container class provides <code>begin</code> and <code>end</code> member functions (with 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 <em>elements</em>.</p>
|
|
<p>The iterable adaptor is a utility class that makes it easier to use and access data in this case.<br />
|
|
It accepts a couple of iterators (or an iterator and a sentinel) and offers an <em>iterable</em> object with all the expected methods like <code>begin</code>, <code>end</code> and whatnot.</p>
|
|
<p>The library uses this class extensively.<br />
|
|
Think for example of views, which can be iterated to access entities but also offer a method for obtaining an iterable object that returns tuples of entities and components at once.<br />
|
|
Another example is the registry class which allows users to iterate its storage by returning an iterable object for the purpose.</p>
|
|
<h1><a class="anchor" id="memory"></a>
|
|
Memory</h1>
|
|
<p>There are a handful of tools within <code>EnTT</code> 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 are designed to help the developer with everyday problems.</p>
|
|
<p>The former are very specific and for niche problems. These are tools designed to unwrap fancy or plain pointers (<code>to_address</code>) or to help forget the meaning of acronyms like <em>POCCA</em>, <em>POCMA</em> or <em>POCS</em>.<br />
|
|
I will not describe them here in detail. Instead, I recommend reading the inline documentation to those interested in the subject.</p>
|
|
<h2><a class="anchor" id="allocator-aware-unique-pointers"></a>
|
|
Allocator aware unique pointers</h2>
|
|
<p>A nasty thing in C++ (at least up to C++20) is the fact that shared pointers support allocators while unique pointers do not.<br />
|
|
There is a proposal at the moment that also shows (among the other things) how this can be implemented without any compiler support.</p>
|
|
<p>The <code>allocate_unique</code> function follows this proposal, making a virtue out of necessity:</p>
|
|
<div class="fragment"><div class="line">std::unique_ptr<my_type, entt::allocation_deleter<my_type>> ptr = <a class="code hl_function" href="namespaceentt.html#ae3729f1b7699d013f982b2de2ec781f9">entt::allocate_unique<my_type></a>(allocator, arguments);</div>
|
|
<div class="ttc" id="anamespaceentt_html_ae3729f1b7699d013f982b2de2ec781f9"><div class="ttname"><a href="namespaceentt.html#ae3729f1b7699d013f982b2de2ec781f9">entt::allocate_unique</a></div><div class="ttdeci">constexpr auto allocate_unique(Allocator &allocator, Args &&...args)</div><div class="ttdoc">Allows std::unique_ptr to use allocators (waiting for C++20).</div><div class="ttdef"><b>Definition</b> <a href="memory_8hpp_source.html#l00109">memory.hpp:109</a></div></div>
|
|
</div><!-- fragment --><p>Although the internal implementation is slightly different from what is proposed for the standard, this function offers an API that is a drop-in replacement for the same feature.</p>
|
|
<h1><a class="anchor" id="monostate"></a>
|
|
Monostate</h1>
|
|
<p>The monostate pattern is often presented as an alternative to a singleton based configuration system.<br />
|
|
This is exactly its purpose in <code>EnTT</code>. Moreover, this implementation is thread safe by design (hopefully).</p>
|
|
<p>Keys are integral values (easily obtained by hashed strings), values are basic types like <code>int</code>s or <code>bool</code>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.</p>
|
|
<p>Example of use:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_struct" href="structentt_1_1monostate.html">entt::monostate</a><<a class="code hl_typedef" href="namespaceentt.html#a1a4c166c8989e0afebf8180e6c85683a">entt::hashed_string</a>{<span class="stringliteral">"mykey"</span>}>{} = <span class="keyword">true</span>;</div>
|
|
<div class="line"><a class="code hl_struct" href="structentt_1_1monostate.html">entt::monostate</a><<span class="stringliteral">"mykey"</span>_hs>{} = 42;</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// ...</span></div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="keyword">const</span> <span class="keywordtype">bool</span> b = <a class="code hl_struct" href="structentt_1_1monostate.html">entt::monostate</a><<span class="stringliteral">"mykey"</span>_hs>{};</div>
|
|
<div class="line"><span class="keyword">const</span> <span class="keywordtype">int</span> i = <a class="code hl_struct" href="structentt_1_1monostate.html">entt::monostate</a><<a class="code hl_typedef" href="namespaceentt.html#a1a4c166c8989e0afebf8180e6c85683a">entt::hashed_string</a>{<span class="stringliteral">"mykey"</span>}>{};</div>
|
|
<div class="ttc" id="astructentt_1_1monostate_html"><div class="ttname"><a href="structentt_1_1monostate.html">entt::monostate</a></div><div class="ttdoc">Minimal implementation of the monostate pattern.</div><div class="ttdef"><b>Definition</b> <a href="monostate_8hpp_source.html#l00021">monostate.hpp:21</a></div></div>
|
|
</div><!-- fragment --><h1><a class="anchor" id="type-support"></a>
|
|
Type support</h1>
|
|
<p><code>EnTT</code> provides some basic information about types of all kinds.<br />
|
|
It also offers additional features that are not yet available in the standard library or that will never be.</p>
|
|
<h2><a class="anchor" id="built-in-rtti-support"></a>
|
|
Built-in RTTI support</h2>
|
|
<p>Runtime type identification support (or RTTI) is one of the most frequently disabled features in the C++ world, especially in the gaming sector. Regardless of the reasons for this, it is often a shame not to be able to rely on opaque type information at runtime.<br />
|
|
The library tries to fill this gap by offering a built-in system that does not serve as a replacement but comes very close to being one and offers similar information to that provided by its counterpart.</p>
|
|
<p>Basically, the whole system relies on a handful of classes. In particular:</p>
|
|
<ul>
|
|
<li><p class="startli">The unique sequential identifier associated with a given type:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> index = <a class="code hl_function" href="structentt_1_1type__index.html#ac1a87730c605024e3fb6426fc633380e">entt::type_index<a_type>::value</a>();</div>
|
|
<div class="ttc" id="astructentt_1_1type__index_html_ac1a87730c605024e3fb6426fc633380e"><div class="ttname"><a href="structentt_1_1type__index.html#ac1a87730c605024e3fb6426fc633380e">entt::type_index::value</a></div><div class="ttdeci">static id_type value() noexcept</div><div class="ttdoc">Returns the sequential identifier of a given type.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00076">type_info.hpp:76</a></div></div>
|
|
</div><!-- fragment --><p class="startli">The returned value is not 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.</p>
|
|
<p class="startli">An external generator can also be used if needed. In fact, <code>type_index</code> can be specialized by type and is also <em>sfinae-friendly</em> in order to allow more refined specializations such as:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">template</span><<span class="keyword">typename</span> Type></div>
|
|
<div class="line"><span class="keyword">struct </span><a class="code hl_struct" href="structentt_1_1type__index.html">entt::type_index</a><Type, std::void_d<decltype(Type::index())>> {</div>
|
|
<div class="line"> <span class="keyword">static</span> <a class="code hl_typedef" href="namespaceentt.html#a620d583c0e6d64acf3d394524bb72303">entt::id_type</a> <a class="code hl_function" href="structentt_1_1type__index.html#ac1a87730c605024e3fb6426fc633380e">value</a>() noexcept {</div>
|
|
<div class="line"> <span class="keywordflow">return</span> Type::index();</div>
|
|
<div class="line"> }</div>
|
|
<div class="line">};</div>
|
|
<div class="ttc" id="anamespaceentt_html_a620d583c0e6d64acf3d394524bb72303"><div class="ttname"><a href="namespaceentt.html#a620d583c0e6d64acf3d394524bb72303">entt::id_type</a></div><div class="ttdeci">std::uint32_t id_type</div><div class="ttdoc">Alias declaration for type identifiers.</div><div class="ttdef"><b>Definition</b> <a href="core_2fwd_8hpp_source.html#l00029">fwd.hpp:29</a></div></div>
|
|
<div class="ttc" id="astructentt_1_1type__index_html"><div class="ttname"><a href="structentt_1_1type__index.html">entt::type_index</a></div><div class="ttdoc">Type sequential identifier.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00071">type_info.hpp:71</a></div></div>
|
|
</div><!-- fragment --><p class="startli">Indexes <b>must</b> be sequentially generated in this case.<br />
|
|
The tool is widely used within <code>EnTT</code>. Generating indices not sequentially would break an assumption and would likely lead to undesired behaviors.</p>
|
|
</li>
|
|
<li><p class="startli">The hash value associated with a given type:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> hash = <a class="code hl_function" href="structentt_1_1type__hash.html#a925c3666663e463a28897f04a7e2c314">entt::type_hash<a_type>::value</a>();</div>
|
|
<div class="ttc" id="astructentt_1_1type__hash_html_a925c3666663e463a28897f04a7e2c314"><div class="ttname"><a href="structentt_1_1type__hash.html#a925c3666663e463a28897f04a7e2c314">entt::type_hash::value</a></div><div class="ttdeci">static constexpr id_type value() noexcept</div><div class="ttdoc">Returns the numeric representation of a given type.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00101">type_info.hpp:101</a></div></div>
|
|
</div><!-- fragment --><p class="startli">In general, the <code>value</code> function exposed by <code>type_hash</code> is also <code>constexpr</code> but this is not guaranteed for all compilers and platforms (although it is valid with the most well-known and popular ones).</p>
|
|
<p class="startli">This function <b>can</b> 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 />
|
|
Users can prevent the library from using these features by means of the <code>ENTT_STANDARD_CPP</code> 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.</p>
|
|
<p class="startli">As it happens with <code>type_index</code>, also <code>type_hash</code> is a <em>sfinae-friendly</em> class that can be specialized in order to customize its behavior globally or on a per-type or per-traits basis.</p>
|
|
</li>
|
|
<li><p class="startli">The name associated with a given type:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> name = <a class="code hl_function" href="structentt_1_1type__name.html#a25bf087449089be106e33b64430bcbd4">entt::type_name<a_type>::value</a>();</div>
|
|
<div class="ttc" id="astructentt_1_1type__name_html_a25bf087449089be106e33b64430bcbd4"><div class="ttname"><a href="structentt_1_1type__name.html#a25bf087449089be106e33b64430bcbd4">entt::type_name::value</a></div><div class="ttdeci">static constexpr std::string_view value() noexcept</div><div class="ttdoc">Returns the name of a given type.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00122">type_info.hpp:122</a></div></div>
|
|
</div><!-- fragment --><p class="startli">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 is not available.<br />
|
|
For example, given the following class:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">struct </span>my_type { <span class="comment">/* ... */</span> };</div>
|
|
</div><!-- fragment --><p class="startli">The name is <code>my_type</code> when compiled with GCC or CLang and <code>struct my_type</code> 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 <code>std::string_view</code>. Users can easily access it and modify it as needed, for example by removing the word <code>struct</code> to normalize the result. <code>EnTT</code> does not do this for obvious reasons, since it would be creating a new string at runtime otherwise.</p>
|
|
<p class="startli">This function <b>can</b> use non-standard features of the language for its own purposes. Users can prevent the library from using these features by means of the <code>ENTT_STANDARD_CPP</code> definition. In this case, the name is just empty.</p>
|
|
<p class="startli">As it happens with <code>type_index</code>, also <code>type_name</code> is a <em>sfinae-friendly</em> class that can be specialized in order to customize its behavior globally or on a per-type or per-traits basis.</p>
|
|
</li>
|
|
</ul>
|
|
<p>These are then combined into utilities that aim to offer an API that is somewhat similar to that made available by the standard library.</p>
|
|
<h3><a class="anchor" id="type-info"></a>
|
|
Type info</h3>
|
|
<p>The <code>type_info</code> class is not a drop-in replacement for <code>std::type_info</code> but can provide similar information which are not implementation defined and do not require to enable RTTI.<br />
|
|
Therefore, they can sometimes be even more reliable than those obtained otherwise.</p>
|
|
<p>Its type defines an opaque class that is also copyable and movable.<br />
|
|
Objects of this type are generally returned by the <code>type_id</code> functions:</p>
|
|
<div class="fragment"><div class="line"><span class="comment">// by type</span></div>
|
|
<div class="line"><span class="keyword">auto</span> info = <a class="code hl_function" href="namespaceentt.html#adb9682d476edbbe4434680363f9c0eb3">entt::type_id<a_type></a>();</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// by value</span></div>
|
|
<div class="line"><span class="keyword">auto</span> other = <a class="code hl_function" href="namespaceentt.html#adb9682d476edbbe4434680363f9c0eb3">entt::type_id</a>(42);</div>
|
|
<div class="ttc" id="anamespaceentt_html_adb9682d476edbbe4434680363f9c0eb3"><div class="ttname"><a href="namespaceentt.html#adb9682d476edbbe4434680363f9c0eb3">entt::type_id</a></div><div class="ttdeci">const type_info & type_id() noexcept</div><div class="ttdoc">Returns the type info object associated to a given type.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00251">type_info.hpp:251</a></div></div>
|
|
</div><!-- fragment --><p>All elements thus received are nothing more than const references to instances of <code>type_info</code> with static storage duration.<br />
|
|
This is convenient for saving the entire object aside for the cost of a pointer. However, nothing prevents from constructing <code>type_info</code> objects directly:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_struct" href="structentt_1_1type__info.html">entt::type_info</a> info{std::in_place_type<int>};</div>
|
|
<div class="ttc" id="astructentt_1_1type__info_html"><div class="ttname"><a href="structentt_1_1type__info.html">entt::type_info</a></div><div class="ttdoc">Implementation specific information about a type.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00133">type_info.hpp:133</a></div></div>
|
|
</div><!-- fragment --><p>These are the information made available by <code>type_info</code>:</p>
|
|
<ul>
|
|
<li><p class="startli">The index associated with a given type:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> idx = <a class="code hl_function" href="namespaceentt.html#adb9682d476edbbe4434680363f9c0eb3">entt::type_id<a_type></a>().<a class="code hl_function" href="structentt_1_1type__info.html#a3335aa54e69d9a63d5ccbcef8e994d3b">index</a>();</div>
|
|
<div class="ttc" id="astructentt_1_1type__info_html_a3335aa54e69d9a63d5ccbcef8e994d3b"><div class="ttname"><a href="structentt_1_1type__info.html#a3335aa54e69d9a63d5ccbcef8e994d3b">entt::type_info::index</a></div><div class="ttdeci">constexpr id_type index() const noexcept</div><div class="ttdoc">Type index.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00150">type_info.hpp:150</a></div></div>
|
|
</div><!-- fragment --><p class="startli">This is also an alias for the following:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> idx = <a class="code hl_struct" href="structentt_1_1type__index.html">entt::type_index<std::remove_cv_t<std::remove_reference_t<a_type></a>>>::value();</div>
|
|
</div><!-- fragment --></li>
|
|
<li><p class="startli">The hash value associated with a given type:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> hash = <a class="code hl_function" href="namespaceentt.html#adb9682d476edbbe4434680363f9c0eb3">entt::type_id<a_type></a>().<a class="code hl_function" href="structentt_1_1type__info.html#a7bbf926cc62b6441c5b64837cb5a52a3">hash</a>();</div>
|
|
<div class="ttc" id="astructentt_1_1type__info_html_a7bbf926cc62b6441c5b64837cb5a52a3"><div class="ttname"><a href="structentt_1_1type__info.html#a7bbf926cc62b6441c5b64837cb5a52a3">entt::type_info::hash</a></div><div class="ttdeci">constexpr id_type hash() const noexcept</div><div class="ttdoc">Type hash.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00158">type_info.hpp:158</a></div></div>
|
|
</div><!-- fragment --><p class="startli">This is also an alias for the following:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> hash = <a class="code hl_struct" href="structentt_1_1type__hash.html">entt::type_hash<std::remove_cv_t<std::remove_reference_t<a_type></a>>>::value();</div>
|
|
<div class="ttc" id="astructentt_1_1type__hash_html"><div class="ttname"><a href="structentt_1_1type__hash.html">entt::type_hash</a></div><div class="ttdoc">Type hash.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00092">type_info.hpp:92</a></div></div>
|
|
</div><!-- fragment --></li>
|
|
<li><p class="startli">The name associated with a given type:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> name = <a class="code hl_function" href="namespaceentt.html#adb9682d476edbbe4434680363f9c0eb3">entt::type_id<my_type></a>().<a class="code hl_function" href="structentt_1_1type__info.html#a56102f0fe01990eb666e7829e402dbdb">name</a>();</div>
|
|
<div class="ttc" id="astructentt_1_1type__info_html_a56102f0fe01990eb666e7829e402dbdb"><div class="ttname"><a href="structentt_1_1type__info.html#a56102f0fe01990eb666e7829e402dbdb">entt::type_info::name</a></div><div class="ttdeci">constexpr std::string_view name() const noexcept</div><div class="ttdoc">Type name.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00166">type_info.hpp:166</a></div></div>
|
|
</div><!-- fragment --><p class="startli">This is also an alias for the following:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> name = <a class="code hl_struct" href="structentt_1_1type__name.html">entt::type_name<std::remove_cv_t<std::remove_reference_t<a_type></a>>>::value();</div>
|
|
<div class="ttc" id="astructentt_1_1type__name_html"><div class="ttname"><a href="structentt_1_1type__name.html">entt::type_name</a></div><div class="ttdoc">Type name.</div><div class="ttdef"><b>Definition</b> <a href="type__info_8hpp_source.html#l00117">type_info.hpp:117</a></div></div>
|
|
</div><!-- fragment --></li>
|
|
</ul>
|
|
<p>Where all accessed features are available at compile-time, the <code>type_info</code> class is also fully <code>constexpr</code>. However, this cannot be guaranteed in advance and depends mainly on the compiler in use and any specializations of the classes described above.</p>
|
|
<h3><a class="anchor" id="almost-unique-identifiers"></a>
|
|
Almost unique identifiers</h3>
|
|
<p>Since the default non-standard, compile-time implementation of <code>type_hash</code> makes use of hashed strings, it may happen that two types are assigned the same hash value.<br />
|
|
In fact, although this is quite rare, it is not entirely excluded.</p>
|
|
<p>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, <code>type_name</code> returns the same value for the two types.<br />
|
|
Fortunately, there are several easy ways to deal with this:</p>
|
|
<ul>
|
|
<li>The most trivial one is to define the <code>ENTT_STANDARD_CPP</code> macro. Runtime identifiers do not suffer from the same problem in fact. However, this solution does not work well with a plugin system, where the libraries are not linked.</li>
|
|
<li>Another possibility is to specialize the <code>type_name</code> class for one of the conflicting types, in order to assign it a custom identifier. This is probably the easiest solution that also preserves the feature of the tool.</li>
|
|
<li>A fully customized identifier generation policy (based for example on enum classes or preprocessing steps) may represent yet another option.</li>
|
|
</ul>
|
|
<p>These are just some examples of possible approaches to the problem, but there are many others. As already mentioned above, since users have full control over their types, this problem is in any case easy to solve and should not worry too much.<br />
|
|
In all likelihood, it will never happen to run into a conflict anyway.</p>
|
|
<h2><a class="anchor" id="type-traits"></a>
|
|
Type traits</h2>
|
|
<p>A handful of utilities and traits not present in the standard template library but which can be useful in everyday life.<br />
|
|
This list <b>is not</b> exhaustive and contains only some of the most useful classes. Refer to the inline documentation for more information on the features offered by this module.</p>
|
|
<h3><a class="anchor" id="size-of"></a>
|
|
Size of</h3>
|
|
<p>The standard operator <code>sizeof</code> complains if users provide it with functions or incomplete types. On the other hand, it is 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 <code>sizeof</code> that works under all circumstances, returning zero if the type is not supported:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">const</span> <span class="keyword">auto</span> size = <a class="code hl_variable" href="namespaceentt.html#a15f9a70cbdd5a64f897a012ab2b5834f">entt::size_of_v<void></a>;</div>
|
|
<div class="ttc" id="anamespaceentt_html_a15f9a70cbdd5a64f897a012ab2b5834f"><div class="ttname"><a href="namespaceentt.html#a15f9a70cbdd5a64f897a012ab2b5834f">entt::size_of_v</a></div><div class="ttdeci">constexpr std::size_t size_of_v</div><div class="ttdoc">Helper variable template.</div><div class="ttdef"><b>Definition</b> <a href="core_2type__traits_8hpp_source.html#l00074">type_traits.hpp:74</a></div></div>
|
|
</div><!-- fragment --><h3><a class="anchor" id="is-applicable"></a>
|
|
Is applicable</h3>
|
|
<p>The standard library offers the great <code>std::is_invocable</code> trait in several forms. This takes a function type and a series of arguments and returns true if the condition is satisfied.<br />
|
|
Moreover, users are also provided with <code>std::apply</code>, a tool for combining invocable elements and tuples of arguments.</p>
|
|
<p>It would therefore be a good idea to have a variant of <code>std::is_invocable</code> that also accepts its arguments in the form of a tuple-like type, so as to complete the offer:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">constexpr</span> <span class="keywordtype">bool</span> result = <a class="code hl_struct" href="structentt_1_1is__applicable.html">entt::is_applicable<Func, std::tuple<a_type, another_type></a>>;</div>
|
|
<div class="ttc" id="astructentt_1_1is__applicable_html"><div class="ttname"><a href="structentt_1_1is__applicable.html">entt::is_applicable</a></div><div class="ttdoc">Same as std::is_invocable, but with tuples.</div><div class="ttdef"><b>Definition</b> <a href="core_2type__traits_8hpp_source.html#l00601">type_traits.hpp:601</a></div></div>
|
|
</div><!-- fragment --><p>This trait is built on top of <code>std::is_invocable</code> and does nothing but unpack a tuple-like type and simplify the code at the call site.</p>
|
|
<h3><a class="anchor" id="constness-as"></a>
|
|
Constness as</h3>
|
|
<p>A utility to easily transfer the constness of a type to another type:</p>
|
|
<div class="fragment"><div class="line"><span class="comment">// type is const dst_type because of the constness of src_type</span></div>
|
|
<div class="line"><span class="keyword">using </span>type = <a class="code hl_typedef" href="namespaceentt.html#a13168ef82af733bfe584f34f29472d20">entt::constness_as_t<dst_type, const src_type></a>;</div>
|
|
<div class="ttc" id="anamespaceentt_html_a13168ef82af733bfe584f34f29472d20"><div class="ttname"><a href="namespaceentt.html#a13168ef82af733bfe584f34f29472d20">entt::constness_as_t</a></div><div class="ttdeci">typename constness_as< To, From >::type constness_as_t</div><div class="ttdoc">Alias template to facilitate the transcription of the constness.</div><div class="ttdef"><b>Definition</b> <a href="core_2type__traits_8hpp_source.html#l00841">type_traits.hpp:841</a></div></div>
|
|
</div><!-- fragment --><p>The trait is subject to the rules of the language. For example, <em>transferring</em> constness between references will not give the desired effect.</p>
|
|
<h3><a class="anchor" id="member-class-type"></a>
|
|
Member class type</h3>
|
|
<p>The <code>auto</code> template parameter introduced with C++17 made it possible to simplify many class templates and template functions but also made the class type opaque when members are passed as template arguments.<br />
|
|
The purpose of this utility is to extract the class type in a few lines of code:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">template</span><<span class="keyword">typename</span> Member></div>
|
|
<div class="line"><span class="keyword">using </span>clazz = <a class="code hl_typedef" href="namespaceentt.html#a021c5343afb213cf29d3703cdc2c8cbc">entt::member_class_t<Member></a>;</div>
|
|
<div class="ttc" id="anamespaceentt_html_a021c5343afb213cf29d3703cdc2c8cbc"><div class="ttname"><a href="namespaceentt.html#a021c5343afb213cf29d3703cdc2c8cbc">entt::member_class_t</a></div><div class="ttdeci">typename member_class< Member >::type member_class_t</div><div class="ttdoc">Helper type.</div><div class="ttdef"><b>Definition</b> <a href="core_2type__traits_8hpp_source.html#l00870">type_traits.hpp:870</a></div></div>
|
|
</div><!-- fragment --><h3><a class="anchor" id="n-th-argument"></a>
|
|
N-th argument</h3>
|
|
<p>A utility to quickly find the n-th argument of a function, member function or data member (for blind operations on opaque types):</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">using </span>type = <a class="code hl_typedef" href="namespaceentt.html#a1665363338d4c3e3a6b4afbec94d0d49">entt::nth_argument_t</a><1u, <span class="keyword">decltype</span>(&clazz::member)>;</div>
|
|
<div class="ttc" id="anamespaceentt_html_a1665363338d4c3e3a6b4afbec94d0d49"><div class="ttname"><a href="namespaceentt.html#a1665363338d4c3e3a6b4afbec94d0d49">entt::nth_argument_t</a></div><div class="ttdeci">typename nth_argument< Index, Candidate >::type nth_argument_t</div><div class="ttdoc">Helper type.</div><div class="ttdef"><b>Definition</b> <a href="core_2type__traits_8hpp_source.html#l00905">type_traits.hpp:905</a></div></div>
|
|
</div><!-- fragment --><p>Disambiguation of overloaded functions is the responsibility of the user, should it be needed.</p>
|
|
<h3><a class="anchor" id="integral-constant"></a>
|
|
Integral constant</h3>
|
|
<p>Since <code>std::integral_constant</code> may be annoying because of its form that requires to specify both a type and a value of that type, there is a more user-friendly shortcut for the creation of integral constants.<br />
|
|
This shortcut is the alias template <code><a class="el" href="namespaceentt.html#a0e653af66fcdc9e4abc2a81f362b8963" title="Wraps a static constant.">entt::integral_constant</a></code>:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">constexpr</span> <span class="keyword">auto</span> constant = <a class="code hl_typedef" href="namespaceentt.html#a0e653af66fcdc9e4abc2a81f362b8963">entt::integral_constant<42></a>;</div>
|
|
<div class="ttc" id="anamespaceentt_html_a0e653af66fcdc9e4abc2a81f362b8963"><div class="ttname"><a href="namespaceentt.html#a0e653af66fcdc9e4abc2a81f362b8963">entt::integral_constant</a></div><div class="ttdeci">std::integral_constant< decltype(Value), Value > integral_constant</div><div class="ttdoc">Wraps a static constant.</div><div class="ttdef"><b>Definition</b> <a href="core_2type__traits_8hpp_source.html#l00097">type_traits.hpp:97</a></div></div>
|
|
</div><!-- fragment --><p>Among the other uses, when combined with a hashed string it helps to define tags as human-readable <em>names</em> where actual types would be required otherwise:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">constexpr</span> <span class="keyword">auto</span> enemy_tag = <a class="code hl_typedef" href="namespaceentt.html#a0e653af66fcdc9e4abc2a81f362b8963">entt::integral_constant</a><<span class="stringliteral">"enemy"</span>_hs>;</div>
|
|
<div class="line"><a class="code hl_typedef" href="namespaceentt.html#ab8c1f492841aeafa5e75422af3f0cdc4">registry</a>.emplace<enemy_tag>(<a class="code hl_enumeration" href="namespaceentt.html#a0b54e231d069e8a231e14b223388808a">entity</a>);</div>
|
|
<div class="ttc" id="anamespaceentt_html_a0b54e231d069e8a231e14b223388808a"><div class="ttname"><a href="namespaceentt.html#a0b54e231d069e8a231e14b223388808a">entt::entity</a></div><div class="ttdeci">entity</div><div class="ttdoc">Default entity identifier.</div><div class="ttdef"><b>Definition</b> <a href="entity_2fwd_8hpp_source.html#l00014">fwd.hpp:14</a></div></div>
|
|
<div class="ttc" id="anamespaceentt_html_ab8c1f492841aeafa5e75422af3f0cdc4"><div class="ttname"><a href="namespaceentt.html#ab8c1f492841aeafa5e75422af3f0cdc4">entt::registry</a></div><div class="ttdeci">basic_registry<> registry</div><div class="ttdoc">Alias declaration for the most common use case.</div><div class="ttdef"><b>Definition</b> <a href="entity_2fwd_8hpp_source.html#l00095">fwd.hpp:95</a></div></div>
|
|
</div><!-- fragment --><h3><a class="anchor" id="tag"></a>
|
|
Tag</h3>
|
|
<p>Type <code>id_type</code> is very important and widely used in <code>EnTT</code>. Therefore, there is a more user-friendly shortcut for the creation of constants based on it.<br />
|
|
This shortcut is the alias template <code><a class="el" href="namespaceentt.html#ae20502ac2073901175466d05be8a3c20" title="Alias template to facilitate the creation of named values.">entt::tag</a></code>.</p>
|
|
<p>If used in combination with hashed strings, it helps to use human-readable names where types would be required otherwise. As an example:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_typedef" href="namespaceentt.html#ab8c1f492841aeafa5e75422af3f0cdc4">registry</a>.emplace<<a class="code hl_typedef" href="namespaceentt.html#ae20502ac2073901175466d05be8a3c20">entt::tag</a><<span class="stringliteral">"enemy"</span>_hs>>(<a class="code hl_enumeration" href="namespaceentt.html#a0b54e231d069e8a231e14b223388808a">entity</a>);</div>
|
|
<div class="ttc" id="anamespaceentt_html_ae20502ac2073901175466d05be8a3c20"><div class="ttname"><a href="namespaceentt.html#ae20502ac2073901175466d05be8a3c20">entt::tag</a></div><div class="ttdeci">integral_constant< Value > tag</div><div class="ttdoc">Alias template to facilitate the creation of named values.</div><div class="ttdef"><b>Definition</b> <a href="core_2type__traits_8hpp_source.html#l00104">type_traits.hpp:104</a></div></div>
|
|
</div><!-- fragment --><p>However, this is not the only permitted use. Literally any value convertible to <code>id_type</code> is a good candidate, such as the named constants of an unscoped enum.</p>
|
|
<h3><a class="anchor" id="type-list-and-value-list"></a>
|
|
Type list and value list</h3>
|
|
<p>There is no respectable library where the much desired <em>type list</em> can be missing.<br />
|
|
<code>EnTT</code> is no exception and provides (making extensive use of it internally) the <code>type_list</code> type, in addition to its <code>value_list</code> counterpart dedicated to non-type template parameters.</p>
|
|
<p>Here is a (possibly incomplete) list of the functionalities that come with a type list:</p>
|
|
<ul>
|
|
<li><code>type_list_element[_t]</code> to get the N-th element of a type list.</li>
|
|
<li><code>type_list_index[_v]</code> to get the index of a given element of a type list.</li>
|
|
<li><code>type_list_cat[_t]</code> and a handy <code>operator+</code> to concatenate type lists.</li>
|
|
<li><code>type_list_unique[_t]</code> to remove duplicate types from a type list.</li>
|
|
<li><code>type_list_contains[_v]</code> to know if a type list contains a given type.</li>
|
|
<li><code>type_list_diff[_t]</code> to remove types from type lists.</li>
|
|
<li><code>type_list_transform[_t]</code> to <em>transform</em> a range and create another type list.</li>
|
|
</ul>
|
|
<p>I am also pretty sure that more and more utilities will be added over time as needs become apparent.<br />
|
|
Many of these functionalities also exist in their version dedicated to value lists. We therefore have <code>value_list_element[_v]</code> as well as <code>value_list_cat[_t]</code>and so on.</p>
|
|
<h1><a class="anchor" id="unique-sequential-identifiers"></a>
|
|
Unique sequential identifiers</h1>
|
|
<p>Sometimes it is useful to be able to give unique, sequential numeric identifiers to types either at compile-time or runtime.<br />
|
|
There are plenty of different solutions for this out there, and I could have used one of them. However, I decided to spend my time to define a couple of tools that fully embrace what modern C++ has to offer.</p>
|
|
<h2><a class="anchor" id="compile-time-generator"></a>
|
|
Compile-time generator</h2>
|
|
<p>To generate sequential numeric identifiers at compile-time, <code>EnTT</code> offers the <code>ident</code> class template:</p>
|
|
<div class="fragment"><div class="line"><span class="comment">// defines the identifiers for the given types</span></div>
|
|
<div class="line"><span class="keyword">using </span>id = <a class="code hl_class" href="classentt_1_1ident.html">entt::ident<a_type, another_type></a>;</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// ...</span></div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="keywordflow">switch</span>(a_type_identifier) {</div>
|
|
<div class="line"><span class="keywordflow">case</span> id::value<a_type>:</div>
|
|
<div class="line"> <span class="comment">// ...</span></div>
|
|
<div class="line"> <span class="keywordflow">break</span>;</div>
|
|
<div class="line"><span class="keywordflow">case</span> id::value<another_type>:</div>
|
|
<div class="line"> <span class="comment">// ...</span></div>
|
|
<div class="line"> <span class="keywordflow">break</span>;</div>
|
|
<div class="line"><span class="keywordflow">default</span>:</div>
|
|
<div class="line"> <span class="comment">// ...</span></div>
|
|
<div class="line">}</div>
|
|
<div class="ttc" id="aclassentt_1_1ident_html"><div class="ttname"><a href="classentt_1_1ident.html">entt::ident</a></div><div class="ttdoc">Type integral identifiers.</div><div class="ttdef"><b>Definition</b> <a href="ident_8hpp_source.html#l00017">ident.hpp:17</a></div></div>
|
|
</div><!-- fragment --><p>This is what this class template has to offer: a <code>value</code> inline variable that contains a numeric identifier for the given type. It can be used in any context where constant expressions are required.</p>
|
|
<p>As long as the list remains unchanged, identifiers are also guaranteed to be stable across different runs. If used in a production environment where a type needs to be removed, a placeholder can help to leave the other identifiers the same:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">template</span><<span class="keyword">typename</span>></div>
|
|
<div class="line"><span class="keyword">struct </span>ignore_type {};</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="keyword">using </span>id = <a class="code hl_class" href="classentt_1_1ident.html">entt::ident</a><</div>
|
|
<div class="line"> a_type_still_valid,</div>
|
|
<div class="line"> ignore_type<no_longer_valid_type>,</div>
|
|
<div class="line"> another_type_still_valid</div>
|
|
<div class="line">>;</div>
|
|
</div><!-- fragment --><p>Perhaps a bit ugly to see in a codebase, but it gets the job done at least.</p>
|
|
<h2><a class="anchor" id="runtime-generator"></a>
|
|
Runtime generator</h2>
|
|
<p>The <code>family</code> class template helps to generate sequential numeric identifiers for types at runtime:</p>
|
|
<div class="fragment"><div class="line"><span class="comment">// defines a custom generator</span></div>
|
|
<div class="line"><span class="keyword">using </span>id = <a class="code hl_class" href="classentt_1_1family.html">entt::family<struct my_tag></a>;</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="comment">// ...</span></div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="keyword">const</span> <span class="keyword">auto</span> a_type_id = id::value<a_type>;</div>
|
|
<div class="line"><span class="keyword">const</span> <span class="keyword">auto</span> another_type_id = id::value<another_type>;</div>
|
|
<div class="ttc" id="aclassentt_1_1family_html"><div class="ttname"><a href="classentt_1_1family.html">entt::family</a></div><div class="ttdoc">Dynamic identifier generator.</div><div class="ttdef"><b>Definition</b> <a href="family_8hpp_source.html#l00017">family.hpp:17</a></div></div>
|
|
</div><!-- fragment --><p>This is what a <em>family</em> has to offer: a <code>value</code> inline variable that contains a numeric identifier for the given type.<br />
|
|
The generator is customizable, so as to get different <em>sequences</em> for different purposes if needed.</p>
|
|
<p>Identifiers are not guaranteed to be stable across different runs. Indeed it mostly depends on the flow of execution.</p>
|
|
<h1><a class="anchor" id="utilities"></a>
|
|
Utilities</h1>
|
|
<p>It is not possible to escape the temptation to add utilities of some kind to a library. In fact, <code>EnTT</code> also provides a handful of tools to simplify the life of developers:</p>
|
|
<ul>
|
|
<li><code><a class="el" href="structentt_1_1identity.html" title="Identity function object (waiting for C++20).">entt::identity</a></code>: the identity function object that will be available with C++20. It returns its argument unchanged and nothing more. It is useful as a sort of <em>do nothing</em> function in template programming.</li>
|
|
<li><p class="startli"><code><a class="el" href="namespaceentt.html#ac5131df9ce458a6884c43595f501f916" title="Constant utility to disambiguate overloaded members of a class.">entt::overload</a></code>: a tool to disambiguate different overloads from their function type. It works with both free and member functions.<br />
|
|
Consider the following definition:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">struct </span>clazz {</div>
|
|
<div class="line"> <span class="keywordtype">void</span> bar(<span class="keywordtype">int</span>) {}</div>
|
|
<div class="line"> <span class="keywordtype">void</span> bar() {}</div>
|
|
<div class="line">};</div>
|
|
</div><!-- fragment --><p class="startli">This utility can be used to get the <em>right</em> overload as:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> *member = <a class="code hl_function" href="namespaceentt.html#ac5131df9ce458a6884c43595f501f916">entt::overload<void(int)></a>(&clazz::bar);</div>
|
|
<div class="ttc" id="anamespaceentt_html_ac5131df9ce458a6884c43595f501f916"><div class="ttname"><a href="namespaceentt.html#ac5131df9ce458a6884c43595f501f916">entt::overload</a></div><div class="ttdeci">constexpr auto overload(Type Class::*member) noexcept</div><div class="ttdoc">Constant utility to disambiguate overloaded members of a class.</div><div class="ttdef"><b>Definition</b> <a href="core_2utility_8hpp_source.html#l00034">utility.hpp:34</a></div></div>
|
|
</div><!-- fragment --><p class="startli">The line above is literally equivalent to:</p>
|
|
<div class="fragment"><div class="line"><span class="keyword">auto</span> *member = <span class="keyword">static_cast<</span><span class="keywordtype">void</span>(clazz:: *)(<span class="keywordtype">int</span>)<span class="keyword">></span>(&clazz::bar);</div>
|
|
</div><!-- fragment --><p class="startli">Just easier to read and shorter to type.</p>
|
|
</li>
|
|
<li><p class="startli"><code><a class="el" href="structentt_1_1overloaded.html" title="Helper type for visitors.">entt::overloaded</a></code>: a small class template used to create a new type with an overloaded <code>operator()</code> from a bunch of lambdas or functors.<br />
|
|
As an example:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_struct" href="structentt_1_1overloaded.html">entt::overloaded</a> func{</div>
|
|
<div class="line"> [](<span class="keywordtype">int</span> value) { <span class="comment">/* ... */</span> },</div>
|
|
<div class="line"> [](<span class="keywordtype">char</span> value) { <span class="comment">/* ... */</span> }</div>
|
|
<div class="line">};</div>
|
|
<div class="line"> </div>
|
|
<div class="line">func(42);</div>
|
|
<div class="line">func(<span class="charliteral">'c'</span>);</div>
|
|
<div class="ttc" id="astructentt_1_1overloaded_html"><div class="ttname"><a href="structentt_1_1overloaded.html">entt::overloaded</a></div><div class="ttdoc">Helper type for visitors.</div><div class="ttdef"><b>Definition</b> <a href="core_2utility_8hpp_source.html#l00054">utility.hpp:54</a></div></div>
|
|
</div><!-- fragment --><p class="startli">Rather useful when doing metaprogramming and having to pass to a function a callable object that supports multiple types at once.</p>
|
|
</li>
|
|
<li><p class="startli"><code><a class="el" href="structentt_1_1y__combinator.html" title="Basic implementation of a y-combinator.">entt::y_combinator</a></code>: this is a C++ implementation of <b>the</b> <em>y-combinator</em>. If it is not clear what it is, there is probably no need for this utility.<br />
|
|
Below is a small example to show its use:</p>
|
|
<div class="fragment"><div class="line"><a class="code hl_struct" href="structentt_1_1y__combinator.html">entt::y_combinator</a> gauss([](<span class="keyword">const</span> <span class="keyword">auto</span> &self, <span class="keyword">auto</span> value) -> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> {</div>
|
|
<div class="line"> <span class="keywordflow">return</span> value ? (value + self(value-1u)) : 0;</div>
|
|
<div class="line">});</div>
|
|
<div class="line"> </div>
|
|
<div class="line"><span class="keyword">const</span> <span class="keyword">auto</span> result = gauss(3u);</div>
|
|
<div class="ttc" id="astructentt_1_1y__combinator_html"><div class="ttname"><a href="structentt_1_1y__combinator.html">entt::y_combinator</a></div><div class="ttdoc">Basic implementation of a y-combinator.</div><div class="ttdef"><b>Definition</b> <a href="core_2utility_8hpp_source.html#l00070">utility.hpp:70</a></div></div>
|
|
</div><!-- fragment --><p class="startli">Maybe convoluted at first glance but certainly effective. Unfortunately, the language does not make it possible to do much better.</p>
|
|
</li>
|
|
</ul>
|
|
<p>This is a rundown of the (actually few) utilities made available by <code>EnTT</code>. The list will probably grow over time, but the size of each will remain rather small, as has been the case so far. </p>
|
|
</div></div><!-- contents -->
|
|
</div><!-- PageDoc -->
|
|
<!-- start footer part -->
|
|
<hr class="footer"/><address class="footer"><small>
|
|
Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.13.2
|
|
</small></address>
|
|
</div><!-- doc-content -->
|
|
</body>
|
|
</html>
|