560 lines
13 KiB
Plaintext
560 lines
13 KiB
Plaintext
[/
|
|
(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]
|