mirror of
https://github.com/boostorg/container.git
synced 2025-08-01 13:34:30 +02:00
Implemented C++14's heterogeneous lookups.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[/
|
||||
/ Copyright (c) 2009-2013 Ion Gazta\u00F1aga
|
||||
/ Copyright (c) 2009-2018 Ion Gazta\u00F1aga
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -8,7 +8,7 @@
|
||||
[library Boost.Container
|
||||
[quickbook 1.5]
|
||||
[authors [Gaztanaga, Ion]]
|
||||
[copyright 2009-2017 Ion Gaztanaga]
|
||||
[copyright 2009-2018 Ion Gaztanaga]
|
||||
[id container]
|
||||
[dirname container]
|
||||
[purpose Containers library]
|
||||
@@ -62,7 +62,7 @@ There is no need to compile [*Boost.Container], since it's a header-only library
|
||||
just include your Boost header directory in your compiler include path *except if you use*:
|
||||
|
||||
* [link container.extended_allocators Extended Allocators]
|
||||
* Some [link container.polymorphic_memory_resources Polymorphic Memory Resources] classes.
|
||||
* Some [link container.cpp_conformance.polymorphic_memory_resources Polymorphic Memory Resources] classes.
|
||||
|
||||
Those exceptions are are implemented as a separately compiled library, so in those cases you must install binaries
|
||||
in a location that can be found by your linker.
|
||||
@@ -166,6 +166,10 @@ the effects are undefined in the following cases: (...) In particular - if an in
|
||||
is used as a template argument when instantiating a template component,
|
||||
unless specifically allowed for that component]].
|
||||
|
||||
Finally C++17 added support for incomplete types in `std::vector`, `std::list` and `std::forward_list`
|
||||
(see [@https://wg21.link/n4569 ['N4569: Minimal incomplete type support for standard containers, revision 4]]
|
||||
for details), but no other containers like `std::set/map/unordered_set/unordered_map`,
|
||||
|
||||
Fortunately all [*Boost.Container] containers except
|
||||
[classref boost::container::static_vector static_vector] and
|
||||
[classref boost::container::small_vector small_vector] and
|
||||
@@ -745,130 +749,12 @@ Use them simply specifying the new allocator in the corresponding template argum
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:polymorphic_memory_resources Extended Functionality: Polymorphic Memory Resources ]
|
||||
|
||||
The document
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html C++ Extensions for Library Fundamentals (Final draft: N4480)]
|
||||
includes classes that provide allocator type erasure and runtime polymorphism. As Pablo Halpern, the author of the proposal,
|
||||
explains in the paper ([@https://isocpp.org/files/papers/N3916.pdf N3916 Polymorphic Memory Resources (r2)]):
|
||||
|
||||
["['A significant impediment to effective memory management in C++ has been the
|
||||
inability to use allocators in non-generic contexts. In large software systems,
|
||||
most of the application program consists of non-generic procedural or
|
||||
object-oriented code that is compiled once and linked many times.]]
|
||||
|
||||
["['Allocators in C++, however, have historically relied solely on
|
||||
compile-time polymorphism, and therefore have not been suitable for use in vocabulary
|
||||
types, which are passed through interfaces between separately-compiled modules,
|
||||
because the allocator type necessarily affects the type of the object that uses it.
|
||||
This proposal builds upon the improvements made to allocators in
|
||||
C++11 and describes a set of facilities for runtime polymorphic memory
|
||||
resources that interoperate with the existing compile-time polymorphic
|
||||
allocators.]]
|
||||
|
||||
[*Boost.Container] implements nearly all classes of the proposal under
|
||||
the namespace `boost::container::pmr`. There are two groups,
|
||||
|
||||
* Header only utilities (these don't require the separately compiled library):
|
||||
* [classref boost::container::pmr::memory_resource memory_resource].
|
||||
* [classref boost::container::pmr::resource_adaptor resource_adaptor].
|
||||
|
||||
* Utilities that require the the separately compiled library:
|
||||
* [classref boost::container::pmr::polymorphic_allocator polymorphic_allocator].
|
||||
* [classref boost::container::pmr::monotonic_buffer_resource monotonic_buffer_resource].
|
||||
* [classref boost::container::pmr::unsynchronized_pool_resource unsynchronized_pool_resource].
|
||||
* [classref boost::container::pmr::synchronized_pool_resource synchronized_pool_resource].
|
||||
* Global resource functions: [funcref boost::container::pmr::get_default_resource get_default_resource]/
|
||||
[funcref boost::container::pmr::set_default_resource set_default_resource]/
|
||||
[funcref boost::container::pmr::new_delete_resource new_delete_resource]/
|
||||
[funcref boost::container::pmr::null_memory_resource null_memory_resource]
|
||||
* Aliases for boost containers using the polymorphic allocator
|
||||
(like [classref boost::container::pmr::vector pmr::vector], etc.)
|
||||
|
||||
[*Boost.Container]'s polymorphic resource library is usable from C++03 containers,
|
||||
and offers some alternative utilities if the required C++11 features of the
|
||||
['Library Fundamentals] specification are not available.
|
||||
|
||||
[import ../example/doc_pmr.cpp]
|
||||
|
||||
Let's review the usage example given in
|
||||
[@https://isocpp.org/files/papers/N3916.pdf N3916] and see how it can be implemented
|
||||
using [*Boost.Container]: ['Suppose we are processing a series of shopping lists, where a shopping list is a
|
||||
container of strings, and storing them in a collection (a list) of shopping lists.
|
||||
Each shopping list being processed uses a bounded amount of memory that is needed for
|
||||
a short period of time, while the collection of shopping lists uses an unbounded
|
||||
amount of memory and will exist for a longer period of time. For efficiency, we can
|
||||
use a more time-efficient memory allocator based on a finite buffer for the temporary
|
||||
shopping lists.]
|
||||
|
||||
Let's see how `ShoppingList` can be defined to support an polymorphic memory resource
|
||||
that can allocate memory from different underlying mechanisms. The most important
|
||||
details are:
|
||||
|
||||
* It should declare that supports an allocator defining an `allocator_type` typedef.
|
||||
This `allocator_type` will be of type [classref boost::container::pmr::memory_resource memory_resource *],
|
||||
which is a base class for polymorphic resources.
|
||||
* It must define constructors that take the
|
||||
the allocator as argument. It can be implemented in two ways:
|
||||
* `ShoppingList` has constructors taking
|
||||
[classref boost::container::pmr::memory_resource memory_resource*] as the last argument.
|
||||
* `ShoppingList` has constructors taking
|
||||
[classref boost::container::allocator_arg_t allocator_arg_t] as the first argument
|
||||
and [classref boost::container::pmr::memory_resource memory_resource*] as the second argument.
|
||||
|
||||
[*Note:] ['In C++03 compilers, it is required that the programmer specializes as `true`
|
||||
[classref boost::container::constructible_with_allocator_suffix constructible_with_allocator_suffix] or
|
||||
[classref boost::container::constructible_with_allocator_prefix constructible_with_allocator_prefix]
|
||||
as in C++03 there is no way to automatically detect the chosen option at compile time. If
|
||||
no specialization is done, [*Boost.Container] assumes the suffix option].
|
||||
|
||||
[doc_pmr_ShoppingList_hpp]
|
||||
|
||||
['However, this time-efficient allocator is not appropriate for the longer
|
||||
lived collection of shopping lists. This example shows how those temporary shopping
|
||||
lists, using a time-efficient allocator, can be used to populate the long lived collection
|
||||
of shopping lists, using a general purpose allocator, something that would be
|
||||
annoyingly difficult without the polymorphic allocators.]
|
||||
|
||||
In [*Boost.Container] for the time-efficient allocation we can use
|
||||
[classref boost::container::pmr::monotonic_buffer_resource monotonic_buffer_resource],
|
||||
providing an external buffer that will be used until it's exhausted. In the default
|
||||
configuration, when the buffer is exhausted, the default memory resource will be used
|
||||
instead.
|
||||
|
||||
[doc_pmr_main_cpp]
|
||||
|
||||
['Notice that the shopping lists within `folder` use the default allocator resource
|
||||
whereas the shopping list `temporaryShoppingList` uses the short-lived but very fast
|
||||
`buf_rsrc`. Despite using different allocators, you can insert
|
||||
`temporaryShoppingList` into folder because they have the same `ShoppingList`
|
||||
type. Also, while `ShoppingList` uses memory_resource directly,
|
||||
[classref boost::container::pmr::list pmr::list],
|
||||
[classref boost::container::pmr::vector pmr::vector]
|
||||
and [classref boost::container::pmr::string pmr::string] all use
|
||||
[classref boost::container::pmr::polymorphic_allocator polymorphic_allocator].]
|
||||
|
||||
['The resource passed to the `ShoppingList` constructor is propagated to the vector and
|
||||
each string within that `ShoppingList`. Similarly, the resource used to construct
|
||||
`folder` is propagated to the constructors of the ShoppingLists that are inserted into
|
||||
the list (and to the strings within those `ShoppingLists`). The
|
||||
[classref boost::container::pmr::polymorphic_allocator polymorphic_allocator]
|
||||
template is designed to be almost interchangeable with a pointer to
|
||||
[classref boost::container::pmr::memory_resource memory_resource],
|
||||
thus producing a ['bridge] between the template-policy
|
||||
style of allocator and the polymorphic-base-class style of allocator.]
|
||||
|
||||
This example actually shows how easy is to use [*Boost.Container] to write
|
||||
type-erasured allocator-capable classes even in C++03 compilers.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:Cpp11_conformance C++11/C++14 Conformance]
|
||||
[section:cpp_conformance C++11/C++14/C++17 Conformance]
|
||||
|
||||
[*Boost.Container] aims for full C++11 conformance except reasoned deviations,
|
||||
backporting as much as possible for C++03. Obviously, this conformance is a work
|
||||
in progress so this section explains what C++11 features are implemented and which of them
|
||||
have been backported to C++03 compilers.
|
||||
in progress so this section explains what C++11/C++14/C++17 features are implemented and which
|
||||
of them have been backported to earlier standard conformig compilers.
|
||||
|
||||
[section:move_emplace Move and Emplace]
|
||||
|
||||
@@ -985,6 +871,128 @@ past the end of the same empty sequence (example taken from N3644):
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:polymorphic_memory_resources Polymorphic Memory Resources ]
|
||||
|
||||
The document
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html C++ Extensions for Library Fundamentals (final draft)]
|
||||
includes classes that provide allocator type erasure and runtime polymorphism. As Pablo Halpern, the author of the proposal,
|
||||
explains in the paper ([@https://isocpp.org/files/papers/N3916.pdf N3916 Polymorphic Memory Resources (r2)]):
|
||||
|
||||
["['A significant impediment to effective memory management in C++ has been the
|
||||
inability to use allocators in non-generic contexts. In large software systems,
|
||||
most of the application program consists of non-generic procedural or
|
||||
object-oriented code that is compiled once and linked many times.]]
|
||||
|
||||
["['Allocators in C++, however, have historically relied solely on
|
||||
compile-time polymorphism, and therefore have not been suitable for use in vocabulary
|
||||
types, which are passed through interfaces between separately-compiled modules,
|
||||
because the allocator type necessarily affects the type of the object that uses it.
|
||||
This proposal builds upon the improvements made to allocators in
|
||||
C++11 and describes a set of facilities for runtime polymorphic memory
|
||||
resources that interoperate with the existing compile-time polymorphic
|
||||
allocators.]]
|
||||
|
||||
Most utilities from the Fundamentals TS were merged into C++17, but
|
||||
[*Boost.Container] offers them for C++03, C++11 and C++14 compilers.
|
||||
|
||||
[*Boost.Container] implements nearly all classes of the proposal under
|
||||
the namespace `boost::container::pmr`. There are two groups,
|
||||
|
||||
* Header only utilities (these don't require the separately compiled library):
|
||||
* [classref boost::container::pmr::memory_resource memory_resource].
|
||||
* [classref boost::container::pmr::resource_adaptor resource_adaptor].
|
||||
|
||||
* Utilities that require the the separately compiled library:
|
||||
* [classref boost::container::pmr::polymorphic_allocator polymorphic_allocator].
|
||||
* [classref boost::container::pmr::monotonic_buffer_resource monotonic_buffer_resource].
|
||||
* [classref boost::container::pmr::unsynchronized_pool_resource unsynchronized_pool_resource].
|
||||
* [classref boost::container::pmr::synchronized_pool_resource synchronized_pool_resource].
|
||||
* Global resource functions: [funcref boost::container::pmr::get_default_resource get_default_resource]/
|
||||
[funcref boost::container::pmr::set_default_resource set_default_resource]/
|
||||
[funcref boost::container::pmr::new_delete_resource new_delete_resource]/
|
||||
[funcref boost::container::pmr::null_memory_resource null_memory_resource]
|
||||
* Aliases for boost containers using the polymorphic allocator
|
||||
(like [classref boost::container::pmr::vector pmr::vector], etc.)
|
||||
|
||||
[*Boost.Container]'s polymorphic resource library is usable from C++03 containers,
|
||||
and offers some alternative utilities if the required C++11 features of the
|
||||
['Library Fundamentals] specification are not available.
|
||||
|
||||
[import ../example/doc_pmr.cpp]
|
||||
|
||||
Let's review the usage example given in
|
||||
[@https://isocpp.org/files/papers/N3916.pdf N3916] and see how it can be implemented
|
||||
using [*Boost.Container]: ['Suppose we are processing a series of shopping lists, where a shopping list is a
|
||||
container of strings, and storing them in a collection (a list) of shopping lists.
|
||||
Each shopping list being processed uses a bounded amount of memory that is needed for
|
||||
a short period of time, while the collection of shopping lists uses an unbounded
|
||||
amount of memory and will exist for a longer period of time. For efficiency, we can
|
||||
use a more time-efficient memory allocator based on a finite buffer for the temporary
|
||||
shopping lists.]
|
||||
|
||||
Let's see how `ShoppingList` can be defined to support an polymorphic memory resource
|
||||
that can allocate memory from different underlying mechanisms. The most important
|
||||
details are:
|
||||
|
||||
* It should declare that supports an allocator defining an `allocator_type` typedef.
|
||||
This `allocator_type` will be of type [classref boost::container::pmr::memory_resource memory_resource *],
|
||||
which is a base class for polymorphic resources.
|
||||
* It must define constructors that take the
|
||||
the allocator as argument. It can be implemented in two ways:
|
||||
* `ShoppingList` has constructors taking
|
||||
[classref boost::container::pmr::memory_resource memory_resource*] as the last argument.
|
||||
* `ShoppingList` has constructors taking
|
||||
[classref boost::container::allocator_arg_t allocator_arg_t] as the first argument
|
||||
and [classref boost::container::pmr::memory_resource memory_resource*] as the second argument.
|
||||
|
||||
[*Note:] ['In C++03 compilers, it is required that the programmer specializes as `true`
|
||||
[classref boost::container::constructible_with_allocator_suffix constructible_with_allocator_suffix] or
|
||||
[classref boost::container::constructible_with_allocator_prefix constructible_with_allocator_prefix]
|
||||
as in C++03 there is no way to automatically detect the chosen option at compile time. If
|
||||
no specialization is done, [*Boost.Container] assumes the suffix option].
|
||||
|
||||
[doc_pmr_ShoppingList_hpp]
|
||||
|
||||
['However, this time-efficient allocator is not appropriate for the longer
|
||||
lived collection of shopping lists. This example shows how those temporary shopping
|
||||
lists, using a time-efficient allocator, can be used to populate the long lived collection
|
||||
of shopping lists, using a general purpose allocator, something that would be
|
||||
annoyingly difficult without the polymorphic allocators.]
|
||||
|
||||
In [*Boost.Container] for the time-efficient allocation we can use
|
||||
[classref boost::container::pmr::monotonic_buffer_resource monotonic_buffer_resource],
|
||||
providing an external buffer that will be used until it's exhausted. In the default
|
||||
configuration, when the buffer is exhausted, the default memory resource will be used
|
||||
instead.
|
||||
|
||||
[doc_pmr_main_cpp]
|
||||
|
||||
['Notice that the shopping lists within `folder` use the default allocator resource
|
||||
whereas the shopping list `temporaryShoppingList` uses the short-lived but very fast
|
||||
`buf_rsrc`. Despite using different allocators, you can insert
|
||||
`temporaryShoppingList` into folder because they have the same `ShoppingList`
|
||||
type. Also, while `ShoppingList` uses memory_resource directly,
|
||||
[classref boost::container::pmr::list pmr::list],
|
||||
[classref boost::container::pmr::vector pmr::vector]
|
||||
and [classref boost::container::pmr::string pmr::string] all use
|
||||
[classref boost::container::pmr::polymorphic_allocator polymorphic_allocator].]
|
||||
|
||||
['The resource passed to the `ShoppingList` constructor is propagated to the vector and
|
||||
each string within that `ShoppingList`. Similarly, the resource used to construct
|
||||
`folder` is propagated to the constructors of the ShoppingLists that are inserted into
|
||||
the list (and to the strings within those `ShoppingLists`). The
|
||||
[classref boost::container::pmr::polymorphic_allocator polymorphic_allocator]
|
||||
template is designed to be almost interchangeable with a pointer to
|
||||
[classref boost::container::pmr::memory_resource memory_resource],
|
||||
thus producing a ['bridge] between the template-policy
|
||||
style of allocator and the polymorphic-base-class style of allocator.]
|
||||
|
||||
This example actually shows how easy is to use [*Boost.Container] to write
|
||||
type-erasured allocator-capable classes even in C++03 compilers.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:forward_list `forward_list<T>`]
|
||||
|
||||
[*Boost.Container] does not offer C++11 `forward_list` container yet, but it will be available in future
|
||||
@@ -1172,10 +1180,10 @@ collect them containers and build [*Boost.Container], a library targeted to a wi
|
||||
With so many high quality standard library implementations out there, why would you want to
|
||||
use [*Boost.Container]? There are several reasons for that:
|
||||
|
||||
* If you have a C++03 compiler, you can have access to C++11 features and have an easy
|
||||
code migration when you change your compiler.
|
||||
* Even if you have a earlier standard conforming compiler, you still can have access to many
|
||||
of the latest C++ standard features and have an easy code migration when you change your compiler.
|
||||
* It's compatible with [*Boost.Interprocess] shared memory allocators.
|
||||
* You have extremely useful new containers like `stable_vector` and `flat_[multi]set/map`.
|
||||
* You have extremely useful new containers like `[stable/static/small]_vector` and `flat_[multi]set/map`.
|
||||
* If you work on multiple platforms, you'll have a portable behaviour without depending
|
||||
on the std-lib implementation conformance of each platform. Some examples:
|
||||
* Default constructors don't allocate memory at all, which improves performance and
|
||||
@@ -1237,6 +1245,8 @@ use [*Boost.Container]? There are several reasons for that:
|
||||
* Improved correctness of [classref boost::container::adaptive_pool adaptive_pool] and many parameters are now compile-time
|
||||
constants instead of runtime constants.
|
||||
|
||||
* Implemented C++14's heterogeneous lookup functions for `[multi]map/[multi]set/flat_[multi]map/flat_[multi]set`.
|
||||
|
||||
* Fixed bugs:
|
||||
* [@https://svn.boost.org/trac/boost/ticket/13533 Trac #13533: ['"Boost vector resize causes assert(false)"]].
|
||||
|
||||
@@ -1348,7 +1358,7 @@ use [*Boost.Container]? There are several reasons for that:
|
||||
|
||||
[section:release_notes_boost_1_60_00 Boost 1.60 Release]
|
||||
|
||||
* Implemented [link container.polymorphic_memory_resources Polymorphic Memory Resources].
|
||||
* Implemented [link container.cpp_conformance.polymorphic_memory_resources Polymorphic Memory Resources].
|
||||
* Add more BOOST_ASSERT checks to test preconditions in some operations (like `pop_back`, `pop_front`, `back`, `front`, etc.)
|
||||
* Added C++11 `back`/`front` operations to [classref boost::container::basic_string basic_string].
|
||||
* Fixed bugs:
|
||||
|
@@ -1160,7 +1160,31 @@ class flat_tree
|
||||
return i;
|
||||
}
|
||||
|
||||
// set operations:
|
||||
template<class K>
|
||||
typename dtl::enable_if_transparent<key_compare, K, iterator>::type
|
||||
find(const K& k)
|
||||
{
|
||||
iterator i = this->lower_bound(k);
|
||||
iterator end_it = this->end();
|
||||
if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
|
||||
i = end_it;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<class K>
|
||||
typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
|
||||
find(const K& k) const
|
||||
{
|
||||
const_iterator i = this->lower_bound(k);
|
||||
|
||||
const_iterator end_it = this->cend();
|
||||
if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
|
||||
i = end_it;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{
|
||||
std::pair<const_iterator, const_iterator> p = this->equal_range(k);
|
||||
@@ -1168,6 +1192,15 @@ class flat_tree
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class K>
|
||||
typename dtl::enable_if_transparent<key_compare, K, size_type>::type
|
||||
count(const K& k) const
|
||||
{
|
||||
std::pair<const_iterator, const_iterator> p = this->equal_range(k);
|
||||
size_type n = p.second - p.first;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<class C2>
|
||||
BOOST_CONTAINER_FORCEINLINE void merge_unique(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
|
||||
{
|
||||
@@ -1212,24 +1245,73 @@ class flat_tree
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const
|
||||
{ return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
|
||||
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, iterator>::type
|
||||
lower_bound(const K& k)
|
||||
{ return this->priv_lower_bound(this->begin(), this->end(), k); }
|
||||
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
|
||||
lower_bound(const K& k) const
|
||||
{ return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k)
|
||||
{ return this->priv_upper_bound(this->begin(), this->end(), k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const
|
||||
{ return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
|
||||
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K,iterator>::type
|
||||
upper_bound(const K& k)
|
||||
{ return this->priv_upper_bound(this->begin(), this->end(), k); }
|
||||
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K,const_iterator>::type
|
||||
upper_bound(const K& k) const
|
||||
{ return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& k)
|
||||
{ return this->priv_equal_range(this->begin(), this->end(), k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
|
||||
{ return this->priv_equal_range(this->cbegin(), this->cend(), k); }
|
||||
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K,std::pair<iterator,iterator> >::type
|
||||
equal_range(const K& k)
|
||||
{ return this->priv_equal_range(this->begin(), this->end(), k); }
|
||||
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
|
||||
equal_range(const K& k) const
|
||||
{ return this->priv_equal_range(this->cbegin(), this->cend(), k); }
|
||||
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, iterator> lower_bound_range(const key_type& k)
|
||||
{ return this->priv_lower_bound_range(this->begin(), this->end(), k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
|
||||
{ return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
|
||||
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K,std::pair<iterator,iterator> >::type
|
||||
lower_bound_range(const K& k)
|
||||
{ return this->priv_lower_bound_range(this->begin(), this->end(), k); }
|
||||
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
|
||||
lower_bound_range(const K& k) const
|
||||
{ return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE size_type capacity() const
|
||||
{
|
||||
const bool value = boost::container::dtl::
|
||||
@@ -1419,9 +1501,9 @@ class flat_tree
|
||||
, boost::forward<Convertible>(convertible));
|
||||
}
|
||||
|
||||
template <class RanIt>
|
||||
template <class RanIt, class K>
|
||||
RanIt priv_lower_bound(RanIt first, const RanIt last,
|
||||
const key_type & key) const
|
||||
const K & key) const
|
||||
{
|
||||
const Compare &key_cmp = this->m_data.get_comp();
|
||||
KeyOfValue key_extract;
|
||||
@@ -1444,9 +1526,9 @@ class flat_tree
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class RanIt>
|
||||
template <class RanIt, class K>
|
||||
RanIt priv_upper_bound
|
||||
(RanIt first, const RanIt last,const key_type & key) const
|
||||
(RanIt first, const RanIt last,const K & key) const
|
||||
{
|
||||
const Compare &key_cmp = this->m_data.get_comp();
|
||||
KeyOfValue key_extract;
|
||||
@@ -1469,9 +1551,9 @@ class flat_tree
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class RanIt>
|
||||
template <class RanIt, class K>
|
||||
std::pair<RanIt, RanIt>
|
||||
priv_equal_range(RanIt first, RanIt last, const key_type& key) const
|
||||
priv_equal_range(RanIt first, RanIt last, const K& key) const
|
||||
{
|
||||
const Compare &key_cmp = this->m_data.get_comp();
|
||||
KeyOfValue key_extract;
|
||||
@@ -1502,8 +1584,8 @@ class flat_tree
|
||||
return std::pair<RanIt, RanIt>(first, first);
|
||||
}
|
||||
|
||||
template<class RanIt>
|
||||
std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const key_type& k) const
|
||||
template<class RanIt, class K>
|
||||
std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const K& k) const
|
||||
{
|
||||
const Compare &key_cmp = this->m_data.get_comp();
|
||||
KeyOfValue key_extract;
|
||||
|
@@ -76,6 +76,24 @@ struct select1st
|
||||
{ return const_cast<type&>(x.first); }
|
||||
};
|
||||
|
||||
template <class T, class=void>
|
||||
struct is_transparent
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_transparent<T, typename T::is_transparent>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <typename C, typename K, typename R>
|
||||
struct enable_if_transparent
|
||||
: boost::move_detail::enable_if_c<dtl::is_transparent<C>::value, R>
|
||||
{};
|
||||
|
||||
|
||||
} //namespace dtl {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
@@ -394,6 +394,7 @@ class RecyclingCloner
|
||||
intrusive_container &m_icont;
|
||||
};
|
||||
|
||||
|
||||
template<class KeyCompare, class KeyOfValue>
|
||||
struct key_node_compare
|
||||
: public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
|
||||
@@ -407,6 +408,21 @@ struct key_node_compare
|
||||
typedef KeyOfValue key_of_value;
|
||||
typedef typename KeyOfValue::type key_type;
|
||||
|
||||
|
||||
template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
|
||||
BOOST_CONTAINER_FORCEINLINE static const key_type &
|
||||
key_from(const tree_node<T, VoidPointer, tree_type_value, OptimizeSize> &n)
|
||||
{
|
||||
return key_of_value()(n.get_data());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_CONTAINER_FORCEINLINE static const T &
|
||||
key_from(const T &t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const key_compare &key_comp() const
|
||||
{ return static_cast<const key_compare &>(*this); }
|
||||
|
||||
@@ -418,15 +434,15 @@ struct key_node_compare
|
||||
|
||||
template<class U>
|
||||
BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const U &nonkey2) const
|
||||
{ return this->key_comp()(key1, key_of_value()(nonkey2.get_data())); }
|
||||
{ return this->key_comp()(key1, this->key_from(nonkey2)); }
|
||||
|
||||
template<class U>
|
||||
BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const key_type &key2) const
|
||||
{ return this->key_comp()(key_of_value()(nonkey1.get_data()), key2); }
|
||||
{ return this->key_comp()(this->key_from(nonkey1), key2); }
|
||||
|
||||
template<class U, class V>
|
||||
BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const V &nonkey2) const
|
||||
{ return this->key_comp()(key_of_value()(nonkey1.get_data()), key_of_value()(nonkey2.get_data())); }
|
||||
{ return this->key_comp()(this->key_from(nonkey1), this->key_from(nonkey2)); }
|
||||
};
|
||||
|
||||
template<class Options>
|
||||
@@ -1260,21 +1276,63 @@ class tree
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& k) const
|
||||
{ return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, iterator>::type
|
||||
find(const K& k)
|
||||
{ return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
|
||||
find(const K& k) const
|
||||
{ return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& k) const
|
||||
{ return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, size_type>::type
|
||||
count(const K& k) const
|
||||
{ return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k)
|
||||
{ return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const
|
||||
{ return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, iterator>::type
|
||||
lower_bound(const K& k)
|
||||
{ return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
|
||||
lower_bound(const K& k) const
|
||||
{ return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k)
|
||||
{ return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const
|
||||
{ return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, iterator>::type
|
||||
upper_bound(const K& k)
|
||||
{ return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
|
||||
upper_bound(const K& k) const
|
||||
{ return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
|
||||
|
||||
std::pair<iterator,iterator> equal_range(const key_type& k)
|
||||
{
|
||||
std::pair<iiterator, iiterator> ret =
|
||||
@@ -1290,6 +1348,27 @@ class tree
|
||||
(const_iterator(ret.first), const_iterator(ret.second));
|
||||
}
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
|
||||
equal_range(const K& k)
|
||||
{
|
||||
std::pair<iiterator, iiterator> ret =
|
||||
this->icont().equal_range(k, KeyNodeCompare(key_comp()));
|
||||
return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
|
||||
}
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type
|
||||
equal_range(const K& k) const
|
||||
{
|
||||
std::pair<iiterator, iiterator> ret =
|
||||
this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp()));
|
||||
return std::pair<const_iterator,const_iterator>
|
||||
(const_iterator(ret.first), const_iterator(ret.second));
|
||||
}
|
||||
|
||||
std::pair<iterator,iterator> lower_bound_range(const key_type& k)
|
||||
{
|
||||
std::pair<iiterator, iiterator> ret =
|
||||
@@ -1305,6 +1384,27 @@ class tree
|
||||
(const_iterator(ret.first), const_iterator(ret.second));
|
||||
}
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
|
||||
lower_bound_range(const K& k)
|
||||
{
|
||||
std::pair<iiterator, iiterator> ret =
|
||||
this->icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
|
||||
return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
|
||||
}
|
||||
|
||||
template <class K>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type
|
||||
lower_bound_range(const K& k) const
|
||||
{
|
||||
std::pair<iiterator, iiterator> ret =
|
||||
this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
|
||||
return std::pair<const_iterator,const_iterator>
|
||||
(const_iterator(ret.first), const_iterator(ret.second));
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void rebalance()
|
||||
{ intrusive_tree_proxy_t::rebalance(this->icont()); }
|
||||
|
||||
|
@@ -1302,12 +1302,44 @@ class flat_map
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator find(const K& x)
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const_iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator find(const K& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
|
||||
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
|
||||
{ return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
|
||||
{ return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
@@ -1322,6 +1354,28 @@ class flat_map
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const K& x)
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const K& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
@@ -1336,6 +1390,28 @@ class flat_map
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const K& x)
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const K& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
|
||||
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
@@ -1348,6 +1424,26 @@ class flat_map
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
|
||||
{ return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
|
||||
{ return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
|
||||
{ return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
|
||||
|
||||
//! <b>Effects</b>: Extracts the internal sequence container.
|
||||
//!
|
||||
//! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
|
||||
@@ -2443,12 +2539,44 @@ class flat_multimap
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator find(const K& x)
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An const_iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator find(const K& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
|
||||
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
|
||||
{ return m_flat_tree.count(x); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
|
||||
{ return m_flat_tree.count(x); }
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
@@ -2456,12 +2584,34 @@ class flat_multimap
|
||||
BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x)
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
|
||||
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key
|
||||
//! not less than k, or a.end() if such an element is not found.
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const K& x)
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const K& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
@@ -2477,6 +2627,28 @@ class flat_multimap
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const K& x)
|
||||
{return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key
|
||||
//! not less than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const K& x) const
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
|
||||
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
@@ -2489,6 +2661,26 @@ class flat_multimap
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
|
||||
{ return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
|
||||
{ return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<class K>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
|
||||
{ return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
|
||||
|
||||
//! <b>Effects</b>: Extracts the internal sequence container.
|
||||
//!
|
||||
//! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
|
||||
|
@@ -823,6 +823,26 @@ class flat_set
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
const_iterator find(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<typename K>
|
||||
iterator find(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const_iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<typename K>
|
||||
const_iterator find(const K& x) const;
|
||||
|
||||
//! <b>Requires</b>: size() >= n.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns an iterator to the nth element
|
||||
@@ -881,6 +901,16 @@ class flat_set
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
|
||||
{ return static_cast<size_type>(this->tree_t::find(x) != this->tree_t::cend()); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
template<typename K>
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
|
||||
{ return static_cast<size_type>(this->tree_t::find(x) != this->tree_t::cend()); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
@@ -894,6 +924,26 @@ class flat_set
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
const_iterator lower_bound(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
iterator lower_bound(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
const_iterator lower_bound(const K& x) const;
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
@@ -906,6 +956,26 @@ class flat_set
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
const_iterator upper_bound(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
iterator upper_bound(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
const_iterator upper_bound(const K& x) const;
|
||||
|
||||
#endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
@@ -920,6 +990,26 @@ class flat_set
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
|
||||
{ return this->tree_t::lower_bound_range(x); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
std::pair<iterator,iterator> equal_range(const K& x)
|
||||
{ return this->tree_t::lower_bound_range(x); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
std::pair<const_iterator,const_iterator> equal_range(const K& x) const
|
||||
{ return this->tree_t::lower_bound_range(x); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Effects</b>: Returns true if x and y are equal
|
||||
|
@@ -1079,6 +1079,26 @@ class map
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
const_iterator find(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<typename K>
|
||||
iterator find(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const_iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<typename K>
|
||||
const_iterator find(const K& x) const;
|
||||
|
||||
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
@@ -1087,6 +1107,16 @@ class map
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
|
||||
{ return static_cast<size_type>(this->find(x) != this->cend()); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
template<typename K>
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
|
||||
{ return static_cast<size_type>(this->find(x) != this->cend()); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
@@ -1101,6 +1131,26 @@ class map
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
const_iterator lower_bound(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
iterator lower_bound(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
const_iterator lower_bound(const K& x) const;
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
@@ -1113,6 +1163,26 @@ class map
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
const_iterator upper_bound(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
iterator upper_bound(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
const_iterator upper_bound(const K& x) const;
|
||||
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
@@ -1123,6 +1193,24 @@ class map
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
std::pair<iterator,iterator> equal_range(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
std::pair<const_iterator,const_iterator> equal_range(const K& x) const;
|
||||
|
||||
//! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear
|
||||
@@ -1841,11 +1929,40 @@ class multimap
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
const_iterator find(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<typename K>
|
||||
iterator find(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const_iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<typename K>
|
||||
const_iterator find(const K& x) const;
|
||||
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
size_type count(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
template<typename K>
|
||||
size_type count(const K& x) const;
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
@@ -1858,6 +1975,26 @@ class multimap
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
const_iterator lower_bound(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
iterator lower_bound(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
const_iterator lower_bound(const K& x) const;
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
@@ -1870,6 +2007,26 @@ class multimap
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
const_iterator upper_bound(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
iterator upper_bound(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
const_iterator upper_bound(const K& x) const;
|
||||
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
@@ -1880,6 +2037,24 @@ class multimap
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
std::pair<iterator,iterator> equal_range(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
std::pair<const_iterator,const_iterator> equal_range(const K& x) const;
|
||||
|
||||
//! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear
|
||||
|
@@ -734,6 +734,26 @@ class set
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
const_iterator find(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<typename K>
|
||||
iterator find(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const_iterator pointing to an element with the key
|
||||
//! equivalent to x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template<typename K>
|
||||
const_iterator find(const K& x) const;
|
||||
|
||||
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
@@ -742,6 +762,16 @@ class set
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
|
||||
{ return static_cast<size_type>(this->base_t::find(x) != this->base_t::cend()); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
template<typename K>
|
||||
BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
|
||||
{ return static_cast<size_type>(this->find(x) != this->cend()); }
|
||||
|
||||
//! <b>Returns</b>: The number of elements with key equivalent to x.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(size())+count(k)
|
||||
@@ -762,6 +792,26 @@ class set
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
const_iterator lower_bound(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
iterator lower_bound(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than k, or a.end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
const_iterator lower_bound(const K& x) const;
|
||||
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
@@ -774,6 +824,26 @@ class set
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
const_iterator upper_bound(const key_type& x) const;
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the first element with key not less
|
||||
//! than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
iterator upper_bound(const K& x);
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Returns</b>: A const iterator pointing to the first element with key not
|
||||
//! less than x, or end() if such an element is not found.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
const_iterator upper_bound(const K& x) const;
|
||||
|
||||
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
@@ -788,18 +858,28 @@ class set
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
|
||||
{ return this->base_t::lower_bound_range(x); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
std::pair<iterator,iterator> equal_range(const K& x)
|
||||
{ return this->base_t::lower_bound_range(x); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
template<typename K>
|
||||
std::pair<const_iterator,const_iterator> equal_range(const K& x) const
|
||||
{ return this->base_t::lower_bound_range(x); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
std::pair<iterator,iterator> equal_range(const key_type& x);
|
||||
|
||||
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
|
||||
|
||||
//! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear
|
||||
@@ -1330,27 +1410,63 @@ class multiset
|
||||
//! @copydoc ::boost::container::set::find(const key_type& ) const
|
||||
const_iterator find(const key_type& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::find(const K& )
|
||||
template<typename K>
|
||||
iterator find(const K& x);
|
||||
|
||||
//! @copydoc ::boost::container::set::find(const K& )
|
||||
template<typename K>
|
||||
const_iterator find(const K& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::count(const key_type& ) const
|
||||
size_type count(const key_type& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::count(const K& ) const
|
||||
template<typename K>
|
||||
size_type count(const K& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::lower_bound(const key_type& )
|
||||
iterator lower_bound(const key_type& x);
|
||||
|
||||
//! @copydoc ::boost::container::set::lower_bound(const key_type& ) const
|
||||
const_iterator lower_bound(const key_type& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::lower_bound(const K& )
|
||||
template<typename K>
|
||||
iterator lower_bound(const K& x);
|
||||
|
||||
//! @copydoc ::boost::container::set::lower_bound(const K& ) const
|
||||
template<typename K>
|
||||
const_iterator lower_bound(const K& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::upper_bound(const key_type& )
|
||||
iterator upper_bound(const key_type& x);
|
||||
|
||||
//! @copydoc ::boost::container::set::upper_bound(const key_type& ) const
|
||||
const_iterator upper_bound(const key_type& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::upper_bound(const K& )
|
||||
template<typename K>
|
||||
iterator upper_bound(const K& x);
|
||||
|
||||
//! @copydoc ::boost::container::set::upper_bound(const K& ) const
|
||||
template<typename K>
|
||||
const_iterator upper_bound(const K& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::equal_range(const key_type& ) const
|
||||
std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::equal_range(const key_type& )
|
||||
std::pair<iterator,iterator> equal_range(const key_type& x);
|
||||
|
||||
//! @copydoc ::boost::container::set::equal_range(const K& ) const
|
||||
template<typename K>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& x) const;
|
||||
|
||||
//! @copydoc ::boost::container::set::equal_range(const K& )
|
||||
template<typename K>
|
||||
std::pair<iterator,iterator> equal_range(const K& x);
|
||||
|
||||
//! @copydoc ::boost::container::set::rebalance()
|
||||
void rebalance();
|
||||
|
||||
|
@@ -108,6 +108,17 @@ bool CheckEqualPairContainers(const MyBoostCont &boostcont, const MyStdCont &std
|
||||
return true;
|
||||
}
|
||||
|
||||
struct less_transparent
|
||||
{
|
||||
typedef void is_transparent;
|
||||
|
||||
template<class T, class U>
|
||||
bool operator()(const T &t, const U &u) const
|
||||
{
|
||||
return t < u;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace test{
|
||||
} //namespace container {
|
||||
} //namespace boost{
|
||||
|
@@ -422,6 +422,85 @@ struct get_real_stored_allocator<flat_multimap<Key, T, Compare, Allocator> >
|
||||
typedef typename flat_multimap<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
|
||||
};
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
typedef flat_map<int, char, less_transparent> map_t;
|
||||
typedef flat_multimap<int, char, less_transparent> mmap_t;
|
||||
typedef map_t::value_type value_type;
|
||||
|
||||
map_t map1;
|
||||
mmap_t mmap1;
|
||||
|
||||
const map_t &cmap1 = map1;
|
||||
const mmap_t &cmmap1 = mmap1;
|
||||
|
||||
map1.insert_or_assign(1, 'a');
|
||||
map1.insert_or_assign(1, 'b');
|
||||
map1.insert_or_assign(2, 'c');
|
||||
map1.insert_or_assign(2, 'd');
|
||||
map1.insert_or_assign(3, 'e');
|
||||
|
||||
mmap1.insert(value_type(1, 'a'));
|
||||
mmap1.insert(value_type(1, 'b'));
|
||||
mmap1.insert(value_type(2, 'c'));
|
||||
mmap1.insert(value_type(2, 'd'));
|
||||
mmap1.insert(value_type(3, 'e'));
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(map1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(map1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cmap1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mmap1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmmap1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(map1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(map1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(mmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(map1.equal_range(find_me).first->second != 'd')
|
||||
return false;
|
||||
if(cmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
if(mmap1.equal_range(find_me).first->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}} //namespace boost::container::test
|
||||
|
||||
template<class VoidAllocatorOrContainer>
|
||||
@@ -527,6 +606,9 @@ int main()
|
||||
if (!boost::container::test::instantiate_constructors<flat_map<int, int>, flat_multimap<int, int> >())
|
||||
return 1;
|
||||
|
||||
if (!test_heterogeneous_lookups())
|
||||
return 1;
|
||||
|
||||
////////////////////////////////////
|
||||
// Testing allocator implementations
|
||||
////////////////////////////////////
|
||||
|
@@ -450,6 +450,84 @@ bool flat_tree_extract_adopt_test()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
typedef flat_set<int, test::less_transparent> set_t;
|
||||
typedef flat_multiset<int, test::less_transparent> mset_t;
|
||||
|
||||
set_t set1;
|
||||
mset_t mset1;
|
||||
|
||||
const set_t &cset1 = set1;
|
||||
const mset_t &cmset1 = mset1;
|
||||
|
||||
set1.insert(1);
|
||||
set1.insert(1);
|
||||
set1.insert(2);
|
||||
set1.insert(2);
|
||||
set1.insert(3);
|
||||
|
||||
mset1.insert(1);
|
||||
mset1.insert(1);
|
||||
mset1.insert(2);
|
||||
mset1.insert(2);
|
||||
mset1.insert(3);
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(*set1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.find(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(set1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cset1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mset1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmset1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(*set1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(*set1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*mset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cmset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(*set1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
if(*mset1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cmset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
template<class VoidAllocatorOrContainer>
|
||||
@@ -636,6 +714,10 @@ int main()
|
||||
if (!boost::container::test::instantiate_constructors<flat_set<int>, flat_multiset<int> >())
|
||||
return 1;
|
||||
|
||||
if(!test_heterogeneous_lookups()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Testing allocator implementations
|
||||
////////////////////////////////////
|
||||
|
@@ -320,6 +320,85 @@ void test_merge_from_different_comparison()
|
||||
map1.merge(map2);
|
||||
}
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
typedef map<int, char, less_transparent> map_t;
|
||||
typedef multimap<int, char, less_transparent> mmap_t;
|
||||
typedef map_t::value_type value_type;
|
||||
|
||||
map_t map1;
|
||||
mmap_t mmap1;
|
||||
|
||||
const map_t &cmap1 = map1;
|
||||
const mmap_t &cmmap1 = mmap1;
|
||||
|
||||
map1.insert_or_assign(1, 'a');
|
||||
map1.insert_or_assign(1, 'b');
|
||||
map1.insert_or_assign(2, 'c');
|
||||
map1.insert_or_assign(2, 'd');
|
||||
map1.insert_or_assign(3, 'e');
|
||||
|
||||
mmap1.insert(value_type(1, 'a'));
|
||||
mmap1.insert(value_type(1, 'b'));
|
||||
mmap1.insert(value_type(2, 'c'));
|
||||
mmap1.insert(value_type(2, 'd'));
|
||||
mmap1.insert(value_type(3, 'e'));
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(map1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(map1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cmap1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mmap1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmmap1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(map1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(map1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(mmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(map1.equal_range(find_me).first->second != 'd')
|
||||
return false;
|
||||
if(cmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
if(mmap1.equal_range(find_me).first->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}} //namespace boost::container::test
|
||||
|
||||
int main ()
|
||||
@@ -437,6 +516,9 @@ int main ()
|
||||
|
||||
test::test_merge_from_different_comparison();
|
||||
|
||||
if(!test::test_heterogeneous_lookups())
|
||||
return 1;
|
||||
|
||||
////////////////////////////////////
|
||||
// Test optimize_size option
|
||||
////////////////////////////////////
|
||||
|
@@ -97,6 +97,12 @@ class movable_int
|
||||
friend bool operator==(int l, const movable_int &r)
|
||||
{ return l == r.get_int(); }
|
||||
|
||||
friend bool operator<(const movable_int &l, int r)
|
||||
{ return l.get_int() < r; }
|
||||
|
||||
friend bool operator<(int l, const movable_int &r)
|
||||
{ return l < r.get_int(); }
|
||||
|
||||
private:
|
||||
int m_int;
|
||||
};
|
||||
@@ -193,6 +199,12 @@ class movable_and_copyable_int
|
||||
friend bool operator==(int l, const movable_and_copyable_int &r)
|
||||
{ return l == r.get_int(); }
|
||||
|
||||
friend bool operator<(const movable_and_copyable_int &l, int r)
|
||||
{ return l.get_int() < r; }
|
||||
|
||||
friend bool operator<(int l, const movable_and_copyable_int &r)
|
||||
{ return l < r.get_int(); }
|
||||
|
||||
private:
|
||||
int m_int;
|
||||
};
|
||||
@@ -280,6 +292,12 @@ class copyable_int
|
||||
friend bool operator==(int l, const copyable_int &r)
|
||||
{ return l == r.get_int(); }
|
||||
|
||||
friend bool operator<(const copyable_int &l, int r)
|
||||
{ return l.get_int() < r; }
|
||||
|
||||
friend bool operator<(int l, const copyable_int &r)
|
||||
{ return l < r.get_int(); }
|
||||
|
||||
private:
|
||||
int m_int;
|
||||
};
|
||||
@@ -351,6 +369,12 @@ class non_copymovable_int
|
||||
friend bool operator==(int l, const non_copymovable_int &r)
|
||||
{ return l == r.get_int(); }
|
||||
|
||||
friend bool operator<(const non_copymovable_int &l, int r)
|
||||
{ return l.get_int() < r; }
|
||||
|
||||
friend bool operator<(int l, const non_copymovable_int &r)
|
||||
{ return l < r.get_int(); }
|
||||
|
||||
private:
|
||||
int m_int;
|
||||
};
|
||||
|
@@ -318,6 +318,84 @@ void test_merge_from_different_comparison()
|
||||
set1.merge(set2);
|
||||
}
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
typedef set<int, test::less_transparent> set_t;
|
||||
typedef multiset<int, test::less_transparent> mset_t;
|
||||
|
||||
set_t set1;
|
||||
mset_t mset1;
|
||||
|
||||
const set_t &cset1 = set1;
|
||||
const mset_t &cmset1 = mset1;
|
||||
|
||||
set1.insert(1);
|
||||
set1.insert(1);
|
||||
set1.insert(2);
|
||||
set1.insert(2);
|
||||
set1.insert(3);
|
||||
|
||||
mset1.insert(1);
|
||||
mset1.insert(1);
|
||||
mset1.insert(2);
|
||||
mset1.insert(2);
|
||||
mset1.insert(3);
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(*set1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.find(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(set1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cset1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mset1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmset1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(*set1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(*set1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*mset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cmset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(*set1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
if(*mset1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cmset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
//Recursive container instantiation
|
||||
@@ -349,6 +427,9 @@ int main ()
|
||||
|
||||
test_merge_from_different_comparison();
|
||||
|
||||
if(!test_heterogeneous_lookups())
|
||||
return 1;
|
||||
|
||||
////////////////////////////////////
|
||||
// Testing allocator implementations
|
||||
////////////////////////////////////
|
||||
|
Reference in New Issue
Block a user