mirror of
https://github.com/boostorg/multi_index.git
synced 2025-05-12 05:41:47 +00:00
improved lookup efficiency in the event of implicit conversion to key_type
This commit is contained in:
parent
87ff899ceb
commit
79541fce51
103
include/boost/multi_index/detail/is_transparent.hpp
Normal file
103
include/boost/multi_index/detail/is_transparent.hpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* Copyright 2003-2014 Joaquin M Lopez Munoz.
|
||||||
|
* 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)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/multi_index for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_MULTI_INDEX_DETAIL_IS_TRANSPARENT_HPP
|
||||||
|
#define BOOST_MULTI_INDEX_DETAIL_IS_TRANSPARENT_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/mpl/bool.hpp>
|
||||||
|
#include <boost/type_traits/intrinsics.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace multi_index{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
/* Metafunction that checks if f(arg,arg2) executes without argument type
|
||||||
|
* conversion. By default (i.e. when it cannot be determined) it evaluates to
|
||||||
|
* true.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2,typename=void>
|
||||||
|
struct is_transparent:mpl::true_{};
|
||||||
|
|
||||||
|
} /* namespace multi_index::detail */
|
||||||
|
|
||||||
|
} /* namespace multi_index */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_SFINAE)&& \
|
||||||
|
!defined(BOOST_NO_CXX11_DECLTYPE)&& \
|
||||||
|
defined(BOOST_IS_FINAL)
|
||||||
|
|
||||||
|
#include <boost/mpl/and.hpp>
|
||||||
|
#include <boost/mpl/not.hpp>
|
||||||
|
#include <boost/type_traits/is_class.hpp>
|
||||||
|
#include <boost/type_traits/is_final.hpp>
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
#include <boost/utility/declval.hpp>
|
||||||
|
#include <boost/utility/enable_if.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace multi_index{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
struct not_is_transparent_result_type{};
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2>
|
||||||
|
struct is_transparent_class_helper:F
|
||||||
|
{
|
||||||
|
using F::operator();
|
||||||
|
template<typename T,typename Q>
|
||||||
|
not_is_transparent_result_type operator()(T,Q)const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2,typename=void>
|
||||||
|
struct is_transparent_class:mpl::true_{};
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2>
|
||||||
|
struct is_transparent_class<
|
||||||
|
F,Arg1,Arg2,
|
||||||
|
typename enable_if<
|
||||||
|
is_same<
|
||||||
|
decltype(
|
||||||
|
declval<const is_transparent_class_helper<F,Arg1,Arg2> >()(
|
||||||
|
declval<const Arg1&>(),declval<const Arg2&>())
|
||||||
|
),
|
||||||
|
not_is_transparent_result_type
|
||||||
|
>
|
||||||
|
>::type
|
||||||
|
>:mpl::false_{};
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2>
|
||||||
|
struct is_transparent<
|
||||||
|
F,Arg1,Arg2,
|
||||||
|
typename enable_if<
|
||||||
|
mpl::and_<
|
||||||
|
is_class<F>,
|
||||||
|
mpl::not_<is_final<F> >
|
||||||
|
>
|
||||||
|
>::type
|
||||||
|
>:is_transparent_class<F,Arg1,Arg2>{};
|
||||||
|
|
||||||
|
} /* namespace multi_index::detail */
|
||||||
|
|
||||||
|
} /* namespace multi_index */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2003-2013 Joaquin M Lopez Munoz.
|
/* Copyright 2003-2014 Joaquin M Lopez Munoz.
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@ -41,6 +41,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/mpl/and.hpp>
|
||||||
|
#include <boost/multi_index/detail/promotes_arg.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace boost{
|
namespace boost{
|
||||||
@ -51,6 +53,9 @@ namespace detail{
|
|||||||
|
|
||||||
/* Common code for index memfuns having templatized and
|
/* Common code for index memfuns having templatized and
|
||||||
* non-templatized versions.
|
* non-templatized versions.
|
||||||
|
* Implementation note: When CompatibleKey is consistently promoted to
|
||||||
|
* KeyFromValue::result_type for comparison, the promotion is made once in
|
||||||
|
* advance to increase efficiency.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<
|
template<
|
||||||
@ -60,6 +65,35 @@ template<
|
|||||||
inline Node* ordered_index_find(
|
inline Node* ordered_index_find(
|
||||||
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||||
const CompatibleCompare& comp)
|
const CompatibleCompare& comp)
|
||||||
|
{
|
||||||
|
typedef typename KeyFromValue::result_type key_type;
|
||||||
|
|
||||||
|
return ordered_index_find(
|
||||||
|
top,y,key,x,comp,
|
||||||
|
mpl::and_<
|
||||||
|
promotes_1st_arg<CompatibleCompare,CompatibleKey,key_type>,
|
||||||
|
promotes_2nd_arg<CompatibleCompare,key_type,CompatibleKey>>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Node,typename KeyFromValue,
|
||||||
|
typename CompatibleCompare
|
||||||
|
>
|
||||||
|
inline Node* ordered_index_find(
|
||||||
|
Node* top,Node* y,const KeyFromValue& key,
|
||||||
|
const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
|
||||||
|
const CompatibleCompare& comp,mpl::true_)
|
||||||
|
{
|
||||||
|
return ordered_index_find(top,y,key,x,comp,mpl::false_());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Node,typename KeyFromValue,
|
||||||
|
typename CompatibleKey,typename CompatibleCompare
|
||||||
|
>
|
||||||
|
inline Node* ordered_index_find(
|
||||||
|
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||||
|
const CompatibleCompare& comp,mpl::false_)
|
||||||
{
|
{
|
||||||
Node* y0=y;
|
Node* y0=y;
|
||||||
|
|
||||||
@ -81,6 +115,33 @@ template<
|
|||||||
inline Node* ordered_index_lower_bound(
|
inline Node* ordered_index_lower_bound(
|
||||||
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||||
const CompatibleCompare& comp)
|
const CompatibleCompare& comp)
|
||||||
|
{
|
||||||
|
typedef typename KeyFromValue::result_type key_type;
|
||||||
|
|
||||||
|
return ordered_index_lower_bound(
|
||||||
|
top,y,key,x,comp,
|
||||||
|
promotes_2nd_arg<CompatibleCompare,key_type,CompatibleKey>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Node,typename KeyFromValue,
|
||||||
|
typename CompatibleCompare
|
||||||
|
>
|
||||||
|
inline Node* ordered_index_lower_bound(
|
||||||
|
Node* top,Node* y,const KeyFromValue& key,
|
||||||
|
const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
|
||||||
|
const CompatibleCompare& comp,mpl::true_)
|
||||||
|
{
|
||||||
|
return ordered_index_lower_bound(top,y,key,x,comp,mpl::false_());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Node,typename KeyFromValue,
|
||||||
|
typename CompatibleKey,typename CompatibleCompare
|
||||||
|
>
|
||||||
|
inline Node* ordered_index_lower_bound(
|
||||||
|
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||||
|
const CompatibleCompare& comp,mpl::false_)
|
||||||
{
|
{
|
||||||
while(top){
|
while(top){
|
||||||
if(!comp(key(top->value()),x)){
|
if(!comp(key(top->value()),x)){
|
||||||
@ -100,6 +161,33 @@ template<
|
|||||||
inline Node* ordered_index_upper_bound(
|
inline Node* ordered_index_upper_bound(
|
||||||
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||||
const CompatibleCompare& comp)
|
const CompatibleCompare& comp)
|
||||||
|
{
|
||||||
|
typedef typename KeyFromValue::result_type key_type;
|
||||||
|
|
||||||
|
return ordered_index_upper_bound(
|
||||||
|
top,y,key,x,comp,
|
||||||
|
promotes_1st_arg<CompatibleCompare,CompatibleKey,key_type>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Node,typename KeyFromValue,
|
||||||
|
typename CompatibleCompare
|
||||||
|
>
|
||||||
|
inline Node* ordered_index_upper_bound(
|
||||||
|
Node* top,Node* y,const KeyFromValue& key,
|
||||||
|
const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
|
||||||
|
const CompatibleCompare& comp,mpl::true_)
|
||||||
|
{
|
||||||
|
return ordered_index_upper_bound(top,y,key,x,comp,mpl::false_());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Node,typename KeyFromValue,
|
||||||
|
typename CompatibleKey,typename CompatibleCompare
|
||||||
|
>
|
||||||
|
inline Node* ordered_index_upper_bound(
|
||||||
|
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||||
|
const CompatibleCompare& comp,mpl::false_)
|
||||||
{
|
{
|
||||||
while(top){
|
while(top){
|
||||||
if(comp(x,key(top->value()))){
|
if(comp(x,key(top->value()))){
|
||||||
@ -119,6 +207,35 @@ template<
|
|||||||
inline std::pair<Node*,Node*> ordered_index_equal_range(
|
inline std::pair<Node*,Node*> ordered_index_equal_range(
|
||||||
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||||
const CompatibleCompare& comp)
|
const CompatibleCompare& comp)
|
||||||
|
{
|
||||||
|
typedef typename KeyFromValue::result_type key_type;
|
||||||
|
|
||||||
|
return ordered_index_equal_range(
|
||||||
|
top,y,key,x,comp,
|
||||||
|
mpl::and_<
|
||||||
|
promotes_1st_arg<CompatibleCompare,CompatibleKey,key_type>,
|
||||||
|
promotes_2nd_arg<CompatibleCompare,key_type,CompatibleKey>>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Node,typename KeyFromValue,
|
||||||
|
typename CompatibleCompare
|
||||||
|
>
|
||||||
|
inline std::pair<Node*,Node*> ordered_index_equal_range(
|
||||||
|
Node* top,Node* y,const KeyFromValue& key,
|
||||||
|
const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
|
||||||
|
const CompatibleCompare& comp,mpl::true_)
|
||||||
|
{
|
||||||
|
return ordered_index_equal_range(top,y,key,x,comp,mpl::false_());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Node,typename KeyFromValue,
|
||||||
|
typename CompatibleKey,typename CompatibleCompare
|
||||||
|
>
|
||||||
|
inline std::pair<Node*,Node*> ordered_index_equal_range(
|
||||||
|
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
|
||||||
|
const CompatibleCompare& comp,mpl::false_)
|
||||||
{
|
{
|
||||||
while(top){
|
while(top){
|
||||||
if(comp(key(top->value()),x)){
|
if(comp(key(top->value()),x)){
|
||||||
@ -130,8 +247,10 @@ inline std::pair<Node*,Node*> ordered_index_equal_range(
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
return std::pair<Node*,Node*>(
|
return std::pair<Node*,Node*>(
|
||||||
ordered_index_lower_bound(Node::from_impl(top->left()),top,key,x,comp),
|
ordered_index_lower_bound(
|
||||||
ordered_index_upper_bound(Node::from_impl(top->right()),y,key,x,comp));
|
Node::from_impl(top->left()),top,key,x,comp,mpl::false_()),
|
||||||
|
ordered_index_upper_bound(
|
||||||
|
Node::from_impl(top->right()),y,key,x,comp,mpl::false_()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
83
include/boost/multi_index/detail/promotes_arg.hpp
Normal file
83
include/boost/multi_index/detail/promotes_arg.hpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* Copyright 2003-2014 Joaquin M Lopez Munoz.
|
||||||
|
* 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)
|
||||||
|
*
|
||||||
|
* See http://www.boost.org/libs/multi_index for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_MULTI_INDEX_DETAIL_PROMOTES_ARG_HPP
|
||||||
|
#define BOOST_MULTI_INDEX_DETAIL_PROMOTES_ARG_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||||
|
#include <boost/mpl/bool.hpp>
|
||||||
|
#include <boost/type_traits/intrinsics.hpp>
|
||||||
|
|
||||||
|
/* Metafunctions to check if f(arg1,arg2) promotes either arg1 to the type of
|
||||||
|
* arg2 or viceversa. By default, (i.e. if it cannot be determined), no
|
||||||
|
* promotion is assumed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(BOOST_IS_CONVERTIBLE)
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace multi_index{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2>
|
||||||
|
struct promotes_1st_arg:mpl::false_{};
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2>
|
||||||
|
struct promotes_2nd_arg:mpl::false_{};
|
||||||
|
|
||||||
|
} /* namespace multi_index::detail */
|
||||||
|
|
||||||
|
} /* namespace multi_index */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <boost/mpl/and.hpp>
|
||||||
|
#include <boost/mpl/not.hpp>
|
||||||
|
#include <boost/multi_index/detail/is_transparent.hpp>
|
||||||
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
|
||||||
|
namespace multi_index{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2>
|
||||||
|
struct promotes_1st_arg:
|
||||||
|
mpl::and_<
|
||||||
|
mpl::not_<is_transparent<F,Arg1,Arg2> >,
|
||||||
|
is_convertible<const Arg1,Arg2>,
|
||||||
|
is_transparent<F,Arg2,Arg2>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename F,typename Arg1,typename Arg2>
|
||||||
|
struct promotes_2nd_arg:
|
||||||
|
mpl::and_<
|
||||||
|
mpl::not_<is_transparent<F,Arg1,Arg2> >,
|
||||||
|
is_convertible<const Arg2,Arg1>,
|
||||||
|
is_transparent<F,Arg1,Arg1>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
} /* namespace multi_index::detail */
|
||||||
|
|
||||||
|
} /* namespace multi_index */
|
||||||
|
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif /* defined(BOOST_IS_CONVERTIBLE) */
|
||||||
|
#endif
|
@ -32,6 +32,7 @@
|
|||||||
#include <boost/multi_index/detail/hash_index_iterator.hpp>
|
#include <boost/multi_index/detail/hash_index_iterator.hpp>
|
||||||
#include <boost/multi_index/detail/index_node_base.hpp>
|
#include <boost/multi_index/detail/index_node_base.hpp>
|
||||||
#include <boost/multi_index/detail/modify_key_adaptor.hpp>
|
#include <boost/multi_index/detail/modify_key_adaptor.hpp>
|
||||||
|
#include <boost/multi_index/detail/promotes_arg.hpp>
|
||||||
#include <boost/multi_index/detail/safe_mode.hpp>
|
#include <boost/multi_index/detail/safe_mode.hpp>
|
||||||
#include <boost/multi_index/detail/scope_guard.hpp>
|
#include <boost/multi_index/detail/scope_guard.hpp>
|
||||||
#include <boost/multi_index/detail/vartempl_support.hpp>
|
#include <boost/multi_index/detail/vartempl_support.hpp>
|
||||||
@ -459,6 +460,11 @@ public:
|
|||||||
* type as iterator.
|
* type as iterator.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Implementation note: When CompatibleKey is consistently promoted to
|
||||||
|
* KeyFromValue::result_type for equality comparison, the promotion is made
|
||||||
|
* once in advance to increase efficiency.
|
||||||
|
*/
|
||||||
|
|
||||||
template<typename CompatibleKey>
|
template<typename CompatibleKey>
|
||||||
iterator find(const CompatibleKey& k)const
|
iterator find(const CompatibleKey& k)const
|
||||||
{
|
{
|
||||||
@ -472,14 +478,8 @@ public:
|
|||||||
const CompatibleKey& k,
|
const CompatibleKey& k,
|
||||||
const CompatibleHash& hash,const CompatiblePred& eq)const
|
const CompatibleHash& hash,const CompatiblePred& eq)const
|
||||||
{
|
{
|
||||||
std::size_t buc=buckets.position(hash(k));
|
return find(
|
||||||
for(node_impl_pointer x=buckets.at(buc)->prior();
|
k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
|
||||||
x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
|
|
||||||
if(eq(k,key(node_type::from_impl(x)->value()))){
|
|
||||||
return make_iterator(node_type::from_impl(x));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CompatibleKey>
|
template<typename CompatibleKey>
|
||||||
@ -495,20 +495,8 @@ public:
|
|||||||
const CompatibleKey& k,
|
const CompatibleKey& k,
|
||||||
const CompatibleHash& hash,const CompatiblePred& eq)const
|
const CompatibleHash& hash,const CompatiblePred& eq)const
|
||||||
{
|
{
|
||||||
std::size_t buc=buckets.position(hash(k));
|
return count(
|
||||||
for(node_impl_pointer x=buckets.at(buc)->prior();
|
k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
|
||||||
x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
|
|
||||||
if(eq(k,key(node_type::from_impl(x)->value()))){
|
|
||||||
size_type res=0;
|
|
||||||
node_impl_pointer y=end_of_range(x);
|
|
||||||
do{
|
|
||||||
++res;
|
|
||||||
x=node_alg::after(x);
|
|
||||||
}while(x!=y);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CompatibleKey>
|
template<typename CompatibleKey>
|
||||||
@ -524,16 +512,8 @@ public:
|
|||||||
const CompatibleKey& k,
|
const CompatibleKey& k,
|
||||||
const CompatibleHash& hash,const CompatiblePred& eq)const
|
const CompatibleHash& hash,const CompatiblePred& eq)const
|
||||||
{
|
{
|
||||||
std::size_t buc=buckets.position(hash(k));
|
return equal_range(
|
||||||
for(node_impl_pointer x=buckets.at(buc)->prior();
|
k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
|
||||||
x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
|
|
||||||
if(eq(k,key(node_type::from_impl(x)->value()))){
|
|
||||||
return std::pair<iterator,iterator>(
|
|
||||||
make_iterator(node_type::from_impl(x)),
|
|
||||||
make_iterator(node_type::from_impl(end_of_range(x))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::pair<iterator,iterator>(end(),end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bucket interface */
|
/* bucket interface */
|
||||||
@ -1527,6 +1507,95 @@ private:
|
|||||||
return make_iterator(p.first);
|
return make_iterator(p.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename CompatibleHash,typename CompatiblePred
|
||||||
|
>
|
||||||
|
iterator find(
|
||||||
|
const key_type& k,
|
||||||
|
const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
|
||||||
|
{
|
||||||
|
return find(k,hash,eq,mpl::false());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
|
||||||
|
>
|
||||||
|
iterator find(
|
||||||
|
const CompatibleKey& k,
|
||||||
|
const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
|
||||||
|
{
|
||||||
|
std::size_t buc=buckets.position(hash(k));
|
||||||
|
for(node_impl_pointer x=buckets.at(buc)->prior();
|
||||||
|
x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
|
||||||
|
if(eq(k,key(node_type::from_impl(x)->value()))){
|
||||||
|
return make_iterator(node_type::from_impl(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename CompatibleHash,typename CompatiblePred
|
||||||
|
>
|
||||||
|
size_type count(
|
||||||
|
const key_type& k,
|
||||||
|
const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
|
||||||
|
{
|
||||||
|
return count(k,hash,eq,mpl::false());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
|
||||||
|
>
|
||||||
|
size_type count(
|
||||||
|
const CompatibleKey& k,
|
||||||
|
const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
|
||||||
|
{
|
||||||
|
std::size_t buc=buckets.position(hash(k));
|
||||||
|
for(node_impl_pointer x=buckets.at(buc)->prior();
|
||||||
|
x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
|
||||||
|
if(eq(k,key(node_type::from_impl(x)->value()))){
|
||||||
|
size_type res=0;
|
||||||
|
node_impl_pointer y=end_of_range(x);
|
||||||
|
do{
|
||||||
|
++res;
|
||||||
|
x=node_alg::after(x);
|
||||||
|
}while(x!=y);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename CompatibleHash,typename CompatiblePred
|
||||||
|
>
|
||||||
|
std::pair<iterator,iterator> equal_range(
|
||||||
|
const key_type& k,
|
||||||
|
const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
|
||||||
|
{
|
||||||
|
return equal_range(k,hash,eq,mpl::false_());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
|
||||||
|
>
|
||||||
|
std::pair<iterator,iterator> equal_range(
|
||||||
|
const CompatibleKey& k,
|
||||||
|
const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
|
||||||
|
{
|
||||||
|
std::size_t buc=buckets.position(hash(k));
|
||||||
|
for(node_impl_pointer x=buckets.at(buc)->prior();
|
||||||
|
x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
|
||||||
|
if(eq(k,key(node_type::from_impl(x)->value()))){
|
||||||
|
return std::pair<iterator,iterator>(
|
||||||
|
make_iterator(node_type::from_impl(x)),
|
||||||
|
make_iterator(node_type::from_impl(end_of_range(x))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::pair<iterator,iterator>(end(),end());
|
||||||
|
}
|
||||||
|
|
||||||
key_from_value key;
|
key_from_value key;
|
||||||
hasher hash_;
|
hasher hash_;
|
||||||
key_equal eq_;
|
key_equal eq_;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Boost.MultiIndex test for standard set operations.
|
/* Boost.MultiIndex test for standard set operations.
|
||||||
*
|
*
|
||||||
* Copyright 2003-2013 Joaquin M Lopez Munoz.
|
* Copyright 2003-2014 Joaquin M Lopez Munoz.
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@ -19,6 +19,34 @@
|
|||||||
|
|
||||||
using namespace boost::multi_index;
|
using namespace boost::multi_index;
|
||||||
|
|
||||||
|
struct type1{};
|
||||||
|
|
||||||
|
struct type2
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
operator type1()const{return type1();}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct less_type12
|
||||||
|
{
|
||||||
|
bool operator()(type1,type1)const{return false;}
|
||||||
|
bool operator()(type1,type2)const{return false;}
|
||||||
|
bool operator()(type2,type1)const{return false;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hash_type12
|
||||||
|
{
|
||||||
|
std::size_t operator()(type1)const{return 0;}
|
||||||
|
std::size_t operator()(type2)const{return 0;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct eq_type12
|
||||||
|
{
|
||||||
|
bool operator()(type1,type1)const{return true;}
|
||||||
|
bool operator()(type1,type2)const{return true;}
|
||||||
|
bool operator()(type2,type1)const{return true;}
|
||||||
|
};
|
||||||
|
|
||||||
void test_set_ops()
|
void test_set_ops()
|
||||||
{
|
{
|
||||||
employee_set es;
|
employee_set es;
|
||||||
@ -55,4 +83,26 @@ void test_set_ops()
|
|||||||
std::pair<employee_set_by_age::iterator,employee_set_by_age::iterator> p2=
|
std::pair<employee_set_by_age::iterator,employee_set_by_age::iterator> p2=
|
||||||
i2.equal_range(30);
|
i2.equal_range(30);
|
||||||
BOOST_TEST(p2.first==p2.second&&p2.first->age==31);
|
BOOST_TEST(p2.first==p2.second&&p2.first->age==31);
|
||||||
|
|
||||||
|
/* check promotion detection plays nice with private conversion */
|
||||||
|
|
||||||
|
multi_index_container<
|
||||||
|
type1,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique<identity<type1>,less_type12>,
|
||||||
|
hashed_unique<identity<type1>,hash_type12,eq_type12>
|
||||||
|
>
|
||||||
|
> c;
|
||||||
|
c.insert(type1());
|
||||||
|
|
||||||
|
BOOST_TEST(c.find(type2())==c.begin());
|
||||||
|
BOOST_TEST(c.count(type2())==1);
|
||||||
|
BOOST_TEST(c.lower_bound(type2())==c.begin());
|
||||||
|
BOOST_TEST(c.upper_bound(type2())==c.end());
|
||||||
|
BOOST_TEST(c.equal_range(type2())==std::make_pair(c.begin(),c.end()));
|
||||||
|
|
||||||
|
BOOST_TEST(c.get<1>().find(type2())==c.get<1>().begin());
|
||||||
|
BOOST_TEST(c.get<1>().count(type2())==1);
|
||||||
|
BOOST_TEST(c.get<1>().equal_range(type2())==
|
||||||
|
std::make_pair(c.get<1>().begin(),c.get<1>().end()));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user