| Home | Libraries | People | FAQ | More

### Using the has_template_(xxx) metafunction

##### Generating the metafunction

You generate the metafunction by invoking the macro with the name of an inner class template:

    // `template type parameters` form

    BOOST_TTI_HAS_TEMPLATE(AClassTemplate,BOOST_PP_NIL) // non-variadic macro
    BOOST_TTI_HAS_TEMPLATE(AClassTemplate)              // variadic macro

    // `specific parameters` form

    BOOST_TTI_HAS_TEMPLATE(AClassTemplate,(2,(class,int))) // non-variadic macro
    BOOST_TTI_HAS_TEMPLATE(AClassTemplate,class,int)       // variadic macro

generates a metafunction called 'has_template_AClassTemplate' in the current scope.

If you want to introspect the same class template name using both the `template type parameters` form and the `specific parameters` form you will have the problem that you will be generating a metafunction of the same name and violating the C++ ODR rule. In this particular case you can use the alternate BOOST_TTI_TRAIT_HAS_TEMPLATE macro to name the particular metafunction which will be generated.

##### Invoking the metafunction

You invoke the metafunction by instantiating the template with an enclosing type to introspect. A return value called 'value' is a compile time bool constant.

    has_template_AType<Enclosing_Type>::value

##### Examples

First we generate metafunctions for various inner class template names:

    #include <boost/tti/has_template.hpp>

    // Using variadic macro, `template type parameters`

    BOOST_TTI_HAS_TEMPLATE(Template1)
    BOOST_TTI_HAS_TEMPLATE(Template2)
    BOOST_TTI_HAS_TEMPLATE(Template3)
    BOOST_TTI_HAS_TEMPLATE(Template4)
    BOOST_TTI_HAS_TEMPLATE(Template5)

    // or using non-variadic macro, `template type parameters`

    BOOST_TTI_HAS_TEMPLATE(Template1,BOOST_PP_NIL)
    BOOST_TTI_HAS_TEMPLATE(Template2,BOOST_PP_NIL)
    BOOST_TTI_HAS_TEMPLATE(Template3,BOOST_PP_NIL)
    BOOST_TTI_HAS_TEMPLATE(Template4,BOOST_PP_NIL)
    BOOST_TTI_HAS_TEMPLATE(Template5,BOOST_PP_NIL)

    // Using variadic macro, `specific parameters`

    BOOST_TTI_HAS_TEMPLATE(Template6,class,int)
    BOOST_TTI_HAS_TEMPLATE(Template7,typename,template<class,class> struct,long)
    BOOST_TTI_HAS_TEMPLATE(Template8,double,typename)
    BOOST_TTI_HAS_TEMPLATE(Template9,typename,class,typename,class,typename,short)

    // or using non-variadic macro, `specific parameters`

    BOOST_TTI_HAS_TEMPLATE(Template6,(2,(class,int)))
    BOOST_TTI_HAS_TEMPLATE(Template7,(4,(typename,template<class,class> struct,long)))
    BOOST_TTI_HAS_TEMPLATE(Template8,(2,(double,typename)))
    BOOST_TTI_HAS_TEMPLATE(Template9,(6,(typename,class,typename,class,typename,short)))

Next let us create some user-defined types we want to introspect.

    struct Top
      {
      template <class X> struct Template1 { };
      template <typename A,typename B,typename C> class Template2 { };
      template <typename A,typename B,typename C,int D> class Template3 { };
      };
    struct Top2
      {
      template <typename A,typename B,typename C,class D> class Template3 { };
      template <class X,typename Y> struct Template4 { };
      template <typename A,class B,typename C,class D,typename E> class Template5 { };
      };
    struct Top3
      {
      template <class X,int Y> struct Template6 { };
      template <typename A,template<class,class> struct B,long C> class Template7 { };
      };
    struct Top4
      {
      template <double X,typename Y> struct Template8 { };
      template <typename A,class B,typename C,class D,typename E,short F> class Template9 { };
      };

Finally we invoke our metafunction and return our value. This all happens at compile time, and can be used by programmers doing compile time template metaprogramming.

    has_template_Template1<Top>::value; // true
    has_template_Template1<Top2>::value; // false

    has_template_Template2<Top>::value; // true
    has_template_Template2<Top2>::value; // false

    has_template_Template3<Top>::value; // false, not all typename/class template parameters
    has_template_Template3<Top2>::value; // true

    has_template_Template4<Top>::value; // false
    has_template_Template4<Top2>::value; // true

    has_template_Template5<Top>::value; // false
    has_template_Template5<Top2>::value; // true

    has_template_Template6<Top3>::value; // true
    has_template_Template6<Top4>::value; // false

    has_template_Template7<Top3>::value; // true
    has_template_Template7<Top4>::value; // false

    has_template_Template8<Top3>::value; // false
    has_template_Template8<Top4>::value; // true

    has_template_Template9<Top3>::value; // false
    has_template_Template9<Top4>::value; // true

##### Metafunction re-use

The macro encodes the name of the inner class template for which we are searching, the fact that we are introspecting for a class template within an enclosing type, and optionally the template parameters for that class template.

Once we create our metafunction for introspecting an inner class template by name, we can reuse the metafunction for introspecting any enclosing type, having any inner class template, for that name.

However we need to understand that we are restricted in our reuse of the metafunction by whether we originally use the template type parameters form or the specific form. In either case we are always introspecting an inner class template which matches that form. In the case of the template type parameters form, any inner class template for which we are introspecting must have all template type parameters, as well as the correct name. In the case of the specific parameters form, any inner class template for which we are introspecting must have template parameters which match the specific template parameters passed to the macro, as well as the correct name.