mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Unordered: Merge from trunk.
Remove some workarounds for old compilers, some documentation updates and tweak some tests for problem compilers. [SVN r74469]
This commit is contained in:
@ -143,7 +143,8 @@ in some breaking changes:
|
||||
* Equality comparison has been changed to the C++11 specification.
|
||||
In a container with equivalent keys, elements in a group with equal
|
||||
keys used to have to be in the same order to be considered equal,
|
||||
now they can be a permutation of each other.
|
||||
now they can be a permutation of each other. To keep the old
|
||||
behavior define the macro `BOOST_UNORDERED_DEPRECATED_EQUALITY`.
|
||||
|
||||
* The behaviour of swap is different when the two containers to be
|
||||
swapped has unequal allocators. It used to allocate new nodes using
|
||||
@ -154,4 +155,12 @@ in some breaking changes:
|
||||
* Allocator's `construct` and `destroy` functions are called with raw
|
||||
pointers, rather than the allocator's `pointer` type.
|
||||
|
||||
* `emplace` used to emulate the variadic pair constructors that
|
||||
appeared in early C++0x drafts. Since they were removed it no
|
||||
longer does so. It does emulate the new `piecewise_construct`
|
||||
pair constructors - only you need to use
|
||||
`boost::piecewise_construct`. To use the old emulation of
|
||||
the variadic consturctors define
|
||||
`BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT`.
|
||||
|
||||
[endsect]
|
||||
|
@ -44,6 +44,8 @@ bucket but there are a some serious problems with this:
|
||||
|
||||
So chained addressing is used.
|
||||
|
||||
[/ (Removing for now as this is out of date)
|
||||
|
||||
For containers with unique keys I store the buckets in a single-linked list.
|
||||
There are other possible data structures (such as a double-linked list)
|
||||
that allow for some operations to be faster (such as erasing and iteration)
|
||||
@ -63,6 +65,17 @@ nodes in reverse order. This allows quick navigation to the end of a group (sinc
|
||||
the first element points to the last) and can be quickly updated when elements
|
||||
are inserted or erased. The main disadvantage of this approach is some hairy code
|
||||
for erasing elements.
|
||||
]
|
||||
|
||||
[/ (Starting to write up new structure, might not be ready in time)
|
||||
The node used to be stored in a linked list for each bucket but that
|
||||
didn't meet the complexity requirements for C++11, so now the nodes
|
||||
are stored in one long single linked list. But there needs a way to get
|
||||
the bucket from the node, to do that a copy of the key's hash value is
|
||||
stored in the node. Another possibility would be to store a pointer to
|
||||
the bucket, or the bucket's index, but storing the hash value allows
|
||||
some operations to be faster.
|
||||
]
|
||||
|
||||
[h2 Number of Buckets]
|
||||
|
||||
@ -90,58 +103,4 @@ efficiency advantage of power of 2 hash tables.
|
||||
|
||||
So, this implementation uses a prime number for the hash table size.
|
||||
|
||||
[h2 Equality operators]
|
||||
|
||||
/TODO/: This is out of date.
|
||||
|
||||
`operator==` and `operator!=` are not included in the standard, but I've
|
||||
added them as I think they could be useful and can be implemented
|
||||
fairly efficiently. They are specified differently to the other standard
|
||||
containers, comparing keys using the equality predicate rather than
|
||||
`operator==`.
|
||||
|
||||
It's also different to the proposal
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2944.pdf n2944].
|
||||
which uses the equality operators for the whole of `value_type`. This
|
||||
implementation just uses the key equality function for the key,
|
||||
and `mapped_type`'s equality operator in `unordered_map` and
|
||||
`unordered_multimap` for the mapped part of the element.
|
||||
|
||||
Also, in `unordered_multimap`, the mapped values for a group of elements with
|
||||
equivalent keys are only considered equal if they are in the same order,
|
||||
in n2944 they just need to be a permutation of each other. Since the
|
||||
order of elements with equal keys is now defined to be stable, it seems to me
|
||||
that their order can be considered part of the container's value.
|
||||
|
||||
[h2 Active Issues and Proposals]
|
||||
|
||||
[h3 C++0x allocators]
|
||||
|
||||
/TODO/: This is out of date.
|
||||
|
||||
Recent drafts have included an overhaul of the allocators, but this was
|
||||
dependent on concepts which are no longer in the standard.
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2946.pdf n2946]
|
||||
attempts to respecify them without concepts. I'll try to implement this (or
|
||||
an appropriate later version) in a future version of boost, possibly changed
|
||||
a little to accomodate non-C++0x compilers.
|
||||
|
||||
[h3 Swapping containers with unequal allocators]
|
||||
|
||||
/TODO/: This is out of date.
|
||||
|
||||
It isn't clear how to swap containers when their allocators aren't equal.
|
||||
This is
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#431
|
||||
Issue 431: Swapping containers with unequal allocators]. This has been resolved
|
||||
with the new allocator specification, so this should be fixed when
|
||||
support is added.
|
||||
|
||||
[h3 Are insert and erase stable for unordered_multiset and unordered_multimap?]
|
||||
|
||||
It wan't specified if `unordered_multiset` and `unordered_multimap` preserve the order
|
||||
of elements with equivalent keys (i.e. if they're stable under `insert` and `erase`).
|
||||
Since [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2691.pdf
|
||||
n2691] it's been specified that they do and this implementation follows that.
|
||||
|
||||
[endsect]
|
||||
|
89
doc/ref.php
89
doc/ref.php
@ -412,10 +412,13 @@ EOL;
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
</para>
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -454,9 +457,13 @@ EOL;
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</para>
|
||||
</notes>
|
||||
</method>
|
||||
@ -658,13 +665,19 @@ EOL;
|
||||
<paramtype><?php echo $name; ?>&</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Swaps the contents of the container with the parameter.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
@ -961,9 +974,28 @@ EOL;
|
||||
<paramtype><?php echo $full_type; ?> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<?php if($equivalent_keys): ?>
|
||||
<para>Return <code>true</code> if <code>x.size() ==
|
||||
y.size</code> and for every equivalent key group in
|
||||
<code>x</code>, there is a group in <code>y</code>
|
||||
for the same key, which is a permutation (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
<?php else: ?>
|
||||
<para>Return <code>true</code> if <code>x.size() ==
|
||||
y.size</code> and for every element in <code>x</code>,
|
||||
there is an element in <code>y</code> with the same
|
||||
for the same key, with an equal value (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
<?php endif; ?>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -985,9 +1017,28 @@ EOL;
|
||||
<paramtype><?php echo $full_type; ?> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<?php if($equivalent_keys): ?>
|
||||
<para>Return <code>false</code> if <code>x.size() ==
|
||||
y.size</code> and for every equivalent key group in
|
||||
<code>x</code>, there is a group in <code>y</code>
|
||||
for the same key, which is a permutation (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
<?php else: ?>
|
||||
<para>Return <code>false</code> if <code>x.size() ==
|
||||
y.size</code> and for every element in <code>x</code>,
|
||||
there is an element in <code>y</code> with the same
|
||||
for the same key, with an equal value (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
<?php endif; ?>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -1014,13 +1065,19 @@ EOL;
|
||||
<effects>
|
||||
<para><code>x.swap(y)</code></para>
|
||||
</effects>
|
||||
<description>
|
||||
<para>Swaps the contents of <code>x</code> and <code>y</code>.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
|
284
doc/ref.xml
284
doc/ref.xml
@ -350,10 +350,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
</para>
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -385,9 +388,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</para>
|
||||
</notes>
|
||||
</method>
|
||||
@ -574,13 +581,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_set&</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Swaps the contents of the container with the parameter.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
@ -841,9 +854,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_set<Value, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<para>Return <code>true</code> if <code>x.size() ==
|
||||
y.size</code> and for every element in <code>x</code>,
|
||||
there is an element in <code>y</code> with the same
|
||||
for the same key, with an equal value (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -866,9 +889,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_set<Value, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<para>Return <code>false</code> if <code>x.size() ==
|
||||
y.size</code> and for every element in <code>x</code>,
|
||||
there is an element in <code>y</code> with the same
|
||||
for the same key, with an equal value (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -896,13 +929,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<effects>
|
||||
<para><code>x.swap(y)</code></para>
|
||||
</effects>
|
||||
<description>
|
||||
<para>Swaps the contents of <code>x</code> and <code>y</code>.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
@ -1251,10 +1290,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
</para>
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -1286,9 +1328,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</para>
|
||||
</notes>
|
||||
</method>
|
||||
@ -1474,13 +1520,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_multiset&</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Swaps the contents of the container with the parameter.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
@ -1741,9 +1793,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_multiset<Value, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<para>Return <code>true</code> if <code>x.size() ==
|
||||
y.size</code> and for every equivalent key group in
|
||||
<code>x</code>, there is a group in <code>y</code>
|
||||
for the same key, which is a permutation (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -1766,9 +1828,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_multiset<Value, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<para>Return <code>false</code> if <code>x.size() ==
|
||||
y.size</code> and for every equivalent key group in
|
||||
<code>x</code>, there is a group in <code>y</code>
|
||||
for the same key, which is a permutation (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -1796,13 +1868,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<effects>
|
||||
<para><code>x.swap(y)</code></para>
|
||||
</effects>
|
||||
<description>
|
||||
<para>Swaps the contents of <code>x</code> and <code>y</code>.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
@ -2164,10 +2242,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
</para>
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -2199,9 +2280,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</para>
|
||||
</notes>
|
||||
</method>
|
||||
@ -2388,13 +2473,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_map&</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Swaps the contents of the container with the parameter.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
@ -2692,9 +2783,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_map<Key, Mapped, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<para>Return <code>true</code> if <code>x.size() ==
|
||||
y.size</code> and for every element in <code>x</code>,
|
||||
there is an element in <code>y</code> with the same
|
||||
for the same key, with an equal value (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -2719,9 +2820,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_map<Key, Mapped, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<para>Return <code>false</code> if <code>x.size() ==
|
||||
y.size</code> and for every element in <code>x</code>,
|
||||
there is an element in <code>y</code> with the same
|
||||
for the same key, with an equal value (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -2751,13 +2862,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<effects>
|
||||
<para><code>x.swap(y)</code></para>
|
||||
</effects>
|
||||
<description>
|
||||
<para>Swaps the contents of <code>x</code> and <code>y</code>.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
@ -3114,10 +3231,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
</para>
|
||||
but using <code>boost::unordered::piecewise_construct</code>.</para>
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</notes>
|
||||
</method>
|
||||
<method name="emplace_hint">
|
||||
@ -3149,9 +3269,13 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<para>If the compiler doesn't support variadic template arguments or rvalue
|
||||
references, this is emulated for up to 10 arguments, with no support
|
||||
for rvalue references or move semantics.</para>
|
||||
<para>Since existing `std::pair` implementations don't support
|
||||
<para>Since existing <code>std::pair</code> implementations don't support
|
||||
<code>std::piecewise_construct</code> this emulates it,
|
||||
but using <code>boost::unordered::piecewise_construct</code>.
|
||||
<para>In version of Boost before 1.48 this emulated the variadic pair
|
||||
constructor from older C++0x drafts. For backwards compatability
|
||||
this can be enabled by defining the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.
|
||||
</para>
|
||||
</notes>
|
||||
</method>
|
||||
@ -3337,13 +3461,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_multimap&</paramtype>
|
||||
</parameter>
|
||||
<type>void</type>
|
||||
<description>
|
||||
<para>Swaps the contents of the container with the parameter.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
@ -3606,9 +3736,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_multimap<Key, Mapped, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<para>Return <code>true</code> if <code>x.size() ==
|
||||
y.size</code> and for every equivalent key group in
|
||||
<code>x</code>, there is a group in <code>y</code>
|
||||
for the same key, which is a permutation (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -3633,9 +3773,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<paramtype>unordered_multimap<Key, Mapped, Hash, Pred, Alloc> const&</paramtype>
|
||||
</parameter>
|
||||
<type>bool</type>
|
||||
<description>
|
||||
<para>Return <code>false</code> if <code>x.size() ==
|
||||
y.size</code> and for every equivalent key group in
|
||||
<code>x</code>, there is a group in <code>y</code>
|
||||
for the same key, which is a permutation (using
|
||||
<code>operator==</code> to compare the value types).
|
||||
</para>
|
||||
</description>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Documentation outdated.</para>
|
||||
<para>This is a boost extension.</para>
|
||||
<para>The behavior of this function was changed to match
|
||||
the C++11 standard in Boost 1.48. If you wish to use
|
||||
the old behaviour, define the macro
|
||||
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
|
||||
<para>Behavior is undefined if the two containers don't have
|
||||
equivalent equality predicates.</para>
|
||||
</notes>
|
||||
@ -3665,13 +3815,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<effects>
|
||||
<para><code>x.swap(y)</code></para>
|
||||
</effects>
|
||||
<description>
|
||||
<para>Swaps the contents of <code>x</code> and <code>y</code>.</para>
|
||||
<para>If <code>Allocator::propagate_on_container_swap</code> is declared and
|
||||
<code>Allocator::propagate_on_container_swap::value</code> is true then the
|
||||
containers' allocators are swapped. Otherwise, swapping with unequal allocators
|
||||
results in undefined behavior.</para>
|
||||
</description>
|
||||
<throws>
|
||||
<para>If the allocators are equal, doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>Hash</code> or <code>Pred</code>.</para>
|
||||
<para>Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of <code>key_equal</code> or <code>hasher</code>.</para>
|
||||
</throws>
|
||||
<notes>
|
||||
<para><emphasis>TODO</emphasis>: Update swap documentation, no longer correct.</para>
|
||||
<para>For a discussion of the behavior when allocators aren't equal see
|
||||
<link linkend="unordered.rationale.swapping_containers_with_unequal_allocators">the implementation details</link>.</para>
|
||||
<para>The exception specifications aren't quite the same as the C++11 standard, as
|
||||
the equality predieate and hash function are swapped using their copy constructors.</para>
|
||||
</notes>
|
||||
</function>
|
||||
</free-function-group>
|
||||
|
@ -22,15 +22,6 @@
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||
|
||||
#if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \
|
||||
&& !defined(__BORLANDC__)
|
||||
# define BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
|
||||
# include <boost/detail/allocator_utilities.hpp>
|
||||
#endif
|
||||
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
|
||||
# include <memory>
|
||||
#endif
|
||||
@ -87,17 +78,12 @@ namespace boost { namespace unordered { namespace detail {
|
||||
// Rebind allocators. For some problematic libraries, use rebind_to
|
||||
// from <boost/detail/allocator_utilities.hpp>.
|
||||
|
||||
# if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
|
||||
template <typename Alloc, typename T>
|
||||
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
|
||||
# else
|
||||
template <typename Alloc, typename T>
|
||||
struct rebind_wrap
|
||||
{
|
||||
typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
|
||||
type;
|
||||
};
|
||||
# endif
|
||||
|
||||
template <typename T> typename boost::add_lvalue_reference<T>::type make();
|
||||
struct choice9 { typedef char (&type)[9]; };
|
||||
@ -474,8 +460,4 @@ namespace boost { namespace unordered { namespace detail {
|
||||
};
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
|
||||
# undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -541,9 +541,11 @@ UNORDERED_AUTO_TEST(map_emplace_test)
|
||||
{
|
||||
boost::unordered_map<int, overloaded_constructor> x;
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
x.emplace();
|
||||
BOOST_TEST(x.find(0) != x.end() &&
|
||||
x.find(0)->second == overloaded_constructor());
|
||||
#endif
|
||||
|
||||
x.emplace(2, 3);
|
||||
BOOST_TEST(x.find(2) != x.end() &&
|
||||
@ -569,8 +571,10 @@ UNORDERED_AUTO_TEST(set_emplace_test)
|
||||
boost::unordered_set<overloaded_constructor> x;
|
||||
overloaded_constructor check;
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
x.emplace();
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
#endif
|
||||
|
||||
x.clear();
|
||||
x.emplace(1);
|
||||
|
@ -203,6 +203,7 @@ namespace unnecessary_copy_tests
|
||||
{
|
||||
reset();
|
||||
T x;
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
x.emplace(boost::move(a));
|
||||
@ -237,6 +238,7 @@ namespace unnecessary_copy_tests
|
||||
// 0 arguments
|
||||
//
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
// The container will have to create a copy in order to compare with
|
||||
// the existing element.
|
||||
reset();
|
||||
@ -246,6 +248,7 @@ namespace unnecessary_copy_tests
|
||||
#else
|
||||
// source_cost doesn't make much sense here, but it seems to fit.
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -322,10 +325,12 @@ namespace unnecessary_copy_tests
|
||||
// 0 arguments
|
||||
//
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
// COPY_COUNT(1) would be okay here.
|
||||
reset();
|
||||
x.emplace();
|
||||
COPY_COUNT(2); MOVE_COUNT(0);
|
||||
#endif
|
||||
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
|
Reference in New Issue
Block a user