Section 5.10.  Sequence Derivation
Team LiB
Previous Section Next Section

5.10. Sequence Derivation

Typically, 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.

    Team LiB
    Previous Section Next Section