1 Star 0 Fork 0

mobangjack / memory

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
md_doc_internal_usage.html 30.31 KB
一键复制 编辑 原始数据 按行查看 历史
Jonathan Müller 提交于 2020-05-05 17:04 . Update documentation
<!-- HTML header for doxygen 1.8.16-->
<!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">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.18"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>memory: Writing classes using a RawAllocator</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>
<link href="doxygen.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 style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">memory
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div id="main-nav">
<ul class="sm sm-dox" id="main-menu">
<li><a href="index.html">Main Page</a></li>
<li><a href="md_doc_tutorial.html">Tutorial</a></li>
<li><a href="namespacefoonathan_1_1memory.html">Index</a></li>
<li><a href="files.html">Files</a></li>
</ul>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.18 -->
</div><!-- top -->
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">Writing classes using a RawAllocator </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Compared to the requirements an <code>AllocatorAwareContainer</code> has to fulfill, it is very easy to use a <code>RawAllocator</code> in a container. There is no need to worry about comparing allocators, <code>select_on_container_copy_construction()</code>, <code>propagate_on_container_move_assignment</code> or the undefined behavior that sometimes happens if you <code>swap()</code> a container.</p>
<h1><a class="anchor" id="autotoc_md64"></a>
The Allocator version</h1>
<p>To demonstrate this, consider a simple <code>deep_copy_ptr</code>. <code>deep_copy_ptr</code> is like <code>std::unique_ptr</code> but provides a copy constructor which will perform a copy of the object. Unlike <code>std::unique_ptr</code> it will take a full-blown <code>Allocator</code>. Then it will be transformed to use a <a href="md_doc_concepts.html#concept_rawallocator">RawAllocator</a>. It is only meant to demonstrate the use of allocator classes and not to be a real use smart pointer class (it is pretty dumb, it copies the pointee on copy but invalidates on move...). So, this is it:</p>
<div class="fragment"><div class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T, <span class="keyword">class</span> Allocator = std::allocator&lt;T&gt;&gt;</div>
<div class="line"><span class="keyword">class </span>deep_copy_ptr</div>
<div class="line">: Allocator</div>
<div class="line">{</div>
<div class="line"> <span class="keyword">using</span> traits = std::allocator_traits&lt;Allocator&gt;;</div>
<div class="line"><span class="keyword">public</span>:</div>
<div class="line"> <span class="keyword">using</span> value_type = <span class="keyword">typename</span> traits::value_type;</div>
<div class="line"> <span class="keyword">using</span> allocator_type = Allocator;</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">explicit</span> deep_copy_ptr(<span class="keyword">const</span> allocator_type &amp;alloc = allocator_type{})</div>
<div class="line"> : allocator_type(alloc), ptr_(<span class="keyword">nullptr</span>) {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(value_type value, <span class="keyword">const</span> allocator_type &amp;alloc = allocator_type{})</div>
<div class="line"> : allocator_type(alloc), ptr_(create(*<span class="keyword">this</span>, std::move(value))) {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(<span class="keyword">const</span> deep_copy_ptr &amp;other)</div>
<div class="line"> : allocator_type(traits::select_on_container_copy_construction(other)),</div>
<div class="line"> ptr_(create(*this, *other))</div>
<div class="line"> {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(deep_copy_ptr &amp;&amp;other) noexcept</div>
<div class="line"> : allocator_type(std::move(other)),</div>
<div class="line"> ptr_(other.ptr_)</div>
<div class="line"> {</div>
<div class="line"> other.ptr_ = <span class="keyword">nullptr</span>;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> ~deep_copy_ptr() noexcept</div>
<div class="line"> {</div>
<div class="line"> destroy();</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr&amp; operator=(<span class="keyword">const</span> deep_copy_ptr &amp;other)</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">if</span> (traits::propagate_on_container_copy_assignment::value &amp;&amp; <span class="keyword">static_cast&lt;</span>Allocator&amp;<span class="keyword">&gt;</span>(*<span class="keyword">this</span>) != other)</div>
<div class="line"> {</div>
<div class="line"> allocator_type alloc(other);</div>
<div class="line"> <span class="keyword">auto</span> ptr = create(alloc, *other);</div>
<div class="line"> destroy();</div>
<div class="line"> </div>
<div class="line"> Allocator::operator=(std::move(alloc));</div>
<div class="line"> ptr_ = ptr;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">else</span></div>
<div class="line"> {</div>
<div class="line"> <span class="keyword">auto</span> ptr = create(*<span class="keyword">this</span>, *other);</div>
<div class="line"> destroy();</div>
<div class="line"> ptr_ = ptr;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr&amp; operator=(deep_copy_ptr &amp;&amp;other) noexcept(traits::propagate_on_container_move_assignment::value)</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">if</span> (traits::propagate_on_container_move_assignment::value &amp;&amp; <span class="keyword">static_cast&lt;</span>allocator_type&amp;<span class="keyword">&gt;</span>(*<span class="keyword">this</span>) != other)</div>
<div class="line"> {</div>
<div class="line"> allocator_type::operator=(std::move(other));</div>
<div class="line"> ptr_ = other.ptr_;</div>
<div class="line"> other.ptr_ = <span class="keyword">nullptr</span>;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<span class="keyword">static_cast&lt;</span>allocator_type&amp;<span class="keyword">&gt;</span>(*<span class="keyword">this</span>) == other)</div>
<div class="line"> {</div>
<div class="line"> ptr_ = other.ptr_;</div>
<div class="line"> other.ptr_ = <span class="keyword">nullptr</span>;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">else</span></div>
<div class="line"> {</div>
<div class="line"> <span class="keyword">auto</span> ptr = create(*<span class="keyword">this</span>, std::move(*other));</div>
<div class="line"> destroy();</div>
<div class="line"> ptr_ = ptr;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">friend</span> <span class="keywordtype">void</span> swap(deep_copy_ptr &amp;a, deep_copy_ptr &amp;b) noexcept</div>
<div class="line"> {</div>
<div class="line"> <span class="keyword">using</span> std::swap;</div>
<div class="line"> <span class="keywordflow">if</span> (traits::propagate_on_container_swap::value)</div>
<div class="line"> swap(<span class="keyword">static_cast&lt;</span>allocator_type&amp;<span class="keyword">&gt;</span>(a), <span class="keyword">static_cast&lt;</span>allocator_type&amp;<span class="keyword">&gt;</span>(b));</div>
<div class="line"> <span class="keywordflow">else</span></div>
<div class="line"> assert(<span class="keyword">static_cast&lt;</span>allocator_type&amp;<span class="keyword">&gt;</span>(a) == b);</div>
<div class="line"> swap(a.ptr_, b.ptr_);</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">explicit</span> <span class="keyword">operator</span> bool()<span class="keyword"> const</span></div>
<div class="line"><span class="keyword"> </span>{</div>
<div class="line"> <span class="keywordflow">return</span> !!ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> T&amp; operator*()</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">return</span> *ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">const</span> T&amp; operator*()<span class="keyword"> const</span></div>
<div class="line"><span class="keyword"> </span>{</div>
<div class="line"> <span class="keywordflow">return</span> *ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">typename</span> traits::pointer operator-&gt;()</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">return</span> ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">typename</span> traits::const_pointer operator-&gt;()<span class="keyword"> const</span></div>
<div class="line"><span class="keyword"> </span>{</div>
<div class="line"> <span class="keywordflow">return</span> ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"><span class="keyword">private</span>:</div>
<div class="line"> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ... Args&gt;</div>
<div class="line"> <span class="keyword">typename</span> traits::pointer create(allocator_type &amp;alloc, Args&amp;&amp;... args)</div>
<div class="line"> {</div>
<div class="line"> <span class="keyword">auto</span> ptr = traits::allocate(alloc, 1);</div>
<div class="line"> <span class="keywordflow">try</span></div>
<div class="line"> {</div>
<div class="line"> traits::construct(alloc, ptr, std::forward&lt;Args&gt;(args)...);</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">catch</span> (...)</div>
<div class="line"> {</div>
<div class="line"> traits::deallocate(alloc, ptr, 1);</div>
<div class="line"> <span class="keywordflow">throw</span>;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">return</span> ptr;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keywordtype">void</span> destroy() noexcept</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">if</span> (ptr_)</div>
<div class="line"> {</div>
<div class="line"> traits::destroy(*<span class="keyword">this</span>, ptr_);</div>
<div class="line"> traits::deallocate(*<span class="keyword">this</span>, ptr_, 1);</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">typename</span> traits::pointer ptr_;</div>
<div class="line">};</div>
</div><!-- fragment --><p>I am not going to go into much detail about this code, since it is just to demonstrate the complexity involved with the <code>Allocator</code> model. To note is the following:</p>
<ul>
<li>The <code>Allocator</code> is inherited privately to use the empty base optimization if it is an empty type. Also the allocator is <em>owned</em> by the pointer.</li>
<li>All access to the <code>Allocator</code> is done through the <code>std::allocator_traits</code> class. In addition, the actual <code>value_type</code> and pointer must be obtained from the traits class and its appropriate functions called to construct/destroy the object.</li>
<li>The copy constructor must call <code>traits::select_on_container_copy_construction()</code>, the move constructor can just move the allocator.</li>
<li>Copy and Move assignment and <code>swap()</code> only exchange the container if the appropriate <code>traits::propagate_on_container_XXX</code> is <code>true</code>. This involves a lot of complexity since if it is <code>false</code> - which is the default! - the old memory has to be deallocated on the old allocator and the new memory allocated on the new allocator if the allocators aren't <em>equal</em> - even for move! Also note the <code>assert()</code> in <code>swap()</code>: Since <code>swap()</code> must not throw, it cannot do the reallocation if the propagation is <code>false</code>.</li>
</ul>
<h1><a class="anchor" id="autotoc_md65"></a>
The RawAllocator version</h1>
<p>This is now a step-by-step review of the changes in the version that uses a <a href="md_doc_concepts.html#concept_rawallocator">RawAllocator</a>.</p>
<div class="fragment"><div class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T, <span class="keyword">class</span> RawAllocator = memory::default_allocator&gt;</div>
<div class="line"><span class="keyword">class </span>deep_copy_ptr</div>
<div class="line">: <a class="code" href="classfoonathan_1_1memory_1_1allocator__reference.html">memory::allocator_reference</a>&lt;RawAllocator&gt;</div>
</div><!-- fragment --><p>The default allocator is now <a class="el" href="group__allocator.html#ga10acce2d854fc42fea7306e511d9cd10">default_allocator</a>. Its actual type can be changed when building this library, but it is similar to <code>std::allocator</code>. Also the allocator is stored in a <a class="el" href="classfoonathan_1_1memory_1_1allocator__reference.html">allocator_reference</a>. This is recommended for three reasons:</p>
<p>a) Usage requirement: <code>RawAllocator</code> classes are only required to be moveable. <a class="el" href="classfoonathan_1_1memory_1_1allocator__reference.html">allocator_reference</a> is copyable, this allows copying the <code>deep_copy_ptr</code>.</p>
<p>b) Simplicity: <a class="el" href="classfoonathan_1_1memory_1_1allocator__reference.html">allocator_reference</a> provides the full interface without using the <a class="el" href="classfoonathan_1_1memory_1_1allocator__traits.html">allocator_traits</a> class. It has already done the wrapping for you.</p>
<p>c) Ownership: The <code>deep_copy_ptr</code> doesn't <em>own</em> the allocator, it can be shared with other classes or objects. This is a useful semantic change which is often required anyway. <em>Note: The passed allocator object must now live as long as the container object, except for stateless allocators!</em></p>
<p>The reference is inherited too for the same reason: It is empty for stateless allocators. They are constructed on-the-fly. This also means that they can be passed in as a temporary. For stateful allocators it stores a pointer. The user has to ensure that the referenced allocator object then outlives the <code>deep_copy_ptr</code> object.</p>
<div class="fragment"><div class="line"> <span class="keyword">using</span> allocator_ref = <a class="code" href="classfoonathan_1_1memory_1_1allocator__reference.html">memory::allocator_reference&lt;RawAllocator&gt;</a>;</div>
<div class="line"><span class="keyword">public</span>:</div>
<div class="line"> <span class="keyword">using</span> value_type = T;</div>
<div class="line"> <span class="keyword">using</span> allocator_type = <span class="keyword">typename</span> allocator_ref::allocator_type;</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">explicit</span> deep_copy_ptr(allocator_ref alloc = allocator_type{})</div>
<div class="line"> : allocator_ref(alloc), ptr_(<span class="keyword">nullptr</span>) {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(value_type value, allocator_ref alloc = allocator_type{})</div>
<div class="line"> : allocator_ref(alloc), ptr_(create(std::move(value))) {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(<span class="keyword">const</span> deep_copy_ptr &amp;other)</div>
<div class="line"> : allocator_ref(other),</div>
<div class="line"> ptr_(create(*other))</div>
<div class="line"> {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(deep_copy_ptr &amp;&amp;other) noexcept</div>
<div class="line"> : allocator_ref(std::move(other)),</div>
<div class="line"> ptr_(other.ptr_)</div>
<div class="line"> {</div>
<div class="line"> other.ptr_ = <span class="keyword">nullptr</span>;</div>
<div class="line"> }</div>
</div><!-- fragment --><p>Not much changed with the typedefs: The traits typedef can be removed, instead there is one for the reference. The <code>value_type</code> is now the template parameter directly but the <code>allocator_type</code> is defined in the reference through the traits. This allows rebinding to support <code>Allocator</code> classes.</p>
<p>The constructors now take an <code>allocator_ref</code> instead of the <code>allocator_type</code> directly but otherwise are left unchanged. Note that the assignment of a default constructed <code>allocator_type</code> only compiles for stateless allocators, since the reference does not actual store a reference to them. For stateful it wil not compile. Since only the reference is copied and not the allocator there is no need for a special treatment in copying. <code>create()</code> no longer needs to take an allocator as reference so this argument can be omitted.</p>
<p>The destructor has not changed at all, it still only calls the helper function <code>destroy()</code>.</p>
<p>Copy and move assignment operators can now use the copy(move)-and-swap-idiom and do not need to worry about all the propagation stuff since the allocator is held by reference. Same goes for <code>swap()</code> which just swaps the reference and pointer.</p>
<p>The accessor functions have not changed, except that the actual pointer type is now simply <code>T*</code> and no longer defined in the traits.</p>
<div class="fragment"><div class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> ... Args&gt;</div>
<div class="line">T* create(Args&amp;&amp;... args)</div>
<div class="line">{</div>
<div class="line"> <span class="keyword">auto</span> storage = this-&gt;allocate_node(<span class="keyword">sizeof</span>(T), <span class="keyword">alignof</span>(T));</div>
<div class="line"> <span class="keywordflow">try</span></div>
<div class="line"> {</div>
<div class="line"> ::new(storage) T(std::forward&lt;Args&gt;(args)...);</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">catch</span> (...)</div>
<div class="line"> {</div>
<div class="line"> this-&gt;deallocate_node(storage, <span class="keyword">sizeof</span>(T), <span class="keyword">alignof</span>(T));</div>
<div class="line"> <span class="keywordflow">throw</span>;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">return</span> <span class="keyword">static_cast&lt;</span>T*<span class="keyword">&gt;</span>(storage);</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> destroy() noexcept</div>
<div class="line">{</div>
<div class="line"> <span class="keywordflow">if</span> (ptr_)</div>
<div class="line"> {</div>
<div class="line"> ptr_-&gt;~T();</div>
<div class="line"> this-&gt;deallocate_node(ptr_, <span class="keyword">sizeof</span>(T), <span class="keyword">alignof</span>(T));</div>
<div class="line"> }</div>
<div class="line">}</div>
</div><!-- fragment --><p>The helper functions <code>create()</code> and <code>destroy()</code> no only perform the (de-)allocation through the allocator, constructor/destructor call is done manually. Note that the pointer returned by <code>allocate_node()</code> is <code>void*</code> and that you have to explicitly specify <code>this-&gt;</code> due to the template name lookup rules.</p>
<p>This is now the full <code>RawAllocator</code> version of <code>deep_copy_ptr</code>:</p>
<div class="fragment"><div class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T, <span class="keyword">class</span> RawAllocator = memory::default_allocator&gt;</div>
<div class="line"><span class="keyword">class </span>deep_copy_ptr</div>
<div class="line">: <a class="code" href="classfoonathan_1_1memory_1_1allocator__reference.html">memory::allocator_reference</a>&lt;RawAllocator&gt;</div>
<div class="line">{</div>
<div class="line"> <span class="keyword">using</span> allocator_ref = <a class="code" href="classfoonathan_1_1memory_1_1allocator__reference.html">memory::allocator_reference&lt;RawAllocator&gt;</a>;</div>
<div class="line"><span class="keyword">public</span>:</div>
<div class="line"> <span class="keyword">using</span> value_type = T;</div>
<div class="line"> <span class="keyword">using</span> allocator_type = <span class="keyword">typename</span> allocator_ref::allocator_type;</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">explicit</span> deep_copy_ptr(allocator_ref alloc = allocator_type{})</div>
<div class="line"> : allocator_ref(alloc), ptr_(<span class="keyword">nullptr</span>) {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(value_type value, allocator_ref alloc = allocator_type{})</div>
<div class="line"> : allocator_ref(alloc), ptr_(create(std::move(value))) {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(<span class="keyword">const</span> deep_copy_ptr &amp;other)</div>
<div class="line"> : allocator_ref(other),</div>
<div class="line"> ptr_(create(*other))</div>
<div class="line"> {}</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr(deep_copy_ptr &amp;&amp;other) noexcept</div>
<div class="line"> : allocator_ref(std::move(other)),</div>
<div class="line"> ptr_(other.ptr_)</div>
<div class="line"> {</div>
<div class="line"> other.ptr_ = <span class="keyword">nullptr</span>;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> ~deep_copy_ptr() noexcept</div>
<div class="line"> {</div>
<div class="line"> destroy();</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr&amp; <a class="code" href="classfoonathan_1_1memory_1_1allocator__storage.html#a6b05c498eb284ca3fa56b1a4a746cceb">operator=</a>(<span class="keyword">const</span> deep_copy_ptr &amp;other)</div>
<div class="line"> {</div>
<div class="line"> deep_copy_ptr tmp(other);</div>
<div class="line"> swap(*<span class="keyword">this</span>, tmp);</div>
<div class="line"> <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> deep_copy_ptr&amp; <a class="code" href="classfoonathan_1_1memory_1_1allocator__storage.html#a6b05c498eb284ca3fa56b1a4a746cceb">operator=</a>(deep_copy_ptr &amp;&amp;other) noexcept</div>
<div class="line"> {</div>
<div class="line"> deep_copy_ptr tmp(std::move(other));</div>
<div class="line"> swap(*<span class="keyword">this</span>, tmp);</div>
<div class="line"> <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">friend</span> <span class="keywordtype">void</span> swap(deep_copy_ptr &amp;a, deep_copy_ptr &amp;b) noexcept</div>
<div class="line"> {</div>
<div class="line"> <span class="keyword">using</span> std::swap;</div>
<div class="line"> swap(<span class="keyword">static_cast&lt;</span>allocator_ref&amp;<span class="keyword">&gt;</span>(a), <span class="keyword">static_cast&lt;</span>allocator_ref&amp;<span class="keyword">&gt;</span>(b));</div>
<div class="line"> swap(a.ptr_, b.ptr_);</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">explicit</span> <span class="keyword">operator</span> bool()<span class="keyword"> const</span></div>
<div class="line"><span class="keyword"> </span>{</div>
<div class="line"> <span class="keywordflow">return</span> !!ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> T&amp; operator*()</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">return</span> *ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">const</span> T&amp; operator*()<span class="keyword"> const</span></div>
<div class="line"><span class="keyword"> </span>{</div>
<div class="line"> <span class="keywordflow">return</span> *ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> T* operator-&gt;()</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">return</span> ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keyword">const</span> T* operator-&gt;()<span class="keyword"> const</span></div>
<div class="line"><span class="keyword"> </span>{</div>
<div class="line"> <span class="keywordflow">return</span> ptr_;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"><span class="keyword">private</span>:</div>
<div class="line"> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ... Args&gt;</div>
<div class="line"> T* create(Args&amp;&amp;... args)</div>
<div class="line"> {</div>
<div class="line"> <span class="keyword">auto</span> storage = this-&gt;<a class="code" href="classfoonathan_1_1memory_1_1allocator__storage.html#aa0774f4f3278b78aab48272657c8da07">allocate_node</a>(<span class="keyword">sizeof</span>(T), <span class="keyword">alignof</span>(T));</div>
<div class="line"> <span class="keywordflow">try</span></div>
<div class="line"> {</div>
<div class="line"> ::new(storage) T(std::forward&lt;Args&gt;(args)...);</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">catch</span> (...)</div>
<div class="line"> {</div>
<div class="line"> this-&gt;<a class="code" href="classfoonathan_1_1memory_1_1allocator__storage.html#af39c4c8201ed3a86738d5571239e19db">deallocate_node</a>(storage, <span class="keyword">sizeof</span>(T), <span class="keyword">alignof</span>(T));</div>
<div class="line"> <span class="keywordflow">throw</span>;</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">return</span> <span class="keyword">static_cast&lt;</span>T*<span class="keyword">&gt;</span>(storage);</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keywordtype">void</span> destroy() noexcept</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">if</span> (ptr_)</div>
<div class="line"> {</div>
<div class="line"> ptr_-&gt;~T();</div>
<div class="line"> this-&gt;<a class="code" href="classfoonathan_1_1memory_1_1allocator__storage.html#af39c4c8201ed3a86738d5571239e19db">deallocate_node</a>(ptr_, <span class="keyword">sizeof</span>(T), <span class="keyword">alignof</span>(T));</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> T *ptr_;</div>
<div class="line">};</div>
</div><!-- fragment --> </div></div><!-- contents -->
</div><!-- PageDoc -->
<div class="ttc" id="aclassfoonathan_1_1memory_1_1allocator__storage_html_a6b05c498eb284ca3fa56b1a4a746cceb"><div class="ttname"><a href="classfoonathan_1_1memory_1_1allocator__storage.html#a6b05c498eb284ca3fa56b1a4a746cceb">foonathan::memory::allocator_storage&lt; reference_storage&lt; RawAllocator &gt;, no_mutex &gt;::operator=</a></div><div class="ttdeci">allocator_storage &amp; operator=(allocator_storage &amp;&amp;other) noexcept</div><div class="ttdef"><b>Definition:</b> allocator_storage.hpp:156</div></div>
<div class="ttc" id="aclassfoonathan_1_1memory_1_1allocator__reference_html"><div class="ttname"><a href="classfoonathan_1_1memory_1_1allocator__reference.html">foonathan::memory::allocator_reference</a></div><div class="ttdoc">An alias template for allocator_storage using the reference_storage policy.</div><div class="ttdef"><b>Definition:</b> allocator_storage.hpp:891</div></div>
<div class="ttc" id="aclassfoonathan_1_1memory_1_1allocator__storage_html_af39c4c8201ed3a86738d5571239e19db"><div class="ttname"><a href="classfoonathan_1_1memory_1_1allocator__storage.html#af39c4c8201ed3a86738d5571239e19db">foonathan::memory::allocator_storage&lt; reference_storage&lt; RawAllocator &gt;, no_mutex &gt;::deallocate_node</a></div><div class="ttdeci">void deallocate_node(void *ptr, std::size_t size, std::size_t alignment) noexcept</div><div class="ttdef"><b>Definition:</b> allocator_storage.hpp:189</div></div>
<div class="ttc" id="aclassfoonathan_1_1memory_1_1allocator__storage_html_aa0774f4f3278b78aab48272657c8da07"><div class="ttname"><a href="classfoonathan_1_1memory_1_1allocator__storage.html#aa0774f4f3278b78aab48272657c8da07">foonathan::memory::allocator_storage&lt; reference_storage&lt; RawAllocator &gt;, no_mutex &gt;::allocate_node</a></div><div class="ttdeci">void * allocate_node(std::size_t size, std::size_t alignment)</div><div class="ttdef"><b>Definition:</b> allocator_storage.hpp:175</div></div>
<!-- HTML footer for doxygen 1.8.16-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.18
</small></address>
</body>
</html>
1
https://gitee.com/mobangjack/memory.git
git@gitee.com:mobangjack/memory.git
mobangjack
memory
memory
gh-pages

搜索帮助