Навязчивыйпредлагает еще одну полезную функцию, которая отсутствует в контейнерах STL: можно получить итератор на значение из самого значения. Эта функция реализована вBoost.Intrusiveконтейнеры с помощью функции, называемой<iterator_to
>:
iterator iterator_to(reference value);
const_iterator iterator_to(const_reference value);
ДляНавязчивыеконтейнеры, которые имеют локальные итераторы, такие как неупорядоченные ассоциативные контейнеры, мы также можем получить локальные итераторы:
local_iterator local_iterator_to(reference value);
const_local_iterator local_iterator_to(const_reference value) const;
Для большинстваBoost.Intrusiveконтейнеров<list
>,<slist
>,<set
>,<multiset
>у нас есть альтернативная статическая<s_iterator_to
>функция.
Для неупорядоченных ассоциативных контейнеров<unordered_set
>,<multiset
><iterator_to
>не имеет статической альтернативной функции. С другой стороны,<local_iterator_to
>функции имеют свои<s_local_iterator_to
>статические альтернативы.
Альтернативные статические функции доступны при определенных обстоятельствах, описанных в. Утвержденные характеристики; если программист использует крючки, предоставляемыеBoost.Intrusive, эти функции будут доступны.
Давайте посмотрим на небольшую функцию, которая показывает использование<iterator_to
>и<local_iterator_to
>:
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/functional/hash.hpp>
#include <vector>
using namespace boost::intrusive;
class intrusive_data
{
int data_id_;
public:
void set(int id) { data_id_ = id; }
list_member_hook<> list_hook_;
unordered_set_member_hook<> unordered_set_hook_;
friend bool operator==(const intrusive_data &a, const intrusive_data &b)
{ return a.data_id_ == b.data_id_; }
friend bool operator!=(const intrusive_data &a, const intrusive_data &b)
{ return a.data_id_ != b.data_id_; }
friend std::size_t hash_value(const intrusive_data &i)
{ return boost::hash<int>()(i.data_id_); }
};
typedef member_hook<intrusive_data, list_member_hook<>
, &intrusive_data::list_hook_> MemberListOption;
typedef list<intrusive_data, MemberListOption> list_t;
typedef member_hook
< intrusive_data, unordered_set_member_hook<>
, &intrusive_data::unordered_set_hook_> MemberUsetOption;
typedef boost::intrusive::unordered_set
< intrusive_data, MemberUsetOption> unordered_set_t;
int main()
{
const int MaxElem = 100;
std::vector<intrusive_data> nodes(MaxElem);
list_t list;
unordered_set_t::bucket_type buckets[MaxElem];
unordered_set_t unordered_set
(unordered_set_t::bucket_traits(buckets, MaxElem));
for(int i = 0; i < MaxElem; ++i) nodes[i].set(i);
list.insert(list.end(), nodes.begin(), nodes.end());
unordered_set.insert(nodes.begin(), nodes.end());
list_t::iterator list_it(list.begin());
for(int i = 0; i < MaxElem; ++i, ++list_it)
if(list.iterator_to(nodes[i]) != list_it ||
list_t::s_iterator_to(nodes[i]) != list_it)
return 1;
unordered_set_t::iterator unordered_set_it(unordered_set.begin());
for(int i = 0; i < MaxElem; ++i){
unordered_set_it = unordered_set.find(nodes[i]);
if(unordered_set.iterator_to(nodes[i]) != unordered_set_it)
return 1;
if(*unordered_set.local_iterator_to(nodes[i]) != *unordered_set_it ||
*unordered_set_t::s_local_iterator_to(nodes[i]) != *unordered_set_it )
return 1;
}
return 0;
}