...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Front Page / Metafunctions / Concepts / Tag Dispatched Metafunction |
A Tag Dispatched Metafunction is a Metafunction that employs a tag dispatching technique in its implementation to build an infrastructure for easy overriding/extenstion of the metafunction's behavior.
Symbol | Legend |
---|---|
name | A placeholder token for the specific metafunction's name. |
tag-metafunction | A placeholder token for the tag metafunction's name. |
tag | A placeholder token for one of possible tag types returned by the tag metafunction. |
template< typename Tag > struct name_impl; template< typename X [, ...] > struct name : name_impl< typename tag-metafunction<X>::type > ::template apply<X [, ...]> { }; template< typename Tag > struct name_impl { template< typename X [, ...] > struct apply { // default implementation }; }; template<> struct name_impl<tag> { template< typename X [, ...] > struct apply { // tag-specific implementation }; };
The usual mechanism for overriding a metafunction's behavior is class template specialization — given a library-defined metafunction f, it's possible to write a specialization of f for a specific type user_type that would have the required semantics [4].
While this mechanism is always available, it's not always the most convenient one, especially if it is desirable to specialize a metafunction's behavior for a family of related types. A typical example of it is numbered forms of sequence classes in MPL itself (list0, ..., list50, et al.), and sequence classes in general.
A Tag Dispatched Metafunction is a concept name for an instance of the metafunction implementation infrastructure being employed by the library to make it easier for users and implementors to override the behavior of library's metafunctions operating on families of specific types.
The infrastructure is built on a variation of the technique commonly known as tag dispatching (hence the concept name), and involves three entities: a metafunction itself, an associated tag-producing tag metafunction, and the metafunction's implementation, in the form of a Metafunction Class template parametrized by a Tag type parameter. The metafunction redirects to its implementation class template by invoking its specialization on a tag type produced by the tag metafunction with the original metafunction's parameters.
[4] | Usually such user-defined specialization is still required to preserve the f's original invariants and complexity requirements. |
#include <boost/mpl/size.hpp> namespace user { struct bitset_tag; struct bitset0 { typedef bitset_tag tag; // ... }; template< typename B0 > struct bitset1 { typedef bitset_tag tag; // ... }; template< typename B0, ..., typename Bn > struct bitsetn { typedef bitset_tag tag; // ... }; } // namespace user namespace boost { namespace mpl { template<> struct size_impl<user::bitset_tag> { template< typename Bitset > struct apply { typedef typename Bitset::size type; }; }; }}