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 objects wouldn't match the container elements, so elements might be in the
wrong bucket and equivalent elements would be incorrectly handled. wrong bucket and equivalent elements would be incorrectly handled.
* Various reference documentation improvements. * Various reference documentation improvements.
* Better allocator support ([ticket 12459]).
* Make the no argument constructors implicit.
* Implement missing allocator aware constructors.
[endsect] [endsect]

View File

@ -189,10 +189,22 @@ EOL;
<para>A const_local_iterator object can be used to iterate through a single bucket.</para> <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description> </description>
</typedef> </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"> <constructor specifiers="explicit">
<parameter name="n"> <parameter name="n">
<paramtype>size_type</paramtype> <paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter> </parameter>
<parameter name="hf"> <parameter name="hf">
<paramtype>hasher const&amp;</paramtype> <paramtype>hasher const&amp;</paramtype>
@ -246,7 +258,12 @@ EOL;
<default>allocator_type()</default> <default>allocator_type()</default>
</parameter> </parameter>
<description> <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> </description>
<requires> <requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and <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> <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> </description>
</constructor> </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> <destructor>
<notes> <notes>
<para>The destructor is applied to every element, and all memory is deallocated</para> <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> <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description> </description>
</typedef> </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"> <constructor specifiers="explicit">
<parameter name="n"> <parameter name="n">
<paramtype>size_type</paramtype> <paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter> </parameter>
<parameter name="hf"> <parameter name="hf">
<paramtype>hasher const&amp;</paramtype> <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> <default>allocator_type()</default>
</parameter> </parameter>
<description> <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> </description>
<requires> <requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and <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> <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> </description>
</constructor> </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> <destructor>
<notes> <notes>
<para>The destructor is applied to every element, and all memory is deallocated</para> <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> <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description> </description>
</typedef> </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"> <constructor specifiers="explicit">
<parameter name="n"> <parameter name="n">
<paramtype>size_type</paramtype> <paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter> </parameter>
<parameter name="hf"> <parameter name="hf">
<paramtype>hasher const&amp;</paramtype> <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> <default>allocator_type()</default>
</parameter> </parameter>
<description> <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> </description>
<requires> <requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and <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> <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> </description>
</constructor> </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> <destructor>
<notes> <notes>
<para>The destructor is applied to every element, and all memory is deallocated</para> <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> <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description> </description>
</typedef> </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"> <constructor specifiers="explicit">
<parameter name="n"> <parameter name="n">
<paramtype>size_type</paramtype> <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> <default>allocator_type()</default>
</parameter> </parameter>
<description> <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> </description>
<requires> <requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and <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> <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> </description>
</constructor> </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> <destructor>
<notes> <notes>
<para>The destructor is applied to every element, and all memory is deallocated</para> <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> <para>A const_local_iterator object can be used to iterate through a single bucket.</para>
</description> </description>
</typedef> </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"> <constructor specifiers="explicit">
<parameter name="n"> <parameter name="n">
<paramtype>size_type</paramtype> <paramtype>size_type</paramtype>
<default><emphasis>implementation-defined</emphasis></default>
</parameter> </parameter>
<parameter name="hf"> <parameter name="hf">
<paramtype>hasher const&amp;</paramtype> <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> <default>allocator_type()</default>
</parameter> </parameter>
<description> <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> </description>
<requires> <requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and <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> <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> </description>
</constructor> </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> <destructor>
<notes> <notes>
<para>The destructor is applied to every element, and all memory is deallocated</para> <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&); 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 // emplace_args
// //
@ -237,9 +247,8 @@ BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
// 2 = boost::container::allocator_traits // 2 = boost::container::allocator_traits
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS) #if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \ # if !defined(BOOST_NO_CXX11_ALLOCATOR)
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) # define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
# elif defined(BOOST_MSVC) # elif defined(BOOST_MSVC)
# if BOOST_MSVC < 1400 # if BOOST_MSVC < 1400
// Use container's allocator_traits for older versions of Visual // 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) #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 {}; template <typename T> struct expr_test<T, sizeof(char)> : T {};
# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \ # define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
@ -412,11 +421,69 @@ namespace boost { namespace unordered { namespace detail {
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> template <typename Alloc, typename T>
struct rebind_wrap 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 # 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) typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
size_type; 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) static pointer allocate(Alloc& a, size_type n)
{ return a.allocate(n); } { return a.allocate(n); }
@ -639,7 +713,7 @@ namespace boost { namespace unordered { namespace detail {
::value>::type ::value>::type
construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x) 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> template <typename T>
@ -673,7 +747,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_construct<Alloc, T>::value>::type boost::unordered::detail::has_construct<Alloc, T>::value>::type
construct(Alloc&, T* p, T const& x) construct(Alloc&, T* p, T const& x)
{ {
new ((void*) p) T(x); new (static_cast<void*>(p)) T(x);
} }
template <typename T> template <typename T>
@ -715,7 +789,7 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same<T, value_type>::value, boost::is_same<T, value_type>::value,
void*>::type = 0) void*>::type = 0)
{ {
new ((void*) p) T(x); new (static_cast<void*>(p)) T(x);
} }
template <typename T> template <typename T>
@ -843,7 +917,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
} }
template <typename Alloc, typename T> 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); 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> 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); boost::unordered::detail::func::destroy(x);
} }
@ -880,7 +954,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
} }
template <typename Alloc, typename T> 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); boost::unordered::detail::func::destroy(x);
} }
@ -1021,7 +1095,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
// For the standard pair constructor. // For the standard pair constructor.
template <typename Alloc, typename T, typename... Args> 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_FWD_REF(Args)... args)
{ {
boost::unordered::detail::func::call_construct(alloc, 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, template <typename Alloc, typename A, typename B,
typename A0, typename A1, typename A2> typename A0, typename A1, typename A2>
inline typename enable_if<use_piecewise<A0>, void>::type 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_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{ {
boost::unordered::detail::func::construct_from_tuple(alloc, 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::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 #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 // Explicitly write out first three overloads for the sake of sane
// error messages. // error messages.
template <typename Alloc, typename T, typename A0> 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) emplace_args1<A0> const& args)
{ {
new((void*) address) T(boost::forward<A0>(args.a0)); new((void*) address) T(boost::forward<A0>(args.a0));
} }
template <typename Alloc, typename T, typename A0, typename A1> 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) emplace_args2<A0, A1> const& args)
{ {
new((void*) address) T( 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> 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) emplace_args3<A0, A1, A2> const& args)
{ {
new((void*) address) T( new((void*) address) T(
@ -1088,7 +1166,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
typename Alloc, typename T, \ typename Alloc, typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \ 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::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \ BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \ > const& args) \
@ -1107,14 +1185,18 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
template <typename Alloc, typename A, typename B, template <typename Alloc, typename A, typename B,
typename A0, typename A1, typename A2> 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, boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
typename enable_if<use_piecewise<A0>, void*>::type = 0) typename enable_if<use_piecewise<A0>, void*>::type = 0)
{ {
boost::unordered::detail::func::construct_from_tuple(alloc, 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::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 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
@ -1165,7 +1247,7 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(!node_); BOOST_ASSERT(!node_);
node_ = p; node_ = p;
node_constructed_ = true; node_constructed_ = true;
boost::unordered::detail::func::destroy_value_impl(alloc_, boost::unordered::detail::func::call_destroy(alloc_,
node_->value_ptr()); node_->value_ptr());
} }
@ -1231,7 +1313,7 @@ namespace boost { namespace unordered { namespace detail {
node_tmp<Alloc>::~node_tmp() node_tmp<Alloc>::~node_tmp()
{ {
if (node_) { if (node_) {
boost::unordered::detail::func::destroy_value_impl(alloc_, boost::unordered::detail::func::call_destroy(alloc_,
node_->value_ptr()); node_->value_ptr());
boost::unordered::detail::func::destroy( boost::unordered::detail::func::destroy(
boost::addressof(*node_)); boost::addressof(*node_));
@ -1242,23 +1324,23 @@ namespace boost { namespace unordered { namespace detail {
namespace boost { namespace unordered { namespace detail { namespace func { 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. // improve implementation later.
template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE> template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer 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); node_constructor<Alloc> a(alloc);
a.create_node(); a.create_node();
construct_value_impl(alloc, a.node_->value_ptr(), construct_from_args(alloc, a.node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_FORWARD); BOOST_UNORDERED_EMPLACE_FORWARD);
return a.release(); return a.release();
} }
template <typename Alloc, typename U> template <typename Alloc, typename U>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer 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); node_constructor<Alloc> a(alloc);
a.create_node(); a.create_node();
@ -1271,29 +1353,33 @@ namespace boost { namespace unordered { namespace detail { namespace func {
// constructor for std::piece_construct with std::tuple. // constructor for std::piece_construct with std::tuple.
template <typename Alloc, typename Key> template <typename Alloc, typename Key>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer 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); node_constructor<Alloc> a(alloc);
a.create_node(); a.create_node();
boost::unordered::detail::func::call_construct( boost::unordered::detail::func::call_construct(alloc,
alloc, boost::addressof(a.node_->value_ptr()->first), boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->first)),
boost::forward<Key>(k)); boost::forward<Key>(k));
boost::unordered::detail::func::call_construct( boost::unordered::detail::func::call_construct(alloc,
alloc, boost::addressof(a.node_->value_ptr()->second)); boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->second)));
return a.release(); return a.release();
} }
template <typename Alloc, typename Key, typename Mapped> template <typename Alloc, typename Key, typename Mapped>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer 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); node_constructor<Alloc> a(alloc);
a.create_node(); a.create_node();
boost::unordered::detail::func::call_construct( boost::unordered::detail::func::call_construct(alloc,
alloc, boost::addressof(a.node_->value_ptr()->first), boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->first)),
boost::forward<Key>(k)); boost::forward<Key>(k));
boost::unordered::detail::func::call_construct( boost::unordered::detail::func::call_construct(alloc,
alloc, boost::addressof(a.node_->value_ptr()->second), boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->second)),
boost::forward<Mapped>(m)); boost::forward<Mapped>(m));
return a.release(); return a.release();
} }

View File

@ -61,7 +61,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
private: private:
#endif #endif
typedef typename Node::node_pointer node_pointer; typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
node_pointer ptr_; node_pointer ptr_;
std::size_t bucket_; std::size_t bucket_;
std::size_t bucket_count_; std::size_t bucket_count_;
@ -72,8 +71,8 @@ namespace boost { namespace unordered { namespace iterator_detail {
l_iterator() BOOST_NOEXCEPT : ptr_() {} l_iterator() BOOST_NOEXCEPT : ptr_() {}
l_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
: ptr_(x.node_), bucket_(b), bucket_count_(c) {} : ptr_(n), bucket_(b), bucket_count_(c) {}
value_type& operator*() const { value_type& operator*() const {
return ptr_->value(); return ptr_->value();
@ -120,7 +119,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
private: private:
typedef typename Node::node_pointer node_pointer; typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
node_pointer ptr_; node_pointer ptr_;
std::size_t bucket_; std::size_t bucket_;
std::size_t bucket_count_; std::size_t bucket_count_;
@ -131,8 +129,8 @@ namespace boost { namespace unordered { namespace iterator_detail {
cl_iterator() BOOST_NOEXCEPT : ptr_() {} cl_iterator() BOOST_NOEXCEPT : ptr_() {}
cl_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT : cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
ptr_(x.node_), bucket_(b), bucket_count_(c) {} ptr_(n), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator< cl_iterator(boost::unordered::iterator_detail::l_iterator<
Node, Policy> const& x) BOOST_NOEXCEPT : Node, Policy> const& x) BOOST_NOEXCEPT :
@ -186,10 +184,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename> template <typename>
friend struct boost::unordered::iterator_detail::c_iterator; 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> template <typename>
friend struct boost::unordered::detail::table; friend struct boost::unordered::detail::table;
template <typename> template <typename>
@ -359,21 +353,6 @@ namespace boost { namespace unordered { namespace detail {
template <typename T> template <typename T>
inline node_pointer copy_of(T const& v) { 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_) { if (nodes_) {
constructor_.reclaim(pop_node()); constructor_.reclaim(pop_node());
} }
@ -387,22 +366,6 @@ namespace boost { namespace unordered { namespace detail {
template <typename T> template <typename T>
inline node_pointer move_copy_of(T& v) { 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_) { if (nodes_) {
constructor_.reclaim(pop_node()); constructor_.reclaim(pop_node());
} }
@ -428,7 +391,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer p = nodes_; node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_); 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()); p->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*p)); boost::unordered::detail::func::destroy(boost::addressof(*p));
node_allocator_traits::deallocate(constructor_.alloc_, p, 1); 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> template <typename A, typename T>
struct pick_grouped_node struct pick_grouped_node
{ {
typedef typename boost::remove_const<T>::type nonconst;
typedef boost::unordered::detail::allocator_traits< typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A, 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; > tentative_node_traits;
typedef boost::unordered::detail::allocator_traits< typedef boost::unordered::detail::allocator_traits<
@ -120,7 +122,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket >::type boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits; > tentative_bucket_traits;
typedef pick_grouped_node2<A, T, typedef pick_grouped_node2<A, nonconst,
typename tentative_node_traits::pointer, typename tentative_node_traits::pointer,
typename tentative_bucket_traits::pointer> pick; typename tentative_bucket_traits::pointer> pick;
@ -186,48 +188,58 @@ namespace boost { namespace unordered { namespace detail {
this->move_init(x); 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 // Accessors
template <class Key, class Pred> template <class Key, class Pred>
iterator find_node_impl( node_pointer find_node_impl(
std::size_t key_hash, std::size_t key_hash,
Key const& k, Key const& k,
Pred const& eq) const Pred const& eq) const
{ {
std::size_t bucket_index = this->hash_to_bucket(key_hash); 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 (;;) 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 (key_hash == node_hash)
{ {
if (eq(k, this->get_key(*n))) if (eq(k, this->get_key(n->value())))
return n; return n;
} }
else else
{ {
if (this->hash_to_bucket(node_hash) != bucket_index) 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 std::size_t count(key_type const& k) const
{ {
iterator n = this->find_node(k); node_pointer n = this->find_node(k);
if (!n.node_) return 0; if (!n) return 0;
std::size_t x = 0; std::size_t x = 0;
node_pointer it = n.node_; node_pointer it = n;
do { do {
it = it->group_prev_; it = it->group_prev_;
++x; ++x;
} while(it != n.node_); } while(it != n);
return x; return x;
} }
@ -235,9 +247,8 @@ namespace boost { namespace unordered { namespace detail {
std::pair<iterator, iterator> std::pair<iterator, iterator>
equal_range(key_type const& k) const equal_range(key_type const& k) const
{ {
iterator n = this->find_node(k); node_pointer n = this->find_node(k);
return std::make_pair( return std::make_pair(iterator(n), iterator(n ? next_group(n) : n));
n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
} }
// Equality // Equality
@ -246,12 +257,12 @@ namespace boost { namespace unordered { namespace detail {
{ {
if(this->size_ != other.size_) return false; 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); node_pointer n2 = other.find_node(other.get_key(n1->value()));
if (!n2.node_) return false; if (!n2) return false;
iterator end1(n1.node_->group_prev_->next_); node_pointer end1 = next_group(n1);
iterator end2(n2.node_->group_prev_->next_); node_pointer end2 = next_group(n2);
if (!group_equals(n1, end1, n2, end2)) return false; if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1; n1 = end1;
} }
@ -259,24 +270,24 @@ namespace boost { namespace unordered { namespace detail {
return true; return true;
} }
static bool group_equals(iterator n1, iterator end1, static bool group_equals(node_pointer n1, node_pointer end1,
iterator n2, iterator end2) node_pointer n2, node_pointer end2)
{ {
for(;;) for(;;)
{ {
if (*n1 != *n2) break; if (n1->value() != n2->value()) break;
++n1; n1 = next_node(n1);
++n2; n2 = next_node(n2);
if (n1 == end1) return n2 == end2; if (n1 == end1) return n2 == end2;
if (n2 == end2) return false; if (n2 == end2) return false;
} }
for(iterator n1a = n1, n2a = n2;;) for(node_pointer n1a = n1, n2a = n2;;)
{ {
++n1a; n1a = next_node(n1a);
++n2a; n2a = next_node(n2a);
if (n1a == end1) if (n1a == end1)
{ {
@ -287,35 +298,34 @@ namespace boost { namespace unordered { namespace detail {
if (n2a == end2) return false; if (n2a == end2) return false;
} }
iterator start = n1; node_pointer start = n1;
for(;n1 != end1; ++n1) for(;n1 != end1; n1 = next_node(n1))
{ {
value_type const& v = *n1; value_type const& v = n1->value();
if (find(start, n1, v)) continue; if (!find(start, n1, v)) {
std::size_t matches = count_equal(n2, end2, v); std::size_t matches = count_equal(n2, end2, v);
if (!matches) return false; if (!matches) return false;
iterator next = n1; if (matches != 1 + count_equal(next_node(n1), end1, v)) return false;
++next; }
if (matches != 1 + count_equal(next, end1, v)) return false;
} }
return true; 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) for(;n != end; n = next_node(n))
if (*n == v) if (n->value() == v)
return true; return true;
return false; 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) value_type const& v)
{ {
std::size_t count = 0; std::size_t count = 0;
for(;n != end; ++n) for(;n != end; n = next_node(n))
if (*n == v) ++count; if (n->value() == v) ++count;
return count; return count;
} }
@ -334,17 +344,17 @@ namespace boost { namespace unordered { namespace detail {
pos->group_prev_ = n; pos->group_prev_ = n;
} }
inline iterator add_node( inline node_pointer add_node(
node_pointer n, node_pointer n,
std::size_t key_hash, std::size_t key_hash,
iterator pos) node_pointer pos)
{ {
n->hash_ = key_hash; n->hash_ = key_hash;
if (pos.node_) { if (pos) {
this->add_to_node_group(n, pos.node_); this->add_to_node_group(n, pos);
if (n->next_) { if (n->next_) {
std::size_t next_bucket = this->hash_to_bucket( 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)) { if (next_bucket != this->hash_to_bucket(key_hash)) {
this->get_bucket(next_bucket)->next_ = n; this->get_bucket(next_bucket)->next_ = n;
} }
@ -360,7 +370,7 @@ namespace boost { namespace unordered { namespace detail {
if (start_node->next_) { if (start_node->next_) {
this->get_bucket(this->hash_to_bucket( this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_ next_node(start_node)->hash_
))->next_ = n; ))->next_ = n;
} }
@ -375,10 +385,10 @@ namespace boost { namespace unordered { namespace detail {
} }
} }
++this->size_; ++this->size_;
return iterator(n); return n;
} }
inline iterator add_using_hint( inline node_pointer add_using_hint(
node_pointer n, node_pointer n,
node_pointer hint) node_pointer hint)
{ {
@ -386,13 +396,13 @@ namespace boost { namespace unordered { namespace detail {
this->add_to_node_group(n, hint); this->add_to_node_group(n, hint);
if (n->next_ != hint && n->next_) { if (n->next_ != hint && n->next_) {
std::size_t next_bucket = this->hash_to_bucket( 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_)) { if (next_bucket != this->hash_to_bucket(n->hash_)) {
this->get_bucket(next_bucket)->next_ = n; this->get_bucket(next_bucket)->next_ = n;
} }
} }
++this->size_; ++this->size_;
return iterator(n); return n;
} }
@ -432,7 +442,7 @@ namespace boost { namespace unordered { namespace detail {
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS) iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{ {
return iterator(emplace_impl( 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))); 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) iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
{ {
return iterator(emplace_hint_impl(hint, 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))); this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
} }
@ -449,9 +459,9 @@ namespace boost { namespace unordered { namespace detail {
node_tmp a(n, this->node_alloc()); node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value()); key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k); 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); 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) 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()); key_type const& k = this->get_key(a.node_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) { if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
this->reserve_for_insert(this->size_ + 1); 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 { else {
std::size_t key_hash = this->hash(k); 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); 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()); node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value()); key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k); 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); 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)); std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
if(distance == 1) { if(distance == 1) {
emplace_impl( emplace_impl(
boost::unordered::detail::func::construct_value( boost::unordered::detail::func::construct_node(
this->node_alloc(), *i)); this->node_alloc(), *i));
} }
else { else {
@ -502,7 +512,7 @@ namespace boost { namespace unordered { namespace detail {
for (; i != j; ++i) { for (; i != j; ++i) {
emplace_impl_no_rehash( emplace_impl_no_rehash(
boost::unordered::detail::func::construct_value( boost::unordered::detail::func::construct_node(
this->node_alloc(), *i)); this->node_alloc(), *i));
} }
} }
@ -514,7 +524,7 @@ namespace boost { namespace unordered { namespace detail {
{ {
for (; i != j; ++i) { for (; i != j; ++i) {
emplace_impl( emplace_impl(
boost::unordered::detail::func::construct_value( boost::unordered::detail::func::construct_node(
this->node_alloc(), *i)); this->node_alloc(), *i));
} }
} }
@ -533,21 +543,21 @@ namespace boost { namespace unordered { namespace detail {
link_pointer prev = this->get_previous_start(bucket_index); link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0; if (!prev) return 0;
node_pointer first_node;
for (;;) for (;;)
{ {
if (!prev->next_) return 0; if (!prev->next_) return 0;
std::size_t node_hash = first_node = next_node(prev);
static_cast<node_pointer>(prev->next_)->hash_; std::size_t node_hash = first_node->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index) if (this->hash_to_bucket(node_hash) != bucket_index)
return 0; return 0;
if (node_hash == key_hash && if (node_hash == key_hash &&
this->key_eq()(k, this->get_key( this->key_eq()(k, this->get_key(first_node->value())))
static_cast<node_pointer>(prev->next_)->value())))
break; 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_; link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end); 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) iterator erase(c_iterator r)
{ {
BOOST_ASSERT(r.node_); BOOST_ASSERT(r.node_);
iterator next(r.node_); node_pointer next = next_node(r.node_);
++next; erase_nodes(r.node_, next);
erase_nodes(r.node_, next.node_); return iterator(next);
return next;
} }
iterator erase_range(c_iterator r1, c_iterator r2) iterator erase_range(c_iterator r1, c_iterator r2)
@ -586,13 +595,12 @@ namespace boost { namespace unordered { namespace detail {
if (!prev) { if (!prev) {
prev = this->get_previous_start(bucket_index); prev = this->get_previous_start(bucket_index);
while (prev->next_ != i) while (prev->next_ != i)
prev = static_cast<node_pointer>(prev->next_)->group_prev_; prev = next_node(prev)->group_prev_;
} }
// Delete the nodes. // Delete the nodes.
do { do {
link_pointer group_end = link_pointer group_end = next_group(next_node(prev));
static_cast<node_pointer>(prev->next_)->group_prev_->next_;
this->delete_nodes(prev, group_end); this->delete_nodes(prev, group_end);
bucket_index = this->fix_bucket(bucket_index, prev); bucket_index = this->fix_bucket(bucket_index, prev);
} while(prev->next_ != j); } while(prev->next_ != j);
@ -632,17 +640,17 @@ namespace boost { namespace unordered { namespace detail {
void copy_buckets(table const& src) { void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_); this->create_buckets(this->bucket_count_);
for (iterator n = src.begin(); n.node_;) { for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n.node_->hash_; std::size_t key_hash = n->hash_;
iterator group_end(n.node_->group_prev_->next_); node_pointer group_end(next_group(n));
iterator pos = this->add_node( node_pointer pos = this->add_node(
boost::unordered::detail::func::construct_value( boost::unordered::detail::func::construct_node(
this->node_alloc(), *n), key_hash, iterator()); this->node_alloc(), n->value()), key_hash, node_pointer());
for (++n; n != group_end; ++n) for (n = next_node(n); n != group_end; n = next_node(n))
{ {
this->add_node( this->add_node(
boost::unordered::detail::func::construct_value( boost::unordered::detail::func::construct_node(
this->node_alloc(), *n), key_hash, pos); this->node_alloc(), n->value()), key_hash, pos);
} }
} }
} }
@ -650,43 +658,43 @@ namespace boost { namespace unordered { namespace detail {
void move_buckets(table const& src) { void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_); this->create_buckets(this->bucket_count_);
for (iterator n = src.begin(); n.node_;) { for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n.node_->hash_; std::size_t key_hash = n->hash_;
iterator group_end(n.node_->group_prev_->next_); node_pointer group_end(next_group(n));
iterator pos = this->add_node( node_pointer pos = this->add_node(
boost::unordered::detail::func::construct_value( boost::unordered::detail::func::construct_node(
this->node_alloc(), boost::move(*n)), key_hash, iterator()); this->node_alloc(), boost::move(n->value())), key_hash, node_pointer());
for (++n; n != group_end; ++n) for (n = next_node(n); n != group_end; n = next_node(n))
{ {
this->add_node( this->add_node(
boost::unordered::detail::func::construct_value( boost::unordered::detail::func::construct_node(
this->node_alloc(), boost::move(*n)), key_hash, pos); this->node_alloc(), boost::move(n->value())), key_hash, pos);
} }
} }
} }
void assign_buckets(table const& src) { void assign_buckets(table const& src) {
node_holder<node_allocator> holder(*this); node_holder<node_allocator> holder(*this);
for (iterator n = src.begin(); n.node_;) { for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n.node_->hash_; std::size_t key_hash = n->hash_;
iterator group_end(n.node_->group_prev_->next_); node_pointer group_end(next_group(n));
iterator pos = this->add_node(holder.copy_of(*n), key_hash, iterator()); node_pointer pos = this->add_node(holder.copy_of(n->value()), key_hash, node_pointer());
for (++n; n != group_end; ++n) 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) { void move_assign_buckets(table& src) {
node_holder<node_allocator> holder(*this); node_holder<node_allocator> holder(*this);
for (iterator n = src.begin(); n.node_;) { for (node_pointer n = src.begin(); n;) {
std::size_t key_hash = n.node_->hash_; std::size_t key_hash = n->hash_;
iterator group_end(n.node_->group_prev_->next_); node_pointer group_end(next_group(n));
iterator pos = this->add_node(holder.move_copy_of(*n), key_hash, iterator()); node_pointer pos = this->add_node(holder.move_copy_of(n->value()), key_hash, node_pointer());
for (++n; n != group_end; ++n) 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); this->create_buckets(num_buckets);
link_pointer prev = this->get_previous_start(); link_pointer prev = this->get_previous_start();
while (prev->next_) while (prev->next_)
prev = place_in_bucket(*this, prev, prev = place_in_bucket(*this, prev, next_node(prev)->group_prev_);
static_cast<node_pointer>(prev->next_)->group_prev_);
} }
// Iterate through the nodes placing them in the correct buckets. // Iterate through the nodes placing them in the correct buckets.

View File

@ -31,6 +31,15 @@ namespace boost { namespace unordered { namespace detail {
extractor; extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy; 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> template <typename A, typename K, typename M, typename H, typename P>
@ -56,6 +65,15 @@ namespace boost { namespace unordered { namespace detail {
extractor; extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy; 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 boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy; 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> 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 boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy; 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::table table_impl;
typedef typename Types::link_pointer link_pointer; typedef typename Types::link_pointer link_pointer;
typedef typename Types::policy policy; 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< typedef boost::unordered::detail::functions<
typename Types::hasher, typename Types::hasher,
@ -110,15 +114,6 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::node_tmp<node_allocator> typedef boost::unordered::detail::node_tmp<node_allocator>
node_tmp; 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 // Members
@ -130,6 +125,13 @@ namespace boost { namespace unordered { namespace detail {
std::size_t max_load_; std::size_t max_load_;
bucket_pointer buckets_; bucket_pointer buckets_;
////////////////////////////////////////////////////////////////////////
// Node functions
static inline node_pointer next_node(link_pointer n) {
return static_cast<node_pointer>(n->next_);
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Data access // Data access
@ -176,16 +178,16 @@ namespace boost { namespace unordered { namespace detail {
return get_bucket(bucket_index)->next_; 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); 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 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 std::size_t bucket_size(std::size_t index) const
{ {
iterator it = begin(index); node_pointer n = begin(index);
if (!it.node_) return 0; if (!n) return 0;
std::size_t count = 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; ++count;
++it; n = next_node(n);
} }
return count; return count;
@ -462,7 +464,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer n = static_cast<node_pointer>(prev->next_); node_pointer n = static_cast<node_pointer>(prev->next_);
prev->next_ = n->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()); n->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*n)); boost::unordered::detail::func::destroy(boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1); node_allocator_traits::deallocate(node_alloc(), n, 1);
@ -698,7 +700,7 @@ namespace boost { namespace unordered { namespace detail {
// Find Node // Find Node
template <typename Key, typename Hash, typename Pred> template <typename Key, typename Hash, typename Pred>
iterator generic_find_node( node_pointer generic_find_node(
Key const& k, Key const& k,
Hash const& hf, Hash const& hf,
Pred const& eq) const Pred const& eq) const
@ -707,7 +709,7 @@ namespace boost { namespace unordered { namespace detail {
find_node_impl(policy::apply_hash(hf, k), k, eq); find_node_impl(policy::apply_hash(hf, k), k, eq);
} }
iterator find_node( node_pointer find_node(
std::size_t key_hash, std::size_t key_hash,
key_type const& k) const key_type const& k) const
{ {
@ -715,23 +717,12 @@ namespace boost { namespace unordered { namespace detail {
find_node_impl(key_hash, k, this->key_eq()); 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)-> return static_cast<table_impl const*>(this)->
find_node_impl(hash(k), k, this->key_eq()); 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 // Reserve and rehash
void reserve_for_insert(std::size_t); void reserve_for_insert(std::size_t);

View File

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

View File

@ -82,12 +82,23 @@ namespace unordered
// constructors // constructors
unordered_map();
explicit unordered_map( explicit unordered_map(
size_type = boost::unordered::detail::default_bucket_count, size_type,
const hasher& = hasher(), const hasher& = hasher(),
const key_equal& = key_equal(), const key_equal& = key_equal(),
const allocator_type& = allocator_type()); 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&); explicit unordered_map(allocator_type const&);
template <class InputIt> template <class InputIt>
@ -108,11 +119,25 @@ namespace unordered
const key_equal&, const key_equal&,
const allocator_type&); 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 // copy/move constructors
unordered_map(unordered_map const&); unordered_map(unordered_map const&);
unordered_map(unordered_map const&, allocator_type 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) #if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map(BOOST_RV_REF(unordered_map) other) unordered_map(BOOST_RV_REF(unordered_map) other)
@ -128,10 +153,6 @@ namespace unordered
} }
#endif #endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map( unordered_map(
std::initializer_list<value_type>, std::initializer_list<value_type>,
@ -139,6 +160,15 @@ namespace unordered
const hasher& = hasher(), const hasher& = hasher(),
const key_equal&l = key_equal(), const key_equal&l = key_equal(),
const allocator_type& = allocator_type()); 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 #endif
// Destructor // Destructor
@ -202,12 +232,12 @@ namespace unordered
iterator begin() BOOST_NOEXCEPT iterator begin() BOOST_NOEXCEPT
{ {
return table_.begin(); return iterator(table_.begin());
} }
const_iterator begin() const BOOST_NOEXCEPT const_iterator begin() const BOOST_NOEXCEPT
{ {
return table_.begin(); return const_iterator(table_.begin());
} }
iterator end() BOOST_NOEXCEPT iterator end() BOOST_NOEXCEPT
@ -222,7 +252,7 @@ namespace unordered
const_iterator cbegin() const BOOST_NOEXCEPT const_iterator cbegin() const BOOST_NOEXCEPT
{ {
return table_.begin(); return const_iterator(table_.begin());
} }
const_iterator cend() const BOOST_NOEXCEPT const_iterator cend() const BOOST_NOEXCEPT
@ -565,12 +595,23 @@ namespace unordered
// constructors // constructors
unordered_multimap();
explicit unordered_multimap( explicit unordered_multimap(
size_type = boost::unordered::detail::default_bucket_count, size_type,
const hasher& = hasher(), const hasher& = hasher(),
const key_equal& = key_equal(), const key_equal& = key_equal(),
const allocator_type& = allocator_type()); 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&); explicit unordered_multimap(allocator_type const&);
template <class InputIt> template <class InputIt>
@ -591,11 +632,25 @@ namespace unordered
const key_equal&, const key_equal&,
const allocator_type&); 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 // copy/move constructors
unordered_multimap(unordered_multimap const&); unordered_multimap(unordered_multimap const&);
unordered_multimap(unordered_multimap const&, allocator_type 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) #if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap(BOOST_RV_REF(unordered_multimap) other) unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
@ -611,10 +666,6 @@ namespace unordered
} }
#endif #endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap( unordered_multimap(
std::initializer_list<value_type>, std::initializer_list<value_type>,
@ -622,6 +673,15 @@ namespace unordered
const hasher& = hasher(), const hasher& = hasher(),
const key_equal&l = key_equal(), const key_equal&l = key_equal(),
const allocator_type& = allocator_type()); 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 #endif
// Destructor // Destructor
@ -686,12 +746,12 @@ namespace unordered
iterator begin() BOOST_NOEXCEPT iterator begin() BOOST_NOEXCEPT
{ {
return table_.begin(); return iterator(table_.begin());
} }
const_iterator begin() const BOOST_NOEXCEPT const_iterator begin() const BOOST_NOEXCEPT
{ {
return table_.begin(); return const_iterator(table_.begin());
} }
iterator end() BOOST_NOEXCEPT iterator end() BOOST_NOEXCEPT
@ -706,7 +766,7 @@ namespace unordered
const_iterator cbegin() const BOOST_NOEXCEPT const_iterator cbegin() const BOOST_NOEXCEPT
{ {
return table_.begin(); return const_iterator(table_.begin());
} }
const_iterator cend() const BOOST_NOEXCEPT 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> template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map( unordered_map<K,T,H,P,A>::unordered_map(
size_type n, const hasher &hf, const key_equal &eql, 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> template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(allocator_type const& a) unordered_map<K,T,H,P,A>::unordered_map(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count, : table_(boost::unordered::detail::default_bucket_count,
@ -1059,6 +1140,31 @@ namespace unordered
table_.insert_range(f, l); 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> template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {} 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> template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map( 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()) : table_(other.table_, a, boost::unordered::detail::move_tag())
{ {
} }
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1094,6 +1196,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end()); 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> 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=( unordered_map<K,T,H,P,A>& unordered_map<K,T,H,P,A>::operator=(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
@ -1208,14 +1334,14 @@ namespace unordered
typename unordered_map<K,T,H,P,A>::iterator typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::find(const key_type& k) 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> template <class K, class T, class H, class P, class A>
typename unordered_map<K,T,H,P,A>::const_iterator typename unordered_map<K,T,H,P,A>::const_iterator
unordered_map<K,T,H,P,A>::find(const key_type& k) const 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> template <class K, class T, class H, class P, class A>
@ -1227,7 +1353,7 @@ namespace unordered
CompatibleHash const& hash, CompatibleHash const& hash,
CompatiblePredicate const& eq) 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> template <class K, class T, class H, class P, class A>
@ -1239,7 +1365,7 @@ namespace unordered
CompatibleHash const& hash, CompatibleHash const& hash,
CompatiblePredicate const& eq) const 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> 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> template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap( unordered_multimap<K,T,H,P,A>::unordered_multimap(
size_type n, const hasher &hf, const key_equal &eql, 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> template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(allocator_type const& a) unordered_multimap<K,T,H,P,A>::unordered_multimap(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count, : table_(boost::unordered::detail::default_bucket_count,
@ -1392,6 +1539,31 @@ namespace unordered
table_.insert_range(f, l); 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> template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {} 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> template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap( 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()) : table_(other.table_, a, boost::unordered::detail::move_tag())
{ {
} }
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@ -1427,6 +1595,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end()); 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> 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=( unordered_multimap<K,T,H,P,A>& unordered_multimap<K,T,H,P,A>::operator=(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
@ -1520,14 +1712,14 @@ namespace unordered
typename unordered_multimap<K,T,H,P,A>::iterator typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k) 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> template <class K, class T, class H, class P, class A>
typename unordered_multimap<K,T,H,P,A>::const_iterator typename unordered_multimap<K,T,H,P,A>::const_iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k) const 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> template <class K, class T, class H, class P, class A>
@ -1539,7 +1731,7 @@ namespace unordered
CompatibleHash const& hash, CompatibleHash const& hash,
CompatiblePredicate const& eq) 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> template <class K, class T, class H, class P, class A>
@ -1551,7 +1743,7 @@ namespace unordered
CompatibleHash const& hash, CompatibleHash const& hash,
CompatiblePredicate const& eq) const 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> 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 std::ptrdiff_t difference_type;
typedef typename table::cl_iterator const_local_iterator; 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 const_iterator;
typedef typename table::c_iterator iterator; typedef typename table::iterator iterator;
private: private:
@ -79,12 +79,23 @@ namespace unordered
// constructors // constructors
unordered_set();
explicit unordered_set( explicit unordered_set(
size_type = boost::unordered::detail::default_bucket_count, size_type,
const hasher& = hasher(), const hasher& = hasher(),
const key_equal& = key_equal(), const key_equal& = key_equal(),
const allocator_type& = allocator_type()); 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&); explicit unordered_set(allocator_type const&);
template <class InputIt> template <class InputIt>
@ -105,11 +116,25 @@ namespace unordered
const key_equal&, const key_equal&,
const allocator_type&); 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 // copy/move constructors
unordered_set(unordered_set const&); unordered_set(unordered_set const&);
unordered_set(unordered_set const&, allocator_type 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) #if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set(BOOST_RV_REF(unordered_set) other) unordered_set(BOOST_RV_REF(unordered_set) other)
@ -125,10 +150,6 @@ namespace unordered
} }
#endif #endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set( unordered_set(
std::initializer_list<value_type>, std::initializer_list<value_type>,
@ -136,6 +157,15 @@ namespace unordered
const hasher& = hasher(), const hasher& = hasher(),
const key_equal&l = key_equal(), const key_equal&l = key_equal(),
const allocator_type& = allocator_type()); 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 #endif
// Destructor // Destructor
@ -199,12 +229,12 @@ namespace unordered
iterator begin() BOOST_NOEXCEPT iterator begin() BOOST_NOEXCEPT
{ {
return table_.begin(); return iterator(table_.begin());
} }
const_iterator begin() const BOOST_NOEXCEPT const_iterator begin() const BOOST_NOEXCEPT
{ {
return table_.begin(); return const_iterator(table_.begin());
} }
iterator end() BOOST_NOEXCEPT iterator end() BOOST_NOEXCEPT
@ -219,7 +249,7 @@ namespace unordered
const_iterator cbegin() const BOOST_NOEXCEPT const_iterator cbegin() const BOOST_NOEXCEPT
{ {
return table_.begin(); return const_iterator(table_.begin());
} }
const_iterator cend() const BOOST_NOEXCEPT const_iterator cend() const BOOST_NOEXCEPT
@ -536,9 +566,9 @@ namespace unordered
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef typename table::cl_iterator const_local_iterator; 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 const_iterator;
typedef typename table::c_iterator iterator; typedef typename table::iterator iterator;
private: private:
@ -548,12 +578,23 @@ namespace unordered
// constructors // constructors
unordered_multiset();
explicit unordered_multiset( explicit unordered_multiset(
size_type = boost::unordered::detail::default_bucket_count, size_type,
const hasher& = hasher(), const hasher& = hasher(),
const key_equal& = key_equal(), const key_equal& = key_equal(),
const allocator_type& = allocator_type()); 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&); explicit unordered_multiset(allocator_type const&);
template <class InputIt> template <class InputIt>
@ -574,11 +615,25 @@ namespace unordered
const key_equal&, const key_equal&,
const allocator_type&); 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 // copy/move constructors
unordered_multiset(unordered_multiset const&); unordered_multiset(unordered_multiset const&);
unordered_multiset(unordered_multiset const&, allocator_type 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) #if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset(BOOST_RV_REF(unordered_multiset) other) unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
@ -594,10 +649,6 @@ namespace unordered
} }
#endif #endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset( unordered_multiset(
std::initializer_list<value_type>, std::initializer_list<value_type>,
@ -605,6 +656,15 @@ namespace unordered
const hasher& = hasher(), const hasher& = hasher(),
const key_equal&l = key_equal(), const key_equal&l = key_equal(),
const allocator_type& = allocator_type()); 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 #endif
// Destructor // 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> template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set( unordered_set<T,H,P,A>::unordered_set(
size_type n, const hasher &hf, const key_equal &eql, 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> template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(allocator_type const& a) unordered_set<T,H,P,A>::unordered_set(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count, : table_(boost::unordered::detail::default_bucket_count,
@ -1033,6 +1114,31 @@ namespace unordered
table_.insert_range(f, l); 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> template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {} 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> template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set( 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()) : table_(other.table_, a, boost::unordered::detail::move_tag())
{ {
} }
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1068,6 +1170,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end()); 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> template <class T, class H, class P, class A>
unordered_set<T,H,P,A>& unordered_set<T,H,P,A>::operator=( unordered_set<T,H,P,A>& unordered_set<T,H,P,A>::operator=(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
@ -1161,7 +1287,7 @@ namespace unordered
typename unordered_set<T,H,P,A>::const_iterator typename unordered_set<T,H,P,A>::const_iterator
unordered_set<T,H,P,A>::find(const key_type& k) const 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> template <class T, class H, class P, class A>
@ -1173,7 +1299,7 @@ namespace unordered
CompatibleHash const& hash, CompatibleHash const& hash,
CompatiblePredicate const& eq) const 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> 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> template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset( unordered_multiset<T,H,P,A>::unordered_multiset(
size_type n, const hasher &hf, const key_equal &eql, 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> template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a) unordered_multiset<T,H,P,A>::unordered_multiset(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count, : table_(boost::unordered::detail::default_bucket_count,
@ -1317,6 +1464,31 @@ namespace unordered
table_.insert_range(f, l); 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> template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {} 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> template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset( 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()) : table_(other.table_, a, boost::unordered::detail::move_tag())
{ {
} }
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@ -1352,6 +1520,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end()); 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> template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>& unordered_multiset<T,H,P,A>::operator=( unordered_multiset<T,H,P,A>& unordered_multiset<T,H,P,A>::operator=(
std::initializer_list<value_type> list) std::initializer_list<value_type> list)
@ -1445,7 +1637,7 @@ namespace unordered
typename unordered_multiset<T,H,P,A>::const_iterator typename unordered_multiset<T,H,P,A>::const_iterator
unordered_multiset<T,H,P,A>::find(const key_type& k) const 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> template <class T, class H, class P, class A>
@ -1457,7 +1649,7 @@ namespace unordered
CompatibleHash const& hash, CompatibleHash const& hash,
CompatiblePredicate const& eq) const 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> 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>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>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>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 ; #alias framework : /boost/test//boost_unit_test_framework ;
@ -27,6 +28,9 @@ test-suite unordered
[ run unordered/minimal_allocator.cpp ] [ run unordered/minimal_allocator.cpp ]
[ run unordered/compile_set.cpp ] [ run unordered/compile_set.cpp ]
[ run unordered/compile_map.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/noexcept_tests.cpp ]
[ run unordered/link_test_1.cpp unordered/link_test_2.cpp ] [ run unordered/link_test_1.cpp unordered/link_test_2.cpp ]
[ run unordered/incomplete_test.cpp ] [ run unordered/incomplete_test.cpp ]

View File

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

View File

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

View File

@ -447,7 +447,7 @@ namespace minimal
{ {
public: public:
typedef T value_type; 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() {} cxx11_allocator() {}
template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {} template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}

View File

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

View File

@ -23,13 +23,13 @@ template class boost::unordered_set<
std::equal_to<int>, std::equal_to<int>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
template class boost::unordered_multiset< template class boost::unordered_multiset<
int, int const,
boost::hash<int>, boost::hash<int>,
std::equal_to<int>, std::equal_to<int>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
template class boost::unordered_set< template class boost::unordered_set<
test::minimal::assignable, test::minimal::assignable const,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<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>( static_cast<comparison_type>(
(std::numeric_limits<difference_type>::max)())); (std::numeric_limits<difference_type>::max)()));
// Constructors
// I don't test the runtime post-conditions here. // 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; X u;
BOOST_TEST(u.size() == 0); BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0); BOOST_TEST(X().size() == 0);
@ -112,6 +123,8 @@ void container_test(X& r, T const&)
sink(X(a)); sink(X(a));
X u2(a); X u2(a);
X u3 = a; X u3 = a;
X u4(rvalue(a_const));
X u5 = rvalue(a_const);
a.swap(b); a.swap(b);
boost::swap(a, 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; typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
test::check_return_type<allocator_type>::equals(a_const.get_allocator()); 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: // Avoid unused variable warnings:
sink(u); sink(u);
sink(u2); sink(u2);
sink(u3); sink(u3);
sink(u4);
sink(u5);
sink(c);
sink(c2);
sink(c3);
} }
template <class X> 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, v);
r.emplace(k_lvalue, v_lvalue); r.emplace(k_lvalue, v_lvalue);
r.emplace(rvalue(k), rvalue(v)); r.emplace(rvalue(k), rvalue(v));
r.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple(v));
} }
template <class X> template <class X>
@ -355,6 +384,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<const_local_iterator>::type boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference; const_local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value)); BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >(); //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, BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>::value)); const_iterator_reference>::value));
X a;
allocator_type m = a.get_allocator();
// Constructors
X(10, hf, eq); X(10, hf, eq);
X a(10, hf, eq); X a1(10, hf, eq);
X(10, hf); X(10, hf);
X a2(10, hf); X a2(10, hf);
X(10); X(10);
@ -396,6 +431,15 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
X(); X();
X a4; 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)); test::check_return_type<size_type>::equals(a.erase(k));
const_iterator q1 = a.cbegin(), q2 = a.cend(); 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: // Avoid unused variable warnings:
sink(a); sink(a);
sink(a1);
sink(a2); sink(a2);
sink(a3); sink(a3);
sink(a4); sink(a4);
sink(a1a);
sink(a2a);
sink(a3a);
sink(a4a);
} }
template <class X, class Key, class T, class Hash, class Pred> 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::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
X a; X a;
allocator_type m = a.get_allocator();
BOOST_DEDUCED_TYPENAME X::value_type* i = 0; BOOST_DEDUCED_TYPENAME X::value_type* i = 0;
BOOST_DEDUCED_TYPENAME X::value_type* j = 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 a5(i, j, 10, hf, eq);
X(i, j, 10, hf); X(i, j, 10, hf);
X a6(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(i, j);
X a8(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; X const b;
sink(X(b)); sink(X(b));
X a9(b); X a9(b);
a = b; a = b;
sink(X(b, m));
X a9a(b, m);
const_iterator q = a.cbegin(); const_iterator q = a.cbegin();
test::check_return_type<iterator>::equals(a.insert(q, t)); 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(a7);
sink(a8); sink(a8);
sink(a9); sink(a9);
sink(a5a);
sink(a6a);
sink(a7a);
sink(a9a);
} }
template <class X, class Key, class T, class Hash, class Pred> 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::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_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) #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x1(rvalue_default<X>()); 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); x2 = boost::move(x1);
#endif #endif
X a;
allocator_type m = a.get_allocator();
test::minimal::constructor_param* i = 0; test::minimal::constructor_param* i = 0;
test::minimal::constructor_param* j = 0; test::minimal::constructor_param* j = 0;
// Constructors
X(i, j, 10, hf, eq); X(i, j, 10, hf, eq);
X a5(i, j, 10, hf, eq); X a5(i, j, 10, hf, eq);
X(i, j, 10, hf); 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(i, j);
X a8(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(); 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(a6);
sink(a7); sink(a7);
sink(a8); sink(a8);
sink(a5a);
sink(a6a);
sink(a7a);
sink(a10); sink(a10);
} }

View File

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