Derive empty base optimization from rebound allocator

This commit is contained in:
Glen Fernandes
2014-02-18 00:14:31 -08:00
parent 5f1d4eae4f
commit 38cb523713
4 changed files with 79 additions and 70 deletions

View File

@ -28,6 +28,12 @@ namespace boost {
size(size_ * array_total<T>::size) {
}
template<class U>
as_size_base(const as_size_base<T[], U>& other)
: A(other),
size(other.size) {
}
std::size_t size;
};
@ -38,6 +44,11 @@ namespace boost {
: A(allocator) {
}
template<class U>
as_size_base(const as_size_base<T[N], U>& other)
: A(other) {
}
enum {
size = array_total<T[N]>::size
};
@ -58,9 +69,13 @@ namespace boost {
template<class T, class R, class A, class Y = char>
class as_allocator
: as_size_base<T, A> {
using as_size_base<T, A>::size;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
: as_size_base<T, typename std::allocator_traits<A>::
template rebind_alloc<Y> > {
#else
: as_size_base<T, typename A::
template rebind<Y>::other> {
#endif
template<class T_, class R_, class A_, class Y_>
friend class as_allocator;
@ -78,6 +93,8 @@ namespace boost {
typedef typename A::template rebind<char>::other CA;
#endif
using as_size_base<T, YA>::size;
public:
typedef typename array_base<T>::type type;
@ -105,36 +122,30 @@ namespace boost {
};
as_allocator(const A& allocator, type** result)
: as_size_base<T, A>(allocator),
: as_size_base<T, YA>(allocator),
data(result) {
}
as_allocator(const A& allocator, std::size_t size_,
type** result)
: as_size_base<T, A>(allocator, size_),
: as_size_base<T, YA>(allocator, size_),
data(result) {
}
template<class U>
as_allocator(const as_allocator<T, R, A, U>& other)
: as_size_base<T, A>(other),
: as_size_base<T, YA>(other),
data(other.data) {
}
pointer address(reference value) const {
YA ya(*this);
return ya.address(value);
}
const_pointer address(const_reference value) const {
YA ya(*this);
return ya.address(value);
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
size_type max_size() const {
YA ya(*this);
return ya.max_size();
return YT::max_size(*this);
}
#else
using YA::address;
using YA::max_size;
#endif
pointer allocate(size_type count, const void* value = 0) {
enum {
@ -171,21 +182,19 @@ namespace boost {
template<class U>
void construct(U* memory, const_reference value) {
YA ya(*this);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::construct(ya, memory, value);
YT::construct(*this, memory, value);
#else
ya.construct(memory, value);
YA::construct(memory, value);
#endif
}
template<class U>
void destroy(U* memory) {
YA ya(*this);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::destroy(ya, memory);
YT::destroy(*this, memory);
#else
ya.destroy(memory);
YA::destroy(memory);
#endif
}
@ -194,8 +203,7 @@ namespace boost {
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<class U, class... Args>
void construct(U* memory, Args&&... args) {
YA ya(*this);
YT::construct(ya, memory, std::forward<Args>(args)...);
YT::construct(*this, memory, std::forward<Args>(args)...);
}
#endif
@ -223,8 +231,7 @@ namespace boost {
private:
void free(ms_init_tag) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
const A& a1(*this);
as_destroy(a1, data.object, size);
as_destroy(*this, data.object, size);
#else
ms_destroy(data.object, size);
#endif
@ -295,6 +302,7 @@ namespace boost {
data(other.data) {
}
#if defined(BOOST_NO_CXX11_ALLOCATOR)
pointer address(reference value) const {
return &value;
}
@ -302,6 +310,7 @@ namespace boost {
const_pointer address(const_reference value) const {
return &value;
}
#endif
size_type max_size() const {
enum {

View File

@ -20,7 +20,7 @@ namespace boost {
typedef ms_in_allocator_tag D;
typedef sp_counted_impl_pda<P, D, A> Y;
public:
sp_counted_impl_pda(P, const D&, const A& allocator_)
sp_counted_impl_pda(P, D, const A& allocator_)
: allocator(allocator_) {
}

View File

@ -30,50 +30,50 @@
user-supplied allocator, allowing finer control.</p>
<h2><a name="synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename U&gt; // U is T[]
template&lt;class U&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size);
template&lt;typename U, typename A&gt; // U is T[]
template&lt;class U, class A&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, size_t size);
template&lt;typename U&gt; // U is T[N]
template&lt;class U&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>();
template&lt;typename U, typename A&gt; // U is T[N]
template&lt;class U, class A&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator);
template&lt;typename U&gt; // U is T[]
template&lt;class U&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size, const T&amp; value);
template&lt;typename U, typename A&gt; // U is T[]
template&lt;class U, class A&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, size_t size, const T&amp; value);
template&lt;typename U&gt; // U is T[N]
template&lt;class U&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(const T&amp; value);
template&lt;typename U, typename A&gt; // U is T[N]
template&lt;class U, class A&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, const T&amp; value);
template&lt;typename U&gt; // U is T[]
template&lt;class U&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared_noinit</a>(size_t size);
template&lt;typename U, typename A&gt; // U is T[]
template&lt;class U, class A&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared_noinit</a>(const A&amp; allocator, size_t size);
template&lt;typename U&gt; // U is T[N]
template&lt;class U&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">make_shared_noinit</a>();
template&lt;typename U, typename A&gt; // U is T[N]
template&lt;class U, class A&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared_noinit</a>(const A&amp; allocator);
}</pre>
<h2><a name="common">Common Requirements</a></h2>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
shared_ptr&lt;U&gt; make_shared(<em>args</em>);
template&lt;typename U, typename A&gt;
template&lt;class U, class A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, <em>args</em>);
template&lt;typename U&gt;
template&lt;class U&gt;
shared_ptr&lt;U&gt; make_shared_noinit(<em>args</em>);
template&lt;typename U, typename A&gt;
template&lt;class U, class A&gt;
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator, <em>args</em>);</pre>
<blockquote>
<p><b>Requires:</b> <code>U</code> is of the form <code>T[]</code> or
@ -157,9 +157,9 @@ template&lt;typename U, typename A&gt;
structures such as the reference counts.</p>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
shared_ptr&lt;U&gt; make_shared(size_t size);
template&lt;typename U, typename A&gt;
template&lt;class U, class A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to a value-initialized
@ -172,9 +172,9 @@ template&lt;typename U, typename A&gt;
boost::shared_ptr&lt;int[][2]&gt; a2 = boost::make_shared&lt;int[][2]&gt;(size);</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
shared_ptr&lt;U&gt; make_shared();
template&lt;typename U, typename A&gt;
template&lt;class U, class A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to a value-initialized
@ -187,9 +187,9 @@ template&lt;typename U, typename A&gt;
boost::shared_ptr&lt;int[4][2]&gt; a2 = boost::make_shared&lt;int[4][2]&gt;();</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
shared_ptr&lt;U&gt; make_shared(size_t size, const T&amp; value);
template&lt;typename U, typename A&gt;
template&lt;class U, class A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size, const T&amp; value);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to an object of type
@ -203,9 +203,9 @@ template&lt;typename U, typename A&gt;
boost::shared_ptr&lt;int[][2]&gt; a2 = boost::make_shared&lt;int[][2]&gt;(size, {1, 2});</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
shared_ptr&lt;U&gt; make_shared(const T&amp; value);
template&lt;typename U, typename A&gt;
template&lt;class U, class A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, const T&amp; value);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to an object of type
@ -219,9 +219,9 @@ template&lt;typename U, typename A&gt;
boost::shared_ptr&lt;int[4][2]&gt; a2 = boost::make_shared&lt;int[4][2]&gt;({1, 2});</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
shared_ptr&lt;U&gt; make_shared_noinit(size_t size);
template&lt;typename U, typename A&gt;
template&lt;class U, class A&gt;
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator, size_t size);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to a default-initialized
@ -234,9 +234,9 @@ template&lt;typename U, typename A&gt;
boost::shared_ptr&lt;int[][2]&gt; a2 = boost::make_shared_noinit&lt;int[][2]&gt;(size);</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
shared_ptr&lt;U&gt; make_shared_noinit();
template&lt;typename U, typename A&gt;
template&lt;class U, class A&gt;
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to a default-initialized

View File

@ -18,30 +18,30 @@
<code>unique_ptr</code> objects.</p>
<h2><a name="synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename U&gt; // U is not array
template&lt;class U&gt; // U is not array
unique_ptr&lt;U&gt; <a href="#functions">make_unique</a>();
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template&lt;typename U, typename... Args&gt; // U is not array
template&lt;class U, class... Args&gt; // U is not array
unique_ptr&lt;U&gt; <a href="#functions">make_unique</a>(Args&amp;&amp;... args);
#endif
template&lt;typename U&gt; // U is not array
template&lt;class U&gt; // U is not array
unique_ptr&lt;U&gt; <a href="#functions">make_unique</a>(U&amp;&amp; value);
template&lt;typename U&gt; // U is T[]
template&lt;class U&gt; // U is T[]
unique_ptr&lt;U&gt; <a href="#functions">make_unique</a>(size_t size);
template&lt;typename U&gt; // U is not array
template&lt;class U&gt; // U is not array
unique_ptr&lt;U&gt; <a href="#functions">make_unique_noinit</a>();
template&lt;typename U&gt; // U is T[]
template&lt;class U&gt; // U is T[]
unique_ptr&lt;U&gt; <a href="#functions">make_unique_noinit</a>(size_t size);
}</pre>
<h2><a name="common">Common Requirements</a></h2>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
unique_ptr&lt;U&gt; make_unique(<em>args</em>);
template&lt;typename U&gt;
template&lt;class U&gt;
unique_ptr&lt;U&gt; make_unique_noinit(<em>args</em>);</pre>
<blockquote>
<p><b>Effects:</b> Allocates memory for an object of type <code>U</code>
@ -73,7 +73,7 @@ template&lt;typename U&gt;
</blockquote>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<pre>template&lt;typename U, typename... Args&gt;
<pre>template&lt;class U, class... Args&gt;
unique_ptr&lt;U&gt; make_unique(Args&amp;&amp;... args);</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to an object of type <code>U</code>,
@ -86,7 +86,7 @@ unique_ptr&lt;U&gt; make_unique(Args&amp;&amp;... args);</pre>
unique_ptr&lt;point&gt; p2 = boost::make_unique&lt;point&gt;(x, y);</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
unique_ptr&lt;U&gt; make_unique(U&amp;&amp; value);</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to an object of type <code>U</code>,
@ -99,7 +99,7 @@ unique_ptr&lt;U&gt; make_unique(U&amp;&amp; value);</pre>
unique_ptr&lt;point&gt; p2 = boost::make_unique&lt;point&gt;({-10, 25});</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
unique_ptr&lt;U&gt; make_unique(size_t size);</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to a value-initialized object of type
@ -112,7 +112,7 @@ unique_ptr&lt;U&gt; make_unique(size_t size);</pre>
unique_ptr&lt;int[][2]&gt; p2 = boost::make_unique&lt;int[][2]&gt;(2);</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
unique_ptr&lt;U&gt; make_unique_noinit();</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to a default-initialized object of
@ -125,7 +125,7 @@ unique_ptr&lt;U&gt; make_unique_noinit();</pre>
unique_ptr&lt;point&gt; p2 = boost::make_unique_noinit&lt;point&gt;();</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
<pre>template&lt;class U&gt;
unique_ptr&lt;U&gt; make_unique_noinit(size_t size);</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to a default-initialized object of