...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
We can introspect a member function template of a user-defined type using the TTI functionality we shall now explain.
A member function template is a function template that is a non-static memmber of a user-defined type. An example of a member function template would be:
struct AType { template<class X,class Y,class Z> double AFuncTemplate(X x,Y * y,Z & z) { ...some code using x,y,z; return 0.0; } };
In order to introspect the function template we use some theoretical valid
instantiation of the member function template AFuncTemplate
.
An instantiation of a function template was previously explained in the topic
"Introspecting function templates
technique".
For the purposes of illustration the instantiation we will use is:
double AFuncTemplate<int,long,bool>(int,long *,bool &)
What we have now which the TTI will need in order to introspect the member
function template template<class X,class Y,class Z>
double AFuncTemplate(X,Y *,Z
&)
within the AType
struct is:
AFuncTemplate
int,long,bool
AType
double
int,long *,bool &
As with all TTI functionality for introspecting entities within a user-defined
type introspecting a member function template is a two step process. The first
process is using a macro to generate a metafunction. The macro for member function
templates is BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE
.
This macro takes the name of the member function template and the instantiated
template parameters, the first two items in our list above:
BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE(AFuncTemplate,int,long,bool)
An alternative form for compilers which do not support variadic macros, and which will also work with compilers which do support variadic macros, is to specify the template parameters of the instantiation as a single macro argument using a Boost PP array:
BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE(AFuncTemplate,(3,(int,long,bool)))
The macro generates a metafunction based on the pattern of "has_member_function_template_'name_of_inner_member_function_template'",
which in our example case would be has_member_function_template_AFuncTemplate
.
To use this macro to test whether our member function template exists the metafunction
the macro creates is invoked with the enclosing type, the instantiated return
type, and the instantiated function parameters, with the resulting value
being a compile time boolean constant
which is true
if the member function
template exists, or false
otherwise.
There are two ways to do this. We can either use each of our needed types as
separate parameters, with the function parameters being enclosed in an MPL
forward sequence, or we can compose our needed type in the form of a pointer
to member function type. In the first case we would have:
has_member_function_template_AFuncTemplate<AType,double,boost::mpl::vector<int,long *,bool &> >::value
and in the second case we would have:
has_member_function_template_AFuncTemplate<double (AType::*) (int,long *,bool &)>::value
Both invocations are equivalent in functionality.
The macro for generating the metafunction for introspecting member function templates also has, like other macros in the TTI library, a complex macro form where the end-user can directly specify the name of the metafunction to be generated. The corresponding macro is BOOST_TTI_TRAIT_HAS_MEMBER_FUNCTION_TEMPLATE, where the first parameter is the name of the metafunction to be generated, the second parameter is the member function template name, and the remaining parameters are the instantiated template parameters. For our example we could have
BOOST_TTI_TRAIT_HAS_MEMBER_FUNCTION_TEMPLATE(AMetafunctionName,AFuncTemplate,int,long,bool)
or for the non-variadic macro form
BOOST_TTI_TRAIT_HAS_MEMBER_FUNCTION_TEMPLATE(AMetafunctionName,AFuncTemplate,(3,(int,long,bool)))
which generates a metafunction whose name would be AMetafunctionName
.
In all other respects the resulting metafunction generated works exactly the same as when using the simpler macro form previously illustrated.
If you do use the simple macro form, which generates the metafunction name
from the name of the function template you are introspecting, you can use a
corresponding macro, taking the name of the member function template as a single
parameter, to create the appropriate metafunction name if you do not want to
remember the pattern for generating the metafunction name. This macro name
is BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE_GEN
as in
BOOST_TTI_HAS_MEMBER_FUNCTION_TEMPLATE_GEN(AFuncTemplate)
which would generate the name has_member_function_template_AFuncTemplate
.
When invoking the appropriate metafunction using the long form of an enclosing type, instantiated return type, and instantiated function parameters, a fourth template argument may optionally be given which holds a Boost FunctionTypes tag type to specify cv-qualification. This means you can add 'const', 'volatile', or both by specifying an appropriate tag type. An alternate to using the tag type is to specify the enclosing type as 'const', 'volatile', or both. As an example if you specify the tag type as 'boost::function_types::const_qualified' or if you specify the enclosing type as 'const YourEnclosingType', the member function template which you are introspecting must be a const function template to match correctly.
When invoking the metafunction using the shorter form of a pointer to member
function you can simply add a possible cv-qualification, such as const
, to the end of the pointer to member function
syntax.