Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

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.


PrevUpHomeNext