...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
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.
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
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
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.