Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

Bimaps with user defined names

In the following example, the library user inserted comments to guide future programmers:

Go to source code

typedef bimap
<
    multiset_of<std::string>,
    int

> People;

People people;

// ...

int user_id;
std::cin >> user_id;

// people.right : map<id,name>

People::right_const_iterator id_iter = people.right.find(user_id);
if( id_iter != people.right.end() )
{
    // first  : id
    // second : name

    std::cout << "name: " << id_iter->second << std::endl
              << "id:   " << id_iter->first  << std::endl;
}
else
{
    std::cout << "Unknown id, users are:" << std::endl;

    // people.left : map<name,id>

    for( People::left_const_iterator
            name_iter = people.left.begin(),
            iend      = people.left.end();

         name_iter != iend; ++name_iter )
    {
        // first  : name
        // second : id

        std::cout << "name: " << name_iter->first  << std::endl
                  << "id:   " << name_iter->second << std::endl;
    }
}

In Boost.Bimap there is a better way to document the code and in the meantime helping you to write more mantainable and readable code. You can tag the two collections of the bimap so they can be accessed by more descriptive names.

tagged

A tagged type is a type that has been labelled using a tag. A tag is any valid C++ type. In a bimap, the types are always tagged. If you do not specify your own tag, the container uses member_at::left and member_at::right to tag the left and right sides respectively. In order to specify a custom tag, the type of each side has to be tagged. Tagging a type is very simple:

typedef tagged< int, a_tag > tagged_int;

Now we can rewrite the example:

Go to source code

struct id   {}; // Tag for the identification number
struct name {}; // Tag for the name of the person

typedef bimap
<
                 tagged< int        , id   >  ,
    multiset_of< tagged< std::string, name > >

> People;

People people;

// ...

int user_id;
std::cin >> user_id;

People::map_by<id>::const_iterator id_iter = people.by<id>().find(user_id);
if( id_iter != people.by<id>().end() )
{
    std::cout << "name: " << id_iter->get<name>() << std::endl
              << "id:   " << id_iter->get<id>()   << std::endl;
}
else
{
    std::cout << "Unknown id, users are:" << std::endl;

    for( People::map_by<name>::const_iterator
            name_iter = people.by<name>().begin(),
            iend      = people.by<name>().end();

        name_iter != iend; ++name_iter )
    {
        std::cout << "name: " << name_iter->get<name>() << std::endl
                  << "id:   " << name_iter->get<id>()   << std::endl;
    }
}

Here is a list of common structures in both tagged and untagged versions. Remember that when the bimap has user defined tags you can still use the untagged version structures.

struct Left  {};
struct Right {};
typedef bimap<
         multiset_of< tagged< int, Left  > >,
    unordered_set_of< tagged< int, Right > >
> bm_type;

bm_type bm;

//...

bm_type::iterator       iter       = bm.begin();
bm_type::left_iterator  left_iter  = bm.left.begin();
bm_type::right_iterator right_iter = bm.right.begin();

Table 1.3. Equivalence of expresions using user defined names

Untagged version

Tagged version

bm.left

bm.by<Left>()

bm.right

bm.by<Right>()

bm_type::left_map

bm::map_by<Left>::type

bm_type::right_value_type

bm::map_by<Right>::value_type

bm_type::left_iterator

bm::map_by<Left>::iterator

bm_type::right_const_iterator

bm::map_by<Right>::const_iterator

iter->left

iter->get<Left>()

iter->right

iter->get<Right>()

left_iter->first

left_iter->get<Left>()

left_iter->second

left_iter->get<Right>()

right_iter->first

right_iter->get<Right>()

right_iter->second

right_iter->get<Left>()

bm.project_left(iter)

bm.project<Left>(iter)

bm.project_right(iter)

bm.project<Right>(iter)



PrevUpHomeNext