Merge branch 'develop'

This commit is contained in:
Daniel James
2016-10-30 23:17:15 +00:00
20 changed files with 1893 additions and 393 deletions

View File

@ -293,5 +293,8 @@ C++11 support has resulted in some breaking changes:
objects wouldn't match the container elements, so elements might be in the
wrong bucket and equivalent elements would be incorrectly handled.
* Various reference documentation improvements.
* Better allocator support ([ticket 12459]).
* Make the no argument constructors implicit.
* Implement missing allocator aware constructors.
[endsect]

View File

@ -189,10 +189,22 @@ EOL;
<para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description>
</typedef>
<constructor>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor specifiers="explicit">
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
@ -246,7 +258,12 @@ EOL;
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
@ -310,6 +327,168 @@ EOL;
<para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
</description>
</constructor>
<constructor>
<parameter name="x">
<paramtype><?php echo $name; ?> &amp;&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>Allocator const&amp;</paramtype>
</parameter>
<description>
<para>Construct a container moving <code>x</code>'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate <code>a</code>.</para>
</description>
<notes>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move insertable.
</para>
</requires>
</constructor>
<constructor>
<parameter name="il">
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
<default>hasher()</default>
</parameter>
<parameter name="eq">
<paramtype>key_equal const&amp;</paramtype>
<default>key_equal()</default>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from <code>il</code> into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default hash function and key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>hasher</code> and <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>a</code> as the allocator, with the
default hash function and key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>hasher</code>, <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>a</code> as the allocator, with the
default key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<destructor>
<notes>
<para>The destructor is applied to every element, and all memory is deallocated</para>

View File

@ -130,10 +130,22 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description>
</typedef>
<constructor>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor specifiers="explicit">
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
@ -187,7 +199,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
@ -251,6 +268,168 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
</description>
</constructor>
<constructor>
<parameter name="x">
<paramtype>unordered_set &amp;&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>Allocator const&amp;</paramtype>
</parameter>
<description>
<para>Construct a container moving <code>x</code>'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate <code>a</code>.</para>
</description>
<notes>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move insertable.
</para>
</requires>
</constructor>
<constructor>
<parameter name="il">
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
<default>hasher()</default>
</parameter>
<parameter name="eq">
<paramtype>key_equal const&amp;</paramtype>
<default>key_equal()</default>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from <code>il</code> into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default hash function and key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>hasher</code> and <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>a</code> as the allocator, with the
default hash function and key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>hasher</code>, <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>a</code> as the allocator, with the
default key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<destructor>
<notes>
<para>The destructor is applied to every element, and all memory is deallocated</para>
@ -1204,10 +1383,22 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description>
</typedef>
<constructor>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor specifiers="explicit">
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
@ -1261,7 +1452,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
@ -1325,6 +1521,168 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
</description>
</constructor>
<constructor>
<parameter name="x">
<paramtype>unordered_multiset &amp;&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>Allocator const&amp;</paramtype>
</parameter>
<description>
<para>Construct a container moving <code>x</code>'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate <code>a</code>.</para>
</description>
<notes>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move insertable.
</para>
</requires>
</constructor>
<constructor>
<parameter name="il">
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
<default>hasher()</default>
</parameter>
<parameter name="eq">
<paramtype>key_equal const&amp;</paramtype>
<default>key_equal()</default>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from <code>il</code> into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default hash function and key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>hasher</code> and <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>a</code> as the allocator, with the
default hash function and key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>hasher</code>, <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>a</code> as the allocator, with the
default key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<destructor>
<notes>
<para>The destructor is applied to every element, and all memory is deallocated</para>
@ -2287,6 +2645,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description>
</typedef>
<constructor>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor specifiers="explicit">
<parameter name="n">
<paramtype>size_type</paramtype>
@ -2344,7 +2715,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
@ -2408,6 +2784,167 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
</description>
</constructor>
<constructor>
<parameter name="x">
<paramtype>unordered_map &amp;&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>Allocator const&amp;</paramtype>
</parameter>
<description>
<para>Construct a container moving <code>x</code>'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate <code>a</code>.</para>
</description>
<notes>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move insertable.
</para>
</requires>
</constructor>
<constructor>
<parameter name="il">
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
<default>hasher()</default>
</parameter>
<parameter name="eq">
<paramtype>key_equal const&amp;</paramtype>
<default>key_equal()</default>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from <code>il</code> into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default hash function and key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>hasher</code> and <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>a</code> as the allocator, with the
default hash function and key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>hasher</code>, <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>a</code> as the allocator, with the
default key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<destructor>
<notes>
<para>The destructor is applied to every element, and all memory is deallocated</para>
@ -3408,10 +3945,22 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description>
</typedef>
<constructor>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor specifiers="explicit">
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
@ -3465,7 +4014,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
@ -3529,6 +4083,168 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Constructs an container, copying <code>x</code>'s contained elements, hash function, predicate, maximum load factor, but using allocator <code>a</code>.</para>
</description>
</constructor>
<constructor>
<parameter name="x">
<paramtype>unordered_multimap &amp;&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>Allocator const&amp;</paramtype>
</parameter>
<description>
<para>Construct a container moving <code>x</code>'s contained elements, and having the hash function, predicate and maximum load factor, but using allocate <code>a</code>.</para>
</description>
<notes>
<para>This is implemented using Boost.Move.</para>
</notes>
<requires>
<para>
<code>value_type</code> is move insertable.
</para>
</requires>
</constructor>
<constructor>
<parameter name="il">
<paramtype>initializer_list&lt;value_type&gt;</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
<default>hasher()</default>
</parameter>
<parameter name="eq">
<paramtype>key_equal const&amp;</paramtype>
<default>key_equal()</default>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
<default>allocator_type()</default>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>eq</code> as the key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0
and inserts the elements from <code>il</code> into it.
</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default hash function and key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>hasher</code> and <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<postconditions>
<code><methodname>size</methodname>() == 0</code>
</postconditions>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
the default key equality predicate,
<code>a</code> as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>a</code> as the allocator, with the
default hash function and key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>hasher</code>, <code>key_equal</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
<template-type-parameter name="InputIterator">
</template-type-parameter>
</template>
<parameter name="f">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="l">
<paramtype>InputIterator</paramtype>
</parameter>
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<parameter name="hf">
<paramtype>hasher const&amp;</paramtype>
</parameter>
<parameter name="a">
<paramtype>allocator_type const&amp;</paramtype>
</parameter>
<description>
<para>Constructs an empty container with at least <code>n</code> buckets,
using <code>hf</code> as the hash function,
<code>a</code> as the allocator, with the
default key equality predicate
and a maximum load factor of 1.0
and inserts the elements from [f, l) into it.
</para>
</description>
<requires>
<para><code>key_equal</code> needs to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<destructor>
<notes>
<para>The destructor is applied to every element, and all memory is deallocated</para>

View File

@ -88,6 +88,16 @@ namespace boost { namespace unordered { namespace detail {
convert_from_anything(T const&);
};
namespace func {
// This is a bit nasty, when constructing the individual members
// of a std::pair, need to cast away 'const'. For modern compilers,
// should be able to use std::piecewise_construct instead.
template <typename T> T* const_cast_pointer(T* x) { return x; }
template <typename T> T* const_cast_pointer(T const* x) {
return const_cast<T*>(x);
}
}
////////////////////////////////////////////////////////////////////////////
// emplace_args
//
@ -237,9 +247,8 @@ BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
// 2 = boost::container::allocator_traits
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
# if !defined(BOOST_NO_CXX11_ALLOCATOR)
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
# elif defined(BOOST_MSVC)
# if BOOST_MSVC < 1400
// Use container's allocator_traits for older versions of Visual
@ -316,7 +325,7 @@ namespace boost { namespace unordered { namespace detail {
#if !defined(BOOST_NO_SFINAE_EXPR)
template <typename T, unsigned int> struct expr_test;
template <typename T, long unsigned int> struct expr_test;
template <typename T> struct expr_test<T, sizeof(char)> : T {};
# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
@ -412,11 +421,69 @@ namespace boost { namespace unordered { namespace detail {
namespace boost { namespace unordered { namespace detail {
// TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
template <typename Alloc, typename T>
struct rebind_alloc;
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <template<typename, typename...> class Alloc,
typename U, typename T, typename... Args>
struct rebind_alloc<Alloc<U, Args...>, T>
{
typedef Alloc<T, Args...> type;
};
#else
template <
template<typename> class Alloc,
typename U, typename T>
struct rebind_alloc<Alloc<U>, T>
{
typedef Alloc<T> type;
};
template <
template<typename, typename> class Alloc,
typename U, typename T,
typename A0>
struct rebind_alloc<Alloc<U, A0>, T>
{
typedef Alloc<T, A0> type;
};
template <
template<typename, typename, typename> class Alloc,
typename U, typename T,
typename A0, typename A1>
struct rebind_alloc<Alloc<U, A0, A1>, T>
{
typedef Alloc<T, A0, A1> type;
};
#endif
template <typename Alloc, typename T>
struct rebind_wrap
{
typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other type;
template <typename X>
static choice1::type test(choice1,
typename X::BOOST_NESTED_TEMPLATE rebind<T>::other* = 0);
template <typename X>
static choice2::type test(choice2, void* = 0);
enum { value = (1 == sizeof(test<Alloc>(choose()))) };
struct fallback {
template <typename U>
struct rebind {
typedef typename rebind_alloc<Alloc, T>::type other;
};
};
typedef typename boost::detail::if_true<value>::
BOOST_NESTED_TEMPLATE then<Alloc, fallback>
::type::BOOST_NESTED_TEMPLATE rebind<T>::other type;
};
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
@ -606,7 +673,14 @@ namespace boost { namespace unordered { namespace detail {
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
size_type;
// TODO: rebind_alloc and rebind_traits
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <typename T>
using rebind_alloc = typename rebind_wrap<Alloc, T>::type;
template <typename T>
using rebind_traits =
boost::unordered::detail::allocator_traits<rebind_alloc<T> >;
#endif
static pointer allocate(Alloc& a, size_type n)
{ return a.allocate(n); }
@ -639,7 +713,7 @@ namespace boost { namespace unordered { namespace detail {
::value>::type
construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
{
new ((void*) p) T(boost::forward<Args>(x)...);
new (static_cast<void*>(p)) T(boost::forward<Args>(x)...);
}
template <typename T>
@ -673,7 +747,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_construct<Alloc, T>::value>::type
construct(Alloc&, T* p, T const& x)
{
new ((void*) p) T(x);
new (static_cast<void*>(p)) T(x);
}
template <typename T>
@ -715,7 +789,7 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same<T, value_type>::value,
void*>::type = 0)
{
new ((void*) p) T(x);
new (static_cast<void*>(p)) T(x);
}
template <typename T>
@ -843,7 +917,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
}
template <typename Alloc, typename T>
inline void destroy_value_impl(Alloc& alloc, T* x) {
inline void call_destroy(Alloc& alloc, T* x) {
boost::unordered::detail::allocator_traits<Alloc>::destroy(alloc, x);
}
@ -858,7 +932,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
}
template <typename Alloc, typename T>
inline void destroy_value_impl(Alloc&, T* x) {
inline void call_destroy(Alloc&, T* x) {
boost::unordered::detail::func::destroy(x);
}
@ -880,7 +954,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
}
template <typename Alloc, typename T>
inline void destroy_value_impl(Alloc&, T* x) {
inline void call_destroy(Alloc&, T* x) {
boost::unordered::detail::func::destroy(x);
}
@ -1021,7 +1095,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
// For the standard pair constructor.
template <typename Alloc, typename T, typename... Args>
inline void construct_value_impl(Alloc& alloc, T* address,
inline void construct_from_args(Alloc& alloc, T* address,
BOOST_FWD_REF(Args)... args)
{
boost::unordered::detail::func::call_construct(alloc,
@ -1036,32 +1110,36 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
template <typename Alloc, typename A, typename B,
typename A0, typename A1, typename A2>
inline typename enable_if<use_piecewise<A0>, void>::type
construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
construct_from_args(Alloc& alloc, std::pair<A, B>* address,
BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::addressof(address->first), boost::forward<A1>(a1));
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->first)),
boost::forward<A1>(a1));
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::addressof(address->second), boost::forward<A2>(a2));
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->second)),
boost::forward<A2>(a2));
}
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
////////////////////////////////////////////////////////////////////////////////
// Construct from emplace_args
////////////////////////////////////////////////////////////////////////////
// Construct from emplace_args
// Explicitly write out first three overloads for the sake of sane
// error messages.
template <typename Alloc, typename T, typename A0>
inline void construct_value_impl(Alloc&, T* address,
inline void construct_from_args(Alloc&, T* address,
emplace_args1<A0> const& args)
{
new((void*) address) T(boost::forward<A0>(args.a0));
}
template <typename Alloc, typename T, typename A0, typename A1>
inline void construct_value_impl(Alloc&, T* address,
inline void construct_from_args(Alloc&, T* address,
emplace_args2<A0, A1> const& args)
{
new((void*) address) T(
@ -1071,7 +1149,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
}
template <typename Alloc, typename T, typename A0, typename A1, typename A2>
inline void construct_value_impl(Alloc&, T* address,
inline void construct_from_args(Alloc&, T* address,
emplace_args3<A0, A1, A2> const& args)
{
new((void*) address) T(
@ -1088,7 +1166,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
typename Alloc, typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
inline void construct_value_impl(Alloc&, T* address, \
inline void construct_from_args(Alloc&, T* address, \
boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
@ -1107,14 +1185,18 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
template <typename Alloc, typename A, typename B,
typename A0, typename A1, typename A2>
inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
inline void construct_from_args(Alloc& alloc, std::pair<A, B>* address,
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
typename enable_if<use_piecewise<A0>, void*>::type = 0)
{
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::addressof(address->first), args.a1);
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->first)),
args.a1);
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::addressof(address->second), args.a2);
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->second)),
args.a2);
}
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
@ -1165,7 +1247,7 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(!node_);
node_ = p;
node_constructed_ = true;
boost::unordered::detail::func::destroy_value_impl(alloc_,
boost::unordered::detail::func::call_destroy(alloc_,
node_->value_ptr());
}
@ -1231,7 +1313,7 @@ namespace boost { namespace unordered { namespace detail {
node_tmp<Alloc>::~node_tmp()
{
if (node_) {
boost::unordered::detail::func::destroy_value_impl(alloc_,
boost::unordered::detail::func::call_destroy(alloc_,
node_->value_ptr());
boost::unordered::detail::func::destroy(
boost::addressof(*node_));
@ -1242,23 +1324,23 @@ namespace boost { namespace unordered { namespace detail {
namespace boost { namespace unordered { namespace detail { namespace func {
// Some nicer construct_value functions, might try to
// Some nicer construct_node functions, might try to
// improve implementation later.
template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_value_generic(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor<Alloc> a(alloc);
a.create_node();
construct_value_impl(alloc, a.node_->value_ptr(),
construct_from_args(alloc, a.node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_FORWARD);
return a.release();
}
template <typename Alloc, typename U>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_value(Alloc& alloc, BOOST_FWD_REF(U) x)
construct_node(Alloc& alloc, BOOST_FWD_REF(U) x)
{
node_constructor<Alloc> a(alloc);
a.create_node();
@ -1271,29 +1353,33 @@ namespace boost { namespace unordered { namespace detail { namespace func {
// constructor for std::piece_construct with std::tuple.
template <typename Alloc, typename Key>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(
alloc, boost::addressof(a.node_->value_ptr()->first),
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->first)),
boost::forward<Key>(k));
boost::unordered::detail::func::call_construct(
alloc, boost::addressof(a.node_->value_ptr()->second));
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->second)));
return a.release();
}
template <typename Alloc, typename Key, typename Mapped>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(
alloc, boost::addressof(a.node_->value_ptr()->first),
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->first)),
boost::forward<Key>(k));
boost::unordered::detail::func::call_construct(
alloc, boost::addressof(a.node_->value_ptr()->second),
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->second)),
boost::forward<Mapped>(m));
return a.release();
}

View File

@ -61,7 +61,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
#endif
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@ -72,8 +71,8 @@ namespace boost { namespace unordered { namespace iterator_detail {
l_iterator() BOOST_NOEXCEPT : ptr_() {}
l_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
: ptr_(n), bucket_(b), bucket_count_(c) {}
value_type& operator*() const {
return ptr_->value();
@ -120,7 +119,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@ -131,8 +129,8 @@ namespace boost { namespace unordered { namespace iterator_detail {
cl_iterator() BOOST_NOEXCEPT : ptr_() {}
cl_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
ptr_(n), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
Node, Policy> const& x) BOOST_NOEXCEPT :
@ -186,10 +184,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename>
friend struct boost::unordered::iterator_detail::c_iterator;
template <typename, typename>
friend struct boost::unordered::iterator_detail::l_iterator;
template <typename, typename>
friend struct boost::unordered::iterator_detail::cl_iterator;
template <typename>
friend struct boost::unordered::detail::table;
template <typename>
@ -359,21 +353,6 @@ namespace boost { namespace unordered { namespace detail {
template <typename T>
inline node_pointer copy_of(T const& v) {
if (nodes_) {
node_tmp<NodeAlloc> a(pop_node(), constructor_.alloc_);
a.node_->value() = v;
return a.release();
}
else {
constructor_.create_node();
boost::unordered::detail::func::call_construct(
constructor_.alloc_, constructor_.node_->value_ptr(), v);
return constructor_.release();
}
}
template <typename T1, typename T2>
inline node_pointer copy_of(std::pair<T1 const, T2> const& v) {
if (nodes_) {
constructor_.reclaim(pop_node());
}
@ -387,22 +366,6 @@ namespace boost { namespace unordered { namespace detail {
template <typename T>
inline node_pointer move_copy_of(T& v) {
if (nodes_) {
node_tmp<NodeAlloc> a(pop_node(), constructor_.alloc_);
a.node_->value() = boost::move(v);
return a.release();
}
else {
constructor_.create_node();
boost::unordered::detail::func::call_construct(
constructor_.alloc_, constructor_.node_->value_ptr(),
boost::move(v));
return constructor_.release();
}
}
template <typename T1, typename T2>
inline node_pointer move_copy_of(std::pair<T1 const, T2>& v) {
if (nodes_) {
constructor_.reclaim(pop_node());
}
@ -428,7 +391,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_);
boost::unordered::detail::func::destroy_value_impl(constructor_.alloc_,
boost::unordered::detail::func::call_destroy(constructor_.alloc_,
p->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*p));
node_allocator_traits::deallocate(constructor_.alloc_, p, 1);

View File

@ -110,9 +110,11 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T>
struct pick_grouped_node
{
typedef typename boost::remove_const<T>::type nonconst;
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::grouped_ptr_node<T> >::type
boost::unordered::detail::grouped_ptr_node<nonconst> >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
@ -120,7 +122,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
typedef pick_grouped_node2<A, T,
typedef pick_grouped_node2<A, nonconst,
typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick;
@ -186,48 +188,58 @@ namespace boost { namespace unordered { namespace detail {
this->move_init(x);
}
// Node functions.
static inline node_pointer next_node(link_pointer n) {
return static_cast<node_pointer>(n->next_);
}
static inline node_pointer next_group(node_pointer n) {
return static_cast<node_pointer>(n->group_prev_->next_);
}
// Accessors
template <class Key, class Pred>
iterator find_node_impl(
node_pointer find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = this->hash_to_bucket(key_hash);
iterator n = this->begin(bucket_index);
node_pointer n = this->begin(bucket_index);
for (;;)
{
if (!n.node_) return n;
if (!n) return n;
std::size_t node_hash = n.node_->hash_;
std::size_t node_hash = n->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(*n)))
if (eq(k, this->get_key(n->value())))
return n;
}
else
{
if (this->hash_to_bucket(node_hash) != bucket_index)
return iterator();
return node_pointer();
}
n = iterator(n.node_->group_prev_->next_);
n = next_group(n);
}
}
std::size_t count(key_type const& k) const
{
iterator n = this->find_node(k);
if (!n.node_) return 0;
node_pointer n = this->find_node(k);
if (!n) return 0;
std::size_t x = 0;
node_pointer it = n.node_;
node_pointer it = n;
do {
it = it->group_prev_;
++x;
} while(it != n.node_);
} while(it != n);
return x;
}
@ -235,9 +247,8 @@ namespace boost { namespace unordered { namespace detail {
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
iterator n = this->find_node(k);
return std::make_pair(
n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
node_pointer n = this->find_node(k);
return std::make_pair(iterator(n), iterator(n ? next_group(n) : n));
}
// Equality
@ -246,12 +257,12 @@ namespace boost { namespace unordered { namespace detail {
{
if(this->size_ != other.size_) return false;
for(iterator n1 = this->begin(); n1.node_;)
for(node_pointer n1 = this->begin(); n1;)
{
iterator n2 = other.find_matching_node(n1);
if (!n2.node_) return false;
iterator end1(n1.node_->group_prev_->next_);
iterator end2(n2.node_->group_prev_->next_);
node_pointer n2 = other.find_node(other.get_key(n1->value()));
if (!n2) return false;
node_pointer end1 = next_group(n1);
node_pointer end2 = next_group(n2);
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
@ -259,24 +270,24 @@ namespace boost { namespace unordered { namespace detail {
return true;
}
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
static bool group_equals(node_pointer n1, node_pointer end1,
node_pointer n2, node_pointer end2)
{
for(;;)
{
if (*n1 != *n2) break;
if (n1->value() != n2->value()) break;
++n1;
++n2;
n1 = next_node(n1);
n2 = next_node(n2);
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
for(iterator n1a = n1, n2a = n2;;)
for(node_pointer n1a = n1, n2a = n2;;)
{
++n1a;
++n2a;
n1a = next_node(n1a);
n2a = next_node(n2a);
if (n1a == end1)
{
@ -287,35 +298,34 @@ namespace boost { namespace unordered { namespace detail {
if (n2a == end2) return false;
}
iterator start = n1;
for(;n1 != end1; ++n1)
node_pointer start = n1;
for(;n1 != end1; n1 = next_node(n1))
{
value_type const& v = *n1;
if (find(start, n1, v)) continue;
std::size_t matches = count_equal(n2, end2, v);
if (!matches) return false;
iterator next = n1;
++next;
if (matches != 1 + count_equal(next, end1, v)) return false;
value_type const& v = n1->value();
if (!find(start, n1, v)) {
std::size_t matches = count_equal(n2, end2, v);
if (!matches) return false;
if (matches != 1 + count_equal(next_node(n1), end1, v)) return false;
}
}
return true;
}
static bool find(iterator n, iterator end, value_type const& v)
static bool find(node_pointer n, node_pointer end, value_type const& v)
{
for(;n != end; ++n)
if (*n == v)
for(;n != end; n = next_node(n))
if (n->value() == v)
return true;
return false;
}
static std::size_t count_equal(iterator n, iterator end,
static std::size_t count_equal(node_pointer n, node_pointer end,
value_type const& v)
{
std::size_t count = 0;
for(;n != end; ++n)
if (*n == v) ++count;
for(;n != end; n = next_node(n))
if (n->value() == v) ++count;
return count;
}
@ -334,17 +344,17 @@ namespace boost { namespace unordered { namespace detail {
pos->group_prev_ = n;
}
inline iterator add_node(
inline node_pointer add_node(
node_pointer n,
std::size_t key_hash,
iterator pos)
node_pointer pos)
{
n->hash_ = key_hash;
if (pos.node_) {
this->add_to_node_group(n, pos.node_);
if (pos) {
this->add_to_node_group(n, pos);
if (n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
static_cast<node_pointer>(n->next_)->hash_);
next_node(n)->hash_);
if (next_bucket != this->hash_to_bucket(key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
@ -360,7 +370,7 @@ namespace boost { namespace unordered { namespace detail {
if (start_node->next_) {
this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_
next_node(start_node)->hash_
))->next_ = n;
}
@ -375,10 +385,10 @@ namespace boost { namespace unordered { namespace detail {
}
}
++this->size_;
return iterator(n);
return n;
}
inline iterator add_using_hint(
inline node_pointer add_using_hint(
node_pointer n,
node_pointer hint)
{
@ -386,13 +396,13 @@ namespace boost { namespace unordered { namespace detail {
this->add_to_node_group(n, hint);
if (n->next_ != hint && n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
static_cast<node_pointer>(n->next_)->hash_);
next_node(n)->hash_);
if (next_bucket != this->hash_to_bucket(n->hash_)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
++this->size_;
return iterator(n);
return n;
}
@ -432,7 +442,7 @@ namespace boost { namespace unordered { namespace detail {
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_impl(
boost::unordered::detail::func::construct_value_generic(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
@ -440,7 +450,7 @@ namespace boost { namespace unordered { namespace detail {
iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_hint_impl(hint,
boost::unordered::detail::func::construct_value_generic(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
@ -449,9 +459,9 @@ namespace boost { namespace unordered { namespace detail {
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
node_pointer position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
return this->add_node(a.release(), key_hash, position);
return iterator(this->add_node(a.release(), key_hash, position));
}
iterator emplace_hint_impl(c_iterator hint, node_pointer n)
@ -460,13 +470,13 @@ namespace boost { namespace unordered { namespace detail {
key_type const& k = this->get_key(a.node_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
this->reserve_for_insert(this->size_ + 1);
return this->add_using_hint(a.release(), hint.node_);
return iterator(this->add_using_hint(a.release(), hint.node_));
}
else {
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
node_pointer position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
return this->add_node(a.release(), key_hash, position);
return iterator(this->add_node(a.release(), key_hash, position));
}
}
@ -475,7 +485,7 @@ namespace boost { namespace unordered { namespace detail {
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
node_pointer position = this->find_node(key_hash, k);
this->add_node(a.release(), key_hash, position);
}
@ -493,7 +503,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
if(distance == 1) {
emplace_impl(
boost::unordered::detail::func::construct_value(
boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
}
else {
@ -502,7 +512,7 @@ namespace boost { namespace unordered { namespace detail {
for (; i != j; ++i) {
emplace_impl_no_rehash(
boost::unordered::detail::func::construct_value(
boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
}
}
@ -514,7 +524,7 @@ namespace boost { namespace unordered { namespace detail {
{
for (; i != j; ++i) {
emplace_impl(
boost::unordered::detail::func::construct_value(
boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
}
}
@ -533,21 +543,21 @@ namespace boost { namespace unordered { namespace detail {
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
node_pointer first_node;
for (;;)
{
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
first_node = next_node(prev);
std::size_t node_hash = first_node->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
this->key_eq()(k, this->get_key(first_node->value())))
break;
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
prev = first_node->group_prev_;
}
node_pointer first_node = static_cast<node_pointer>(prev->next_);
link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
@ -558,10 +568,9 @@ namespace boost { namespace unordered { namespace detail {
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
erase_nodes(r.node_, next.node_);
return next;
node_pointer next = next_node(r.node_);
erase_nodes(r.node_, next);
return iterator(next);
}
iterator erase_range(c_iterator r1, c_iterator r2)
@ -586,13 +595,12 @@ namespace boost { namespace unordered { namespace detail {
if (!prev) {
prev = this->get_previous_start(bucket_index);
while (prev->next_ != i)
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
prev = next_node(prev)->group_prev_;
}
// Delete the nodes.
do {
link_pointer group_end =
static_cast<node_pointer>(prev->next_)->group_prev_->next_;
link_pointer group_end = next_group(next_node(prev));
this->delete_nodes(prev, group_end);
bucket_index = this->fix_bucket(bucket_index, prev);
} while(prev->next_ != j);
@ -632,17 +640,17 @@ namespace boost { namespace unordered { namespace detail {
void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for (iterator n = src.begin(); n.node_;) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
iterator pos = this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *n), key_hash, iterator());
for (++n; n != group_end; ++n)
for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n->hash_;
node_pointer group_end(next_group(n));
node_pointer pos = this->add_node(
boost::unordered::detail::func::construct_node(
this->node_alloc(), n->value()), key_hash, node_pointer());
for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *n), key_hash, pos);
boost::unordered::detail::func::construct_node(
this->node_alloc(), n->value()), key_hash, pos);
}
}
}
@ -650,43 +658,43 @@ namespace boost { namespace unordered { namespace detail {
void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for (iterator n = src.begin(); n.node_;) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
iterator pos = this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), boost::move(*n)), key_hash, iterator());
for (++n; n != group_end; ++n)
for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n->hash_;
node_pointer group_end(next_group(n));
node_pointer pos = this->add_node(
boost::unordered::detail::func::construct_node(
this->node_alloc(), boost::move(n->value())), key_hash, node_pointer());
for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), boost::move(*n)), key_hash, pos);
boost::unordered::detail::func::construct_node(
this->node_alloc(), boost::move(n->value())), key_hash, pos);
}
}
}
void assign_buckets(table const& src) {
node_holder<node_allocator> holder(*this);
for (iterator n = src.begin(); n.node_;) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
iterator pos = this->add_node(holder.copy_of(*n), key_hash, iterator());
for (++n; n != group_end; ++n)
for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n->hash_;
node_pointer group_end(next_group(n));
node_pointer pos = this->add_node(holder.copy_of(n->value()), key_hash, node_pointer());
for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(holder.copy_of(*n), key_hash, pos);
this->add_node(holder.copy_of(n->value()), key_hash, pos);
}
}
}
void move_assign_buckets(table& src) {
node_holder<node_allocator> holder(*this);
for (iterator n = src.begin(); n.node_;) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
iterator pos = this->add_node(holder.move_copy_of(*n), key_hash, iterator());
for (++n; n != group_end; ++n)
for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n->hash_;
node_pointer group_end(next_group(n));
node_pointer pos = this->add_node(holder.move_copy_of(n->value()), key_hash, node_pointer());
for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(holder.move_copy_of(*n), key_hash, pos);
this->add_node(holder.move_copy_of(n->value()), key_hash, pos);
}
}
}
@ -699,8 +707,7 @@ namespace boost { namespace unordered { namespace detail {
this->create_buckets(num_buckets);
link_pointer prev = this->get_previous_start();
while (prev->next_)
prev = place_in_bucket(*this, prev,
static_cast<node_pointer>(prev->next_)->group_prev_);
prev = place_in_bucket(*this, prev, next_node(prev)->group_prev_);
}
// Iterate through the nodes placing them in the correct buckets.

View File

@ -31,6 +31,15 @@ namespace boost { namespace unordered { namespace detail {
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::iterator_detail::
iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
};
template <typename A, typename K, typename M, typename H, typename P>
@ -56,6 +65,15 @@ namespace boost { namespace unordered { namespace detail {
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::iterator_detail::
iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
};
}}}

View File

@ -29,6 +29,15 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::iterator_detail::
c_iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
};
template <typename A, typename T, typename H, typename P>
@ -53,5 +62,14 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::iterator_detail::
c_iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
};
}}}

View File

@ -84,6 +84,10 @@ namespace boost { namespace unordered { namespace detail {
typedef typename Types::table table_impl;
typedef typename Types::link_pointer link_pointer;
typedef typename Types::policy policy;
typedef typename Types::iterator iterator;
typedef typename Types::c_iterator c_iterator;
typedef typename Types::l_iterator l_iterator;
typedef typename Types::cl_iterator cl_iterator;
typedef boost::unordered::detail::functions<
typename Types::hasher,
@ -110,15 +114,6 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::node_tmp<node_allocator>
node_tmp;
typedef boost::unordered::iterator_detail::
iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
////////////////////////////////////////////////////////////////////////
// Members
@ -130,6 +125,13 @@ namespace boost { namespace unordered { namespace detail {
std::size_t max_load_;
bucket_pointer buckets_;
////////////////////////////////////////////////////////////////////////
// Node functions
static inline node_pointer next_node(link_pointer n) {
return static_cast<node_pointer>(n->next_);
}
////////////////////////////////////////////////////////////////////////
// Data access
@ -176,16 +178,16 @@ namespace boost { namespace unordered { namespace detail {
return get_bucket(bucket_index)->next_;
}
iterator begin() const
node_pointer begin() const
{
return size_ ? iterator(get_previous_start()->next_) : iterator();
return size_ ? next_node(get_previous_start()) : node_pointer();
}
iterator begin(std::size_t bucket_index) const
node_pointer begin(std::size_t bucket_index) const
{
if (!size_) return iterator();
if (!size_) return node_pointer();
link_pointer prev = get_previous_start(bucket_index);
return prev ? iterator(prev->next_) : iterator();
return prev ? next_node(prev) : node_pointer();
}
std::size_t hash_to_bucket(std::size_t hash_value) const
@ -202,14 +204,14 @@ namespace boost { namespace unordered { namespace detail {
std::size_t bucket_size(std::size_t index) const
{
iterator it = begin(index);
if (!it.node_) return 0;
node_pointer n = begin(index);
if (!n) return 0;
std::size_t count = 0;
while(it.node_ && hash_to_bucket(it.node_->hash_) == index)
while(n && hash_to_bucket(n->hash_) == index)
{
++count;
++it;
n = next_node(n);
}
return count;
@ -462,7 +464,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer n = static_cast<node_pointer>(prev->next_);
prev->next_ = n->next_;
boost::unordered::detail::func::destroy_value_impl(node_alloc(),
boost::unordered::detail::func::call_destroy(node_alloc(),
n->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
@ -698,7 +700,7 @@ namespace boost { namespace unordered { namespace detail {
// Find Node
template <typename Key, typename Hash, typename Pred>
iterator generic_find_node(
node_pointer generic_find_node(
Key const& k,
Hash const& hf,
Pred const& eq) const
@ -707,7 +709,7 @@ namespace boost { namespace unordered { namespace detail {
find_node_impl(policy::apply_hash(hf, k), k, eq);
}
iterator find_node(
node_pointer find_node(
std::size_t key_hash,
key_type const& k) const
{
@ -715,23 +717,12 @@ namespace boost { namespace unordered { namespace detail {
find_node_impl(key_hash, k, this->key_eq());
}
iterator find_node(key_type const& k) const
node_pointer find_node(key_type const& k) const
{
return static_cast<table_impl const*>(this)->
find_node_impl(hash(k), k, this->key_eq());
}
iterator find_matching_node(iterator n) const
{
// TODO: Does this apply to C++11?
//
// For some stupid reason, I decided to support equality comparison
// when different hash functions are used. So I can't use the hash
// value from the node here.
return find_node(get_key(*n));
}
// Reserve and rehash
void reserve_for_insert(std::size_t);

View File

@ -106,9 +106,11 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T>
struct pick_node
{
typedef typename boost::remove_const<T>::type nonconst;
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A,
boost::unordered::detail::ptr_node<T> >::type
boost::unordered::detail::ptr_node<nonconst> >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
@ -116,7 +118,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
typedef pick_node2<A, T,
typedef pick_node2<A, nonconst,
typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick;
@ -184,47 +186,53 @@ namespace boost { namespace unordered { namespace detail {
this->move_init(x);
}
// Node functions.
static inline node_pointer next_node(link_pointer n) {
return static_cast<node_pointer>(n->next_);
}
// Accessors
template <class Key, class Pred>
iterator find_node_impl(
node_pointer find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = this->hash_to_bucket(key_hash);
iterator n = this->begin(bucket_index);
node_pointer n = this->begin(bucket_index);
for (;;)
{
if (!n.node_) return n;
if (!n) return n;
std::size_t node_hash = n.node_->hash_;
std::size_t node_hash = n->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(*n)))
if (eq(k, this->get_key(n->value())))
return n;
}
else
{
if (this->hash_to_bucket(node_hash) != bucket_index)
return iterator();
return node_pointer();
}
++n;
n = next_node(n);
}
}
std::size_t count(key_type const& k) const
{
return this->find_node(k).node_ ? 1 : 0;
return this->find_node(k) ? 1 : 0;
}
value_type& at(key_type const& k) const
{
if (this->size_) {
iterator it = this->find_node(k);
if (it.node_) return *it;
node_pointer n = this->find_node(k);
if (n) return n->value();
}
boost::throw_exception(
@ -234,10 +242,8 @@ namespace boost { namespace unordered { namespace detail {
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
iterator n = this->find_node(k);
iterator n2 = n;
if (n2.node_) ++n2;
return std::make_pair(n, n2);
node_pointer n = this->find_node(k);
return std::make_pair(iterator(n), iterator(n ? next_node(n) : n));
}
// equals
@ -246,11 +252,11 @@ namespace boost { namespace unordered { namespace detail {
{
if(this->size_ != other.size_) return false;
for(iterator n1 = this->begin(); n1.node_; ++n1)
for(node_pointer n1 = this->begin(); n1; n1 = next_node(n1))
{
iterator n2 = other.find_matching_node(n1);
node_pointer n2 = other.find_node(other.get_key(n1->value()));
if (!n2.node_ || *n1 != *n2)
if (!n2 || n1->value() != n2->value())
return false;
}
@ -259,7 +265,7 @@ namespace boost { namespace unordered { namespace detail {
// Emplace/Insert
inline iterator add_node(
inline node_pointer add_node(
node_pointer n,
std::size_t key_hash)
{
@ -273,7 +279,7 @@ namespace boost { namespace unordered { namespace detail {
if (start_node->next_) {
this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_)
next_node(start_node)->hash_)
)->next_ = n;
}
@ -288,10 +294,10 @@ namespace boost { namespace unordered { namespace detail {
}
++this->size_;
return iterator(n);
return n;
}
inline iterator resize_and_add_node(node_pointer n, std::size_t key_hash)
inline node_pointer resize_and_add_node(node_pointer n, std::size_t key_hash)
{
node_tmp b(n, this->node_alloc());
this->reserve_for_insert(this->size_ + 1);
@ -301,11 +307,15 @@ namespace boost { namespace unordered { namespace detail {
value_type& operator[](key_type const& k)
{
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return *pos;
return *this->resize_and_add_node(
boost::unordered::detail::func::construct_pair(this->node_alloc(), k),
key_hash);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return pos->value();
}
else {
return this->resize_and_add_node(
boost::unordered::detail::func::construct_node_pair(this->node_alloc(), k),
key_hash)->value();
}
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@ -314,7 +324,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
return emplace_return(iterator(), false);
}
iterator emplace_hint(c_iterator,
@ -322,21 +332,21 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return this->begin();
return iterator();
}
# else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
return emplace_return(iterator(), false);
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return this->begin();
return iterator();
}
# endif
#endif
@ -403,16 +413,16 @@ namespace boost { namespace unordered { namespace detail {
BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) {
return emplace_return(pos, false);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return emplace_return(iterator(pos), false);
}
else {
return emplace_return(
this->resize_and_add_node(
boost::unordered::detail::func::construct_value_generic(
iterator(this->resize_and_add_node(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
key_hash),
key_hash)),
true);
}
}
@ -422,7 +432,7 @@ namespace boost { namespace unordered { namespace detail {
BOOST_UNORDERED_EMPLACE_ARGS)
{
node_tmp b(
boost::unordered::detail::func::construct_value_generic(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
key_type const& k = this->get_key(b.node_->value());
@ -430,12 +440,12 @@ namespace boost { namespace unordered { namespace detail {
return iterator(hint.node_);
}
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) {
return pos;
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return iterator(pos);
}
else {
return this->resize_and_add_node(b.release(), key_hash);
return iterator(this->resize_and_add_node(b.release(), key_hash));
}
}
@ -443,18 +453,18 @@ namespace boost { namespace unordered { namespace detail {
emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_tmp b(
boost::unordered::detail::func::construct_value_generic(
boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
key_type const& k = this->get_key(b.node_->value());
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) {
return emplace_return(pos, false);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return emplace_return(iterator(pos), false);
}
else {
return emplace_return(
this->resize_and_add_node(b.release(), key_hash),
iterator(this->resize_and_add_node(b.release(), key_hash)),
true);
}
}
@ -495,11 +505,11 @@ namespace boost { namespace unordered { namespace detail {
{
// No side effects in this initial code
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
node_pointer pos = this->find_node(key_hash, k);
if (!pos.node_) {
if (!pos) {
node_tmp b(
boost::unordered::detail::func::construct_value(this->node_alloc(), *i),
boost::unordered::detail::func::construct_node(this->node_alloc(), *i),
this->node_alloc());
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
@ -521,9 +531,9 @@ namespace boost { namespace unordered { namespace detail {
key_type const& k = this->get_key(b.node_->value());
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
node_pointer pos = this->find_node(key_hash, k);
if (pos.node_) {
if (pos) {
a.reclaim(b.release());
}
else {
@ -552,18 +562,17 @@ namespace boost { namespace unordered { namespace detail {
for (;;)
{
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
std::size_t node_hash = next_node(prev)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
next_node(prev)->value())))
break;
prev = prev->next_;
}
link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
link_pointer end = next_node(prev)->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
@ -573,10 +582,9 @@ namespace boost { namespace unordered { namespace detail {
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
erase_nodes(r.node_, next.node_);
return next;
node_pointer next = next_node(r.node_);
erase_nodes(r.node_, next);
return iterator(next);
}
iterator erase_range(c_iterator r1, c_iterator r2)
@ -607,36 +615,36 @@ namespace boost { namespace unordered { namespace detail {
void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for(iterator n = src.begin(); n.node_; ++n) {
for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *n), n.node_->hash_);
boost::unordered::detail::func::construct_node(
this->node_alloc(), n->value()), n->hash_);
}
}
void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for(iterator n = src.begin(); n.node_; ++n) {
for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), boost::move(*n)), n.node_->hash_);
boost::unordered::detail::func::construct_node(
this->node_alloc(), boost::move(n->value())), n->hash_);
}
}
void assign_buckets(table const& src)
{
node_holder<node_allocator> holder(*this);
for(iterator n = src.begin(); n.node_; ++n) {
this->add_node(holder.copy_of(*n), n.node_->hash_);
for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(holder.copy_of(n->value()), n->hash_);
}
}
void move_assign_buckets(table& src)
{
node_holder<node_allocator> holder(*this);
for(iterator n = src.begin(); n.node_; ++n) {
this->add_node(holder.move_copy_of(*n), n.node_->hash_);
for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(holder.move_copy_of(n->value()), n->hash_);
}
}
@ -655,7 +663,7 @@ namespace boost { namespace unordered { namespace detail {
// pre: prev->next_ is not null.
static link_pointer place_in_bucket(table& dst, link_pointer prev)
{
node_pointer n = static_cast<node_pointer>(prev->next_);
node_pointer n = next_node(prev);
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
if (!b->next_) {

View File

@ -82,12 +82,23 @@ namespace unordered
// constructors
unordered_map();
explicit unordered_map(
size_type = boost::unordered::detail::default_bucket_count,
size_type,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_map(
size_type,
const allocator_type&);
explicit unordered_map(
size_type,
const hasher&,
const allocator_type&);
explicit unordered_map(allocator_type const&);
template <class InputIt>
@ -108,11 +119,25 @@ namespace unordered
const key_equal&,
const allocator_type&);
template <class InputIt>
unordered_map(
InputIt, InputIt,
size_type,
const hasher&,
const allocator_type&);
template <class InputIt>
unordered_map(
InputIt, InputIt,
size_type,
const allocator_type&);
// copy/move constructors
unordered_map(unordered_map const&);
unordered_map(unordered_map const&, allocator_type const&);
unordered_map(BOOST_RV_REF(unordered_map), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map(BOOST_RV_REF(unordered_map) other)
@ -128,10 +153,6 @@ namespace unordered
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map(
std::initializer_list<value_type>,
@ -139,6 +160,15 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
unordered_map(
std::initializer_list<value_type>,
size_type,
const hasher&,
const allocator_type&);
unordered_map(
std::initializer_list<value_type>,
size_type,
const allocator_type&);
#endif
// Destructor
@ -202,12 +232,12 @@ namespace unordered
iterator begin() BOOST_NOEXCEPT
{
return table_.begin();
return iterator(table_.begin());
}
const_iterator begin() const BOOST_NOEXCEPT
{
return table_.begin();
return const_iterator(table_.begin());
}
iterator end() BOOST_NOEXCEPT
@ -222,7 +252,7 @@ namespace unordered
const_iterator cbegin() const BOOST_NOEXCEPT
{
return table_.begin();
return const_iterator(table_.begin());
}
const_iterator cend() const BOOST_NOEXCEPT
@ -565,12 +595,23 @@ namespace unordered
// constructors
unordered_multimap();
explicit unordered_multimap(
size_type = boost::unordered::detail::default_bucket_count,
size_type,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_multimap(
size_type,
const allocator_type&);
explicit unordered_multimap(
size_type,
const hasher&,
const allocator_type&);
explicit unordered_multimap(allocator_type const&);
template <class InputIt>
@ -591,11 +632,25 @@ namespace unordered
const key_equal&,
const allocator_type&);
template <class InputIt>
unordered_multimap(
InputIt, InputIt,
size_type,
const hasher&,
const allocator_type&);
template <class InputIt>
unordered_multimap(
InputIt, InputIt,
size_type,
const allocator_type&);
// copy/move constructors
unordered_multimap(unordered_multimap const&);
unordered_multimap(unordered_multimap const&, allocator_type const&);
unordered_multimap(BOOST_RV_REF(unordered_multimap), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
@ -611,10 +666,6 @@ namespace unordered
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap(
std::initializer_list<value_type>,
@ -622,6 +673,15 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
unordered_multimap(
std::initializer_list<value_type>,
size_type,
const hasher&,
const allocator_type&);
unordered_multimap(
std::initializer_list<value_type>,
size_type,
const allocator_type&);
#endif
// Destructor
@ -686,12 +746,12 @@ namespace unordered
iterator begin() BOOST_NOEXCEPT
{
return table_.begin();
return iterator(table_.begin());
}
const_iterator begin() const BOOST_NOEXCEPT
{
return table_.begin();
return const_iterator(table_.begin());
}
iterator end() BOOST_NOEXCEPT
@ -706,7 +766,7 @@ namespace unordered
const_iterator cbegin() const BOOST_NOEXCEPT
{
return table_.begin();
return const_iterator(table_.begin());
}
const_iterator cend() const BOOST_NOEXCEPT
@ -1002,6 +1062,13 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
size_type n, const hasher &hf, const key_equal &eql,
@ -1010,6 +1077,20 @@ namespace unordered
{
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
size_type n, const allocator_type &a)
: table_(n, hasher(), key_equal(), a)
{
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
size_type n, const hasher &hf, const allocator_type &a)
: table_(n, hf, key_equal(), a)
{
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@ -1059,6 +1140,31 @@ namespace unordered
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
template <class InputIt>
unordered_map<K,T,H,P,A>::unordered_map(
InputIt f, InputIt l,
size_type n,
const hasher &hf,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hf, key_equal(), a)
{
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
template <class InputIt>
unordered_map<K,T,H,P,A>::unordered_map(
InputIt f, InputIt l,
size_type n,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hasher(), key_equal(), a)
{
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
@ -1069,17 +1175,13 @@ namespace unordered
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
unordered_map&& other, allocator_type const& a)
BOOST_RV_REF(unordered_map) other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
@ -1094,6 +1196,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
std::initializer_list<value_type> list, size_type n,
const hasher &hf, const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
std::initializer_list<value_type> list, size_type n,
const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hasher(), key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>& unordered_map<K,T,H,P,A>::operator=(
std::initializer_list<value_type> list)
@ -1208,14 +1334,14 @@ namespace unordered
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::find(const key_type& k)
{
return table_.find_node(k);
return iterator(table_.find_node(k));
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K,T,H,P,A>::const_iterator
unordered_map<K,T,H,P,A>::find(const key_type& k) const
{
return table_.find_node(k);
return const_iterator(table_.find_node(k));
}
template <class K, class T, class H, class P, class A>
@ -1227,7 +1353,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return table_.generic_find_node(k, hash, eq);
return iterator(table_.generic_find_node(k, hash, eq));
}
template <class K, class T, class H, class P, class A>
@ -1239,7 +1365,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return table_.generic_find_node(k, hash, eq);
return const_iterator(table_.generic_find_node(k, hash, eq));
}
template <class K, class T, class H, class P, class A>
@ -1335,6 +1461,13 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
size_type n, const hasher &hf, const key_equal &eql,
@ -1343,6 +1476,20 @@ namespace unordered
{
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
size_type n, const allocator_type &a)
: table_(n, hasher(), key_equal(), a)
{
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
size_type n, const hasher &hf, const allocator_type &a)
: table_(n, hf, key_equal(), a)
{
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@ -1392,6 +1539,31 @@ namespace unordered
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
template <class InputIt>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
InputIt f, InputIt l,
size_type n,
const hasher &hf,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hf, key_equal(), a)
{
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
template <class InputIt>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
InputIt f, InputIt l,
size_type n,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hasher(), key_equal(), a)
{
table_.insert_range(f, l);
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {}
@ -1402,17 +1574,13 @@ namespace unordered
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
unordered_multimap&& other, allocator_type const& a)
BOOST_RV_REF(unordered_multimap) other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
@ -1427,6 +1595,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
std::initializer_list<value_type> list, size_type n,
const hasher &hf, const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
std::initializer_list<value_type> list, size_type n,
const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hasher(), key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>& unordered_multimap<K,T,H,P,A>::operator=(
std::initializer_list<value_type> list)
@ -1520,14 +1712,14 @@ namespace unordered
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k)
{
return table_.find_node(k);
return iterator(table_.find_node(k));
}
template <class K, class T, class H, class P, class A>
typename unordered_multimap<K,T,H,P,A>::const_iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
{
return table_.find_node(k);
return const_iterator(table_.find_node(k));
}
template <class K, class T, class H, class P, class A>
@ -1539,7 +1731,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return table_.generic_find_node(k, hash, eq);
return iterator(table_.generic_find_node(k, hash, eq));
}
template <class K, class T, class H, class P, class A>
@ -1551,7 +1743,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return table_.generic_find_node(k, hash, eq);
return const_iterator(table_.generic_find_node(k, hash, eq));
}
template <class K, class T, class H, class P, class A>

View File

@ -67,9 +67,9 @@ namespace unordered
typedef std::ptrdiff_t difference_type;
typedef typename table::cl_iterator const_local_iterator;
typedef typename table::cl_iterator local_iterator;
typedef typename table::l_iterator local_iterator;
typedef typename table::c_iterator const_iterator;
typedef typename table::c_iterator iterator;
typedef typename table::iterator iterator;
private:
@ -79,12 +79,23 @@ namespace unordered
// constructors
unordered_set();
explicit unordered_set(
size_type = boost::unordered::detail::default_bucket_count,
size_type,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_set(
size_type,
const allocator_type&);
explicit unordered_set(
size_type,
const hasher&,
const allocator_type&);
explicit unordered_set(allocator_type const&);
template <class InputIt>
@ -105,11 +116,25 @@ namespace unordered
const key_equal&,
const allocator_type&);
template <class InputIt>
unordered_set(
InputIt, InputIt,
size_type,
const hasher&,
const allocator_type&);
template <class InputIt>
unordered_set(
InputIt, InputIt,
size_type,
const allocator_type&);
// copy/move constructors
unordered_set(unordered_set const&);
unordered_set(unordered_set const&, allocator_type const&);
unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set(BOOST_RV_REF(unordered_set) other)
@ -125,10 +150,6 @@ namespace unordered
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set(
std::initializer_list<value_type>,
@ -136,6 +157,15 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
unordered_set(
std::initializer_list<value_type>,
size_type,
const hasher&,
const allocator_type&);
unordered_set(
std::initializer_list<value_type>,
size_type,
const allocator_type&);
#endif
// Destructor
@ -199,12 +229,12 @@ namespace unordered
iterator begin() BOOST_NOEXCEPT
{
return table_.begin();
return iterator(table_.begin());
}
const_iterator begin() const BOOST_NOEXCEPT
{
return table_.begin();
return const_iterator(table_.begin());
}
iterator end() BOOST_NOEXCEPT
@ -219,7 +249,7 @@ namespace unordered
const_iterator cbegin() const BOOST_NOEXCEPT
{
return table_.begin();
return const_iterator(table_.begin());
}
const_iterator cend() const BOOST_NOEXCEPT
@ -536,9 +566,9 @@ namespace unordered
typedef std::ptrdiff_t difference_type;
typedef typename table::cl_iterator const_local_iterator;
typedef typename table::cl_iterator local_iterator;
typedef typename table::l_iterator local_iterator;
typedef typename table::c_iterator const_iterator;
typedef typename table::c_iterator iterator;
typedef typename table::iterator iterator;
private:
@ -548,12 +578,23 @@ namespace unordered
// constructors
unordered_multiset();
explicit unordered_multiset(
size_type = boost::unordered::detail::default_bucket_count,
size_type,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
explicit unordered_multiset(
size_type,
const allocator_type&);
explicit unordered_multiset(
size_type,
const hasher&,
const allocator_type&);
explicit unordered_multiset(allocator_type const&);
template <class InputIt>
@ -574,11 +615,25 @@ namespace unordered
const key_equal&,
const allocator_type&);
template <class InputIt>
unordered_multiset(
InputIt, InputIt,
size_type,
const hasher&,
const allocator_type&);
template <class InputIt>
unordered_multiset(
InputIt, InputIt,
size_type,
const allocator_type&);
// copy/move constructors
unordered_multiset(unordered_multiset const&);
unordered_multiset(unordered_multiset const&, allocator_type const&);
unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
@ -594,10 +649,6 @@ namespace unordered
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset(
std::initializer_list<value_type>,
@ -605,6 +656,15 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
unordered_multiset(
std::initializer_list<value_type>,
size_type,
const hasher&,
const allocator_type&);
unordered_multiset(
std::initializer_list<value_type>,
size_type,
const allocator_type&);
#endif
// Destructor
@ -976,6 +1036,13 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
size_type n, const hasher &hf, const key_equal &eql,
@ -984,6 +1051,20 @@ namespace unordered
{
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
size_type n, const allocator_type &a)
: table_(n, hasher(), key_equal(), a)
{
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
size_type n, const hasher &hf, const allocator_type &a)
: table_(n, hf, key_equal(), a)
{
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@ -1033,6 +1114,31 @@ namespace unordered
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
template <class InputIt>
unordered_set<T,H,P,A>::unordered_set(
InputIt f, InputIt l,
size_type n,
const hasher &hf,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hf, key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
template <class InputIt>
unordered_set<T,H,P,A>::unordered_set(
InputIt f, InputIt l,
size_type n,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hasher(), key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
@ -1043,17 +1149,13 @@ namespace unordered
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
unordered_set&& other, allocator_type const& a)
BOOST_RV_REF(unordered_set) other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
@ -1068,6 +1170,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
std::initializer_list<value_type> list, size_type n,
const hasher &hf, const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
std::initializer_list<value_type> list, size_type n,
const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hasher(), key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>& unordered_set<T,H,P,A>::operator=(
std::initializer_list<value_type> list)
@ -1161,7 +1287,7 @@ namespace unordered
typename unordered_set<T,H,P,A>::const_iterator
unordered_set<T,H,P,A>::find(const key_type& k) const
{
return table_.find_node(k);
return const_iterator(table_.find_node(k));
}
template <class T, class H, class P, class A>
@ -1173,7 +1299,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return table_.generic_find_node(k, hash, eq);
return const_iterator(table_.generic_find_node(k, hash, eq));
}
template <class T, class H, class P, class A>
@ -1260,6 +1386,13 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
size_type n, const hasher &hf, const key_equal &eql,
@ -1268,6 +1401,20 @@ namespace unordered
{
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
size_type n, const allocator_type &a)
: table_(n, hasher(), key_equal(), a)
{
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
size_type n, const hasher &hf, const allocator_type &a)
: table_(n, hf, key_equal(), a)
{
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@ -1317,6 +1464,31 @@ namespace unordered
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
template <class InputIt>
unordered_multiset<T,H,P,A>::unordered_multiset(
InputIt f, InputIt l,
size_type n,
const hasher &hf,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hf, key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
template <class InputIt>
unordered_multiset<T,H,P,A>::unordered_multiset(
InputIt f, InputIt l,
size_type n,
const allocator_type &a)
: table_(boost::unordered::detail::initial_size(f, l, n),
hasher(), key_equal(), a)
{
table_.insert_range(f, l);
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {}
@ -1327,17 +1499,13 @@ namespace unordered
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
unordered_multiset&& other, allocator_type const& a)
BOOST_RV_REF(unordered_multiset) other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
@ -1352,6 +1520,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
std::initializer_list<value_type> list, size_type n,
const hasher &hf, const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hf, key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
std::initializer_list<value_type> list, size_type n,
const allocator_type &a)
: table_(
boost::unordered::detail::initial_size(
list.begin(), list.end(), n),
hasher(), key_equal(), a)
{
table_.insert_range(list.begin(), list.end());
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>& unordered_multiset<T,H,P,A>::operator=(
std::initializer_list<value_type> list)
@ -1445,7 +1637,7 @@ namespace unordered
typename unordered_multiset<T,H,P,A>::const_iterator
unordered_multiset<T,H,P,A>::find(const key_type& k) const
{
return table_.find_node(k);
return const_iterator(table_.find_node(k));
}
template <class T, class H, class P, class A>
@ -1457,7 +1649,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return table_.generic_find_node(k, hash, eq);
return const_iterator(table_.generic_find_node(k, hash, eq));
}
template <class T, class H, class P, class A>

View File

@ -14,6 +14,7 @@ project unordered-test/unordered
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>clang:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
<toolset>msvc:<cxxflags>"/wd4494"
;
#alias framework : /boost/test//boost_unit_test_framework ;
@ -27,6 +28,9 @@ test-suite unordered
[ run unordered/minimal_allocator.cpp ]
[ run unordered/compile_set.cpp ]
[ run unordered/compile_map.cpp ]
[ run unordered/compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_ALLOCATOR_TRAITS=0
: compile_map_unordered_allocator ]
[ run unordered/noexcept_tests.cpp ]
[ run unordered/link_test_1.cpp unordered/link_test_2.cpp ]
[ run unordered/incomplete_test.cpp ]

View File

@ -179,12 +179,13 @@ namespace test {
class test_runner
{
Test const& test_;
bool exception_in_check_;
test_runner(test_runner const&);
test_runner& operator=(test_runner const&);
public:
test_runner(Test const& t) : test_(t) {}
void operator()() const {
test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
void run() {
DISABLE_EXCEPTIONS;
test::scope = "";
BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
@ -199,14 +200,24 @@ namespace test {
>(&Test::run, test_, x, strong);
}
catch(...) {
call_ignore_extra_parameters<
Test,
BOOST_DEDUCED_TYPENAME Test::data_type const,
BOOST_DEDUCED_TYPENAME Test::strong_type const
>(&Test::check, test_, constant(x), constant(strong));
try {
DISABLE_EXCEPTIONS;
call_ignore_extra_parameters<
Test,
BOOST_DEDUCED_TYPENAME Test::data_type const,
BOOST_DEDUCED_TYPENAME Test::strong_type const
>(&Test::check, test_, constant(x), constant(strong));
} catch(...) {
exception_in_check_ = true;
}
throw;
}
}
void end() {
if (exception_in_check_) {
BOOST_ERROR("Unexcpected exception in test_runner check call.");
}
}
};
// Quick exception testing based on lightweight test
@ -236,26 +247,30 @@ namespace test {
iteration = 0;
bool success = false;
char const* error_msg = 0;
do {
++iteration;
count = 0;
try {
runner();
runner.run();
success = true;
}
catch(test_failure) {
BOOST_ERROR("test_failure caught.");
error_msg = "test_failure caught.";
break;
}
catch(test_exception) {
continue;
}
catch(...) {
BOOST_ERROR("Unexpected exception.");
error_msg = "Unexpected exception.";
break;
}
} while(!success);
if (error_msg) { BOOST_ERROR(error_msg); }
runner.end();
}
}
}

View File

@ -201,9 +201,11 @@ namespace test
public move_allocator_base<Flags>,
Flags
{
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind {
typedef cxx11_allocator<U, Flags> other;
};
#endif
explicit cxx11_allocator(int t = 0)
: cxx11_allocator_base<T>(t)
@ -251,9 +253,11 @@ namespace test
return tmp;
}
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind {
typedef cxx11_allocator<U, Flags> other;
};
#endif
explicit cxx11_allocator(int t = 0)
: cxx11_allocator_base<T>(t)

View File

@ -447,7 +447,7 @@ namespace minimal
{
public:
typedef T value_type;
template <class U> struct rebind { typedef cxx11_allocator<U> other; };
//template <class U> struct rebind { typedef cxx11_allocator<U> other; };
cxx11_allocator() {}
template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}

View File

@ -24,15 +24,15 @@ template class boost::unordered_map<
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_multimap<
int,
int,
int const,
int const,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<std::pair<int const, int> > >;
template class boost::unordered_map<
test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::assignable const,
test::minimal::default_assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >;

View File

@ -23,13 +23,13 @@ template class boost::unordered_set<
std::equal_to<int>,
test::minimal::allocator<int> >;
template class boost::unordered_multiset<
int,
int const,
boost::hash<int>,
std::equal_to<int>,
test::minimal::allocator<int> >;
template class boost::unordered_set<
test::minimal::assignable,
test::minimal::assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >;

View File

@ -101,7 +101,18 @@ void container_test(X& r, T const&)
static_cast<comparison_type>(
(std::numeric_limits<difference_type>::max)()));
// Constructors
// I don't test the runtime post-conditions here.
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
// It isn't specified in the container requirements that the no argument
// constructor is implicit, but it is defined that way in the concrete
// container specification.
X u_implicit = {};
sink(u_implicit);
#endif
X u;
BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0);
@ -112,6 +123,8 @@ void container_test(X& r, T const&)
sink(X(a));
X u2(a);
X u3 = a;
X u4(rvalue(a_const));
X u5 = rvalue(a_const);
a.swap(b);
boost::swap(a, b);
@ -121,12 +134,25 @@ void container_test(X& r, T const&)
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
allocator_type m = a.get_allocator();
sink(X(m));
X c(m);
sink(X(a_const, m));
X c2(a_const, m);
sink(X(rvalue(a_const), m));
X c3(rvalue(a_const), m);
// Avoid unused variable warnings:
sink(u);
sink(u2);
sink(u3);
sink(u4);
sink(u5);
sink(c);
sink(c2);
sink(c3);
}
template <class X>
@ -247,6 +273,9 @@ void unordered_map_test(X& r, Key const& k, T const& v)
r.emplace(k, v);
r.emplace(k_lvalue, v_lvalue);
r.emplace(rvalue(k), rvalue(v));
r.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple(v));
}
template <class X>
@ -355,6 +384,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
@ -387,8 +417,13 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>::value));
X a;
allocator_type m = a.get_allocator();
// Constructors
X(10, hf, eq);
X a(10, hf, eq);
X a1(10, hf, eq);
X(10, hf);
X a2(10, hf);
X(10);
@ -396,6 +431,15 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
X();
X a4;
X(10, hf, eq, m);
X a1a(10, hf, eq, m);
X(10, hf, m);
X a2a(10, hf, m);
X(10, m);
X a3a(10, m);
(X(m));
X a4a(m);
test::check_return_type<size_type>::equals(a.erase(k));
const_iterator q1 = a.cbegin(), q2 = a.cend();
@ -438,9 +482,14 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
// Avoid unused variable warnings:
sink(a);
sink(a1);
sink(a2);
sink(a3);
sink(a4);
sink(a1a);
sink(a2a);
sink(a3a);
sink(a4a);
}
template <class X, class Key, class T, class Hash, class Pred>
@ -450,14 +499,17 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
X a;
allocator_type m = a.get_allocator();
BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
BOOST_DEDUCED_TYPENAME X::value_type* j = 0;
X(i, j, 10, hf, eq);
// Constructors
X(i, j, 10, hf, eq);
X a5(i, j, 10, hf, eq);
X(i, j, 10, hf);
X a6(i, j, 10, hf);
@ -466,11 +518,38 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
X(i, j);
X a8(i, j);
X(i, j, 10, hf, eq, m);
X a5a(i, j, 10, hf, eq, m);
X(i, j, 10, hf, m);
X a6a(i, j, 10, hf, m);
X(i, j, 10, m);
X a7a(i, j, 10, m);
// Not specified for some reason (maybe ambiguity with another constructor?)
//X(i, j, m);
//X a8a(i, j, m);
//sink(a8a);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::size_t min_buckets = 10;
X({t});
X({t}, min_buckets);
X({t}, min_buckets, hf);
X({t}, min_buckets, hf, eq);
//X({t}, m);
X({t}, min_buckets, m);
X({t}, min_buckets, hf, m);
X({t}, min_buckets, hf, eq, m);
#endif
X const b;
sink(X(b));
X a9(b);
a = b;
sink(X(b, m));
X a9a(b, m);
const_iterator q = a.cbegin();
test::check_return_type<iterator>::equals(a.insert(q, t));
@ -502,6 +581,10 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
sink(a7);
sink(a8);
sink(a9);
sink(a5a);
sink(a6a);
sink(a7a);
sink(a9a);
}
template <class X, class Key, class T, class Hash, class Pred>
@ -511,6 +594,7 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x1(rvalue_default<X>());
@ -519,9 +603,14 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
x2 = boost::move(x1);
#endif
X a;
allocator_type m = a.get_allocator();
test::minimal::constructor_param* i = 0;
test::minimal::constructor_param* j = 0;
// Constructors
X(i, j, 10, hf, eq);
X a5(i, j, 10, hf, eq);
X(i, j, 10, hf);
@ -531,7 +620,17 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
X(i, j);
X a8(i, j);
X a;
X(i, j, 10, hf, eq, m);
X a5a(i, j, 10, hf, eq, m);
X(i, j, 10, hf, m);
X a6a(i, j, 10, hf, m);
X(i, j, 10, m);
X a7a(i, j, 10, m);
// Not specified for some reason (maybe ambiguity with another constructor?)
//X(i, j, m);
//X a8a(i, j, m);
//sink(a8a);
const_iterator q = a.cbegin();
@ -565,6 +664,9 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
sink(a6);
sink(a7);
sink(a8);
sink(a5a);
sink(a6a);
sink(a7a);
sink(a10);
}

View File

@ -434,6 +434,7 @@ void move_emplace_tests(X*, test::random_generator generator)
template <class X>
void default_emplace_tests(X*, test::random_generator)
{
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
std::cerr<<"emplace() tests.\n";
bool is_unique = test::has_unique_keys<X>::value;
@ -464,6 +465,7 @@ void default_emplace_tests(X*, test::random_generator)
BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 2u));
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
#endif
}
template <class X>