5.10. Sequence DerivationTypically, the unnumbered form of any sequence is derived from the corresponding numbered form, or else shares with it a common base class that provides the sequence's implementation. For example, mpl::vector might be defined this way: namespace boost { namespace mpl { struct void_; // "no argument" marker // primary template declaration template <class T0 = void_, class T1 = void_, etc....> struct vector; // specializations template<> struct vector<> : vector0<> {}; template<class T0> struct vector<T0> : vector1<T0> {}; template<class T0, class T1> struct vector<T0,T1> : vector2<T0,T1> {}; template<class T0, class T1, class T2> struct vector<T0,T1,T2> : vector3<T0,T1,T2> {}; etc. }} The integral sequence wrappers are similarly derived from equivalent underlying type sequences. All of the built-in MPL sequences are designed so that nearly any subclass functions as an equivalent type sequence. Derivation is a powerful way to provide a new interface, or just a new name, to an existing family of sequences. For example, the Boost Python library provides the following type sequence:
namespace boost { namespace python {
template <class T0=mpl::void_, ... class T4=mpl::void_>
struct bases : mpl::vector<T0, T1, T2, T3, T4> {};
}}
You can use the same technique to create a plain class that is an MPL type sequence: struct signed_integers : mpl::vector<signed char, short, int, long> {}; On some compilers, using signed_integers instead of the underlying vector can dramatically improve metaprogram efficiency. See Appendix C for more details. ![]() |