Like std::pair, but attempts to optimize away the space for either the first or second template parameter if the type is "empty". And instead of the members being accessible via the public data members first and second, they are accessible via member methods first() and second(). The compressed_pair handles reference types as well as other types thanks to the call_traits template. This is a good example to study if you're wanting to see how to take advantage of either call_traits or is_empty. To see an example of how compressed_pair is used see alloc_ptr.
Use of the single argument constructors will fail at compile time (ambiguous call) if first_type and second_type are the same type.
The swap specialization will call swap on each member if and only if its size has not been optimized away. The call to swap on each member will look both in std, and in the member's namespace for the appropriate swap specialization. Thus clients of compressed_pair need not put swap specializations into namespace std.
A good use of compressed_pair is in the implementation of a container that must store a function object. Function objects are typically zero-sized classes, but are also allowed to be ordinary function pointers. If the function object is a zero-sized class, then the container can optimize its space away by using it as a base class. But if the function object instantiates to a function pointer, it can not be used as a base class. By putting the function object into a compressed_pair, the container implementor need not worry whether it will instantiate to a class or function pointer.
MyContainer1 uses a zero-sized Compare object. On a 32 bit machine, the sizeof MyContainer1 will be 4 bytes as the space for Compare is optimized away by compressed_pair. But MyContainer2 instantiates Compare with an ordinary function pointer which can't be optimized away. Thus the sizeof MyContainer2 is 8 bytes.
#include <iostream> #include <functional> #include <ewl_utility> template <class T, class Compare> class MyContainer { public: explicit MyContainer(const Compare& c = Compare()) : data_(0, c) {} T* pointer() {return data_.first();} const T* pointer() const {return data_.first();} Compare& compare() {return data_.second();} const Compare& compare() const {return data_.second();} void swap(MyContainer& y) {data_.swap(y.data_);} private: Metrowerks::compressed_pair<T*, Compare> data_; }; int main() { typedef MyContainer<int, std::less<int>> MyContainer1; typedef MyContainer<int, bool (*)(int, int)> MyContainer2 std::cout << sizeof(MyContainer1) << '\n'; std::cout << sizeof(MyContainer2) << '\n'; }