[/ 
  (C) Copyright Edward Diener 2011,2012,2020
  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE_1_0.txt or copy at
  http://www.boost.org/LICENSE_1_0.txt).
]

[section:tti_usingMM An example using the macro metafunctions]
[#sectti_usingMM]

Using the macro metafunctions can be illustrated by first creating some hypothetical
user-defined type with corresponding nested types and other inner elements.
With this type we can illustrate the use of the macro metafunctions. This is 
just meant to serve as a model for what a type T might entail from within 
a class or function template where 'T' is a type passed to the template.

 // An enclosing type, this could also be a class or a union

 struct AType
   {
   
   // Type
   
   typedef int AnIntType; // as a typedef
   
   // Class/Struct
   
   struct BType // as a nested struct
     {
     struct CType
       {
       };
     };
     
   class AClass // as a nested class
     {
     };
     
   // Enumeration
   
   enum EColor // as a nested enumeration
     {
     Red,
     Blue,
     Green
     };
     
   // Union
   
   union AUnion // as a nested union
     {
     int i;
     long l;
     };
   
   // Class Template
   
   template <class> struct AMemberTemplate { };
   template <class,class,class> struct AnotherMemberTemplate { };
   template <class,class,int,class,template <class> class,class,long> struct ManyParameters { };
   template <class,class,int,short,class,template <class,int> class,class> struct MoreParameters { };
   
   // Data
   
   BType IntBT;
   
   // Function
   
   int IntFunction(short) { return 0; }
   
   // Const Function
   
   long AnotherFunction(bool,double) const { return 0L; }
   
   // Function Template
   
   template<class X, class Y, int Z> int MyFunctionTemplate(X *, Y &) { return Z; }
   
   // Const Function Template
   
   template<class X, int Y, class Z> int AnotherFunctionTemplate(X &, Z **) const { return Y; }
   
   // Static Data
   
   static short DSMember;
   
   // Static Function
   
   static int SIntFunction(long,double) { return 2; }
   
   // Static Function Template
   
   template<class A, class B> static long SFunctionTemplate(long &,A **,B,float) { return 20L; }
   
   };
  
I will be using the type above just to illustrate the sort of 
metaprogramming questions we can ask of some type T which is passed 
to the template programmer in a class template. Here is what the 
class template might look like:

 #include <boost/tti/tti.hpp>

 template<class T>
 struct OurTemplateClass
   {
   
   // compile-time template code regarding T
   
   };

Now let us create and invoke the macro metafunctions for each of our inner element types, 
to see if type T above corresponds to our hypothetical type above. Imagine this being 
within 'OurTemplateClass' above. In the examples below the same macro is invoked just once 
to avoid ODR violations. Also in these examples we are showing results which return
the compile time boolean result of 'true' to illustrate how our macro metafunctions work.
We could just as well create examples which return the compile time boolean result of
'false' if we introspect for constructs that do not exist in our hypothetical type of T.
We can validly return 'true' or 'false' without generating compiler errors as long as the
types using in our macro metafunction invocations exist at the time we invoke the
metafunction.
 
[heading Type]

C++ named types can be typedefs or type aliases, class, structs, unions, or enumerations

Does T have a nested type called 'AnIntType' ?

 BOOST_TTI_HAS_TYPE(AnIntType)
 
 has_type_AnIntType
   <
   T
   >
   
Does T have a nested type called 'BType' ?

 BOOST_TTI_HAS_TYPE(BType)
  
 has_type_BType
   <
   T
   >
   
Does T have a nested type called 'AClass' ?

 BOOST_TTI_HAS_TYPE(AClass)
  
 has_type_ACLass
   <
   T
   >
   
Does T have a nested type called 'EColor' ?

 BOOST_TTI_HAS_TYPE(EColor)
  
 has_type_EColor
   <
   T
   >
   
Does T have a nested type called 'AUnion' ?

 BOOST_TTI_HAS_TYPE(AUnion)
  
 has_type_AUnion
   <
   T
   >
   
[heading Type checking the typedef using an MPL lambda expression]

Does T have a nested typedef called 'AnIntType' whose type is an 'int' ?

 #include <boost/mpl/placeholders.hpp
 #include <boost/type_traits/is_same.hpp
 using namespace boost::mpl::placeholders;
 
 has_type_AnIntType
   <
   T,
   boost::is_same<_1,int>
   >

[heading Class/Struct]

Does T have a nested class called 'AClass' ?

 BOOST_TTI_HAS_CLASS(AClass)
  
 has_class_AClass
   <
   T
   >
   
Does T have a nested struct called 'BType' ?

 BOOST_TTI_HAS_CLASS(BType)
  
 has_class_BType
   <
   T
   >
   
You can also use an MPL lambda expression with a class/struct just as you can with a general type.
   
[heading Enumeration]

Does T have a nested enumeration called 'EColor' ?

 BOOST_TTI_HAS_ENUM(EColor)
  
 has_enum_EColor
   <
   T
   >
   
You can also use an MPL lambda expression with an enumeration just as you can with a general type.
   
[heading Union]

Does T have a nested union called 'AUnion' ?

 BOOST_TTI_HAS_UNION(AUnion)
  
 has_union_AUnion
   <
   T
   >
   
You can also use an MPL lambda expression with a union just as you can with a general type.
   
[heading Template]

Does T have a nested class template called 'AMemberTemplate' whose template 
parameters are all types ('class' or 'typename') ?

 BOOST_TTI_HAS_TEMPLATE(AMemberTemplate,BOOST_PP_NIL)
 
 has_template_AMemberTemplate
   <
   T
   >

[heading Template using variadic macros]

Does T have a nested class template called 'AMemberTemplate' whose template 
parameters are all types ('class' or 'typename') ?

 BOOST_TTI_HAS_TEMPLATE(AnotherMemberTemplate)
 
 has_template_AnotherMemberTemplate
   <
   T
   >

[heading Template with params]

Does T have a nested class template called 'MoreParameters' whose template 
parameters are specified exactly ?

 BOOST_TTI_HAS_TEMPLATE(MoreParameters,(8,(class,class,int,short,class,template <class,int> class,class)))
 
 has_template_MoreParameters
   <
   T
   >

[heading Template with params using variadic macros]

Does T have a nested class template called 'ManyParameters' whose template 
parameters are specified exactly ?

 BOOST_TTI_HAS_TEMPLATE(ManyParameters,class,class,int,class,template <class> class,class,long)
 
 has_template_ManyParameters
   <
   T
   >

[heading Member data]

Does T have a member data called 'IntBT' whose type is 'AType::BType' ?

 BOOST_TTI_HAS_MEMBER_DATA(IntBT)
 
 has_member_data_IntBT
   <
   T,
   AType::BType
   >

[heading Member data with composite type]

Does T have a member data called 'IntBT' whose type is 'AType::BType' ?

 BOOST_TTI_HAS_MEMBER_DATA(IntBT)
 
 has_member_data_IntBT
   <
   AType::BType T::*
   >

[heading Member function with individual types]

Does T have a member function called 'IntFunction' whose type is 
'int (short)' ?

 BOOST_TTI_HAS_MEMBER_FUNCTION(IntFunction)
 
 has_member_function_IntFunction
   <
   T,
   int,
   boost::mpl::vector<short>
   >

[heading Member function with composite type]

Does T have a member function called 'IntFunction' whose type is 
'int (short)' ?

 BOOST_TTI_HAS_MEMBER_FUNCTION(IntFunction)
 
 has_member_function_IntFunction
   <
   int (T::*) (short)
   >

[heading Const member function with individual types]

Does T have a member function called 'AnotherFunction' whose type is 
'long (bool,double) const' ?

 BOOST_TTI_HAS_MEMBER_FUNCTION(AnotherFunction)
 
 has_member_function_AnotherFunction
   <
   T,
   long,
   boost::mpl::vector<bool,double>,
   boost::function_types::const_qualified
   >

[heading Const member function with composite type]

Does T have a member function called 'AnotherFunction' whose type is 
'long (bool,double) const' ?

 BOOST_TTI_HAS_MEMBER_FUNCTION(AnotherFunction)
 
 has_member_function_AnotherFunction
   <
   long (T::*) (bool,double) const
   >

[heading Member function template with individual types]

Does T have a member function template called 'MyFunctionTemplate' woth an instantiated
signature of 'int MyFunctionTemplate<short,float,579>(short *,float &)' ?

 BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE(MyFunctionTemplate,short,float,579)
 
 has_member_function_MyFunctionTemplate
   <
   T,
   int,
   boost::mpl::vector<short *,float &>
   >

[heading Member function template with composite type]

Does T have a member function template called 'MyFunctionTemplate' woth an instantiated
signature of 'int MyFunctionTemplate<int,long,183>(int *,long &)' ?

 BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE(MyFunctionTemplate,int,long,183)
 
 has_member_function_template_MyFunctionTemplate
   <
   int (T::*)(int *,long &)
   >

[heading Const member function template with individual types]

Does T have a member function template called 'AnotherFunctionTemplate' with an instantiated
signature of 'int AnotherFunctionTemplate<bool,8359,double>(bool &,double **) const' ?

 BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE(AnotherFunctionTemplate,bool,8359,double)
 
 has_member_function_AnotherFunctionTemplate
   <
   T,
   int,
   boost::mpl::vector<bool &,double **>,
   boost::function_types::const_qualified
   >

[heading Const member function template with composite type]

Does T have a member function template called 'AnotherFunctionTemplate' with an instantiated
signature of 'int AnotherFunctionTemplate<bool,8359,double>(bool &,double **) const' ?

 BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE(AnotherFunctionTemplate,bool,8359,double)
 
 has_member_function_template_MyFunctionTemplate
   <
   int (T::*)(bool &,double **) const
   >

[heading Static member data]

Does T have a static member data called 'DSMember' whose type is 'short' ?

 BOOST_TTI_HAS_STATIC_MEMBER_DATA(DSMember)
 
 has_static_member_data_DSMember
   <
   T,
   short
   >

[heading Static member function with individual types]

Does T have a static member function called 'SIntFunction' whose type 
is 'int (long,double)' ?

 BOOST_TTI_HAS_STATIC_MEMBER_FUNCTION(SIntFunction)
 
 has_static_member_function_SIntFunction
   <
   T,
   int,
   boost::mpl::vector<long,double>
   >

[heading Static member function with composite type]

Does T have a static member function called 'SIntFunction' whose type 
is 'int (long,double)' ?

 BOOST_TTI_HAS_STATIC_MEMBER_FUNCTION(SIntFunction)
 
 has_static_member_function_SIntFunction
   <
   T,
   int (long,double)
   >

[heading Static member function template with individual types]

Does T have a static member function template called 'SFunctionTemplate' with an
instantiated signature of 'long SFunctionTemplate<char,unsigned>(long &,char **,unsigned,float)' ?

 BOOST_TTI_HAS_STATIC_MEMBER_FUNCTION_TEMPLATE(SFunctionTemplate,char,unsigned)
 
 has_static_member_function_template_SFunctionTemplate
   <
   T,
   long,
   boost::mpl::vector<long &,char **,unsigned,float>
   >

[heading Static member function template with composite type]

Does T have a static member function template called 'SFunctionTemplate' with an
instantiated signature of 'long SFunctionTemplate<bool,int>(long &,bool **,int,float)' ?

 BOOST_TTI_HAS_STATIC_MEMBER_FUNCTION_TEMPLATE(SFunctionTemplate,bool,int)
 
 has_static_member_function_template_SFunctionTemplate
   <
   T,
   long (long &,bool **,int,float)
   >

[heading Data]

Does T have a member data or static member data called 'DSMember' whose type is 'short' ?

 BOOST_TTI_HAS_DATA(DSMember)
 
 has_static_member_data_DSMember
   <
   T,
   short
   >

[heading Function]

Does T have a member function or a static member function called 'IntFunction' whose type is 
'int (short)' ?

 BOOST_TTI_HAS_FUNCTION(IntFunction)
 
 has_function_IntFunction
   <
   T,
   int,
   boost::mpl::vector<short>
   >

[heading Function Template]

Does T have a member function template or a static member function template called 'MyFunctionTemplate'
with an instantiated signature of 'int MyFunctionTemplate<bool,short,3487>(bool *,short &)' ?

 BOOST_TTI_HAS_FUNCTION_TEMPLATE(MyFunctionTemplate,bool,short,3487)
 
 has_function_template_MyFunctionTemplate
   <
   T,
   int,
   boost::mpl::vector<bool *,short &>
   >

[heading Member type]

Create a nested type T::BType::CType without creating a compiler error
if T does not have the nested type BType::CType ?

 BOOST_TTI_MEMBER_TYPE(BType)
 BOOST_TTI_MEMBER_TYPE(CType)
 
 typename
 member_type_CType
   <
   typename
   member_type_BType
     <
     T
     >::type
   >::type
 
[heading Member type existence]

Does a nested type T::BType::CType, created without creating a compiler error
if T does not have the nested type BType::CType, actually exist ?

 BOOST_TTI_MEMBER_TYPE(BType)
 BOOST_TTI_MEMBER_TYPE(CType)
 
 typedef typename
 member_type_CType
   <
   typename
   member_type_BType
     <
     T
     >::type
   >::type
 AType;
 
 boost::tti::valid_member_type
   <
   AType
   >
 
[endsect]
