More C++ Idioms/Boost mutant

< More C++ Idioms

Boost mutantEdit


Reverse a pair of plain old data (POD) types without physically reorganizing or copying the data items.

Also Known AsEdit


The need of this idiom is best motivated using the Boost.Bimap data structure. Boost.Bimap is a bidirectional maps library for C++. In bimap<X,Y>, values of types X and Y both can serve as keys. The implementation of such a data structure can be optimized using the boost mutant idiom.

Solution and Sample CodeEdit

Boost mutant idiom makes use of reinterpret_cast and depends heavily on assumption that the memory layouts of two different structures with identical data members (types and order) are interchangeable. Although the C++ standard does not guarantee this property, virtually all the compilers satisfy it. Moreover, the mutant idiom is standard if only POD types are used.[1] The following example shows how boost mutant idiom works.

template <class Pair>
struct Reverse
    typedef typename Pair::first_type  second_type;
    typedef typename Pair::second_type first_type;
    second_type second;
    first_type first;

template <class Pair>
Reverse<Pair> & mutate(Pair & p)
  return reinterpret_cast<Reverse<Pair> &>(p);

int main(void)
  std::pair<double, int> p(1.34, 5);

  std::cout << "p.first = " << p.first << ", p.second = "  << p.second << std::endl;
  std::cout << "mutate(p).first = " << mutate(p).first << ", mutate(p).second = "  << mutate(p).second << std::endl;

Given a std::pair<X,Y> object of POD data members only, the layout of the Reverse<std::pair<X,Y>> is identical to that of pair's on most compilers. The Reverse template reverses the names of the data members without physically reversing the data. A helper mutate function is used to easily construct a Reverse<Pair> reference, which can be considered as a view over the original pair object. The output of the above program confirms that the reverse view can be obtained without reorganizing data:

p.first = 1.34, p.second = 5

mutate(p).first = 5, mutate(p).second = 1.34

Known UsesEdit

Related IdiomsEdit