165 lines
7.2 KiB
Plaintext
165 lines
7.2 KiB
Plaintext
[/
|
|
(C) Copyright Edward Diener 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_detail_has_function_template Introspecting function template]
|
|
|
|
We can introspect a member function template or a static member function template
|
|
of a user-defined type using the TTI functionality we shall now explain.
|
|
|
|
A function template of a user-defined type can either be a member function
|
|
template or a static member function template. An example 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; }
|
|
template<class X,int Y> static int AFuncTemplate(X x)
|
|
{ ...some code using x; return Y; }
|
|
};
|
|
|
|
A function template `AFuncTemplate` is a member function template of the `AType`
|
|
user-defined type and a different function template also called `AFuncTemplate`
|
|
is a static member function template of the `AType` user-defined type.
|
|
|
|
In order to introspect either function template we use some theoretical valid
|
|
instantiations of `AFuncTemplate`. An instantiation of a function template was
|
|
previously explained in the topic [link sectti_function_templates "Introspecting function templates technique"].
|
|
|
|
For the purposes of illustration the instantiation we will use is:
|
|
|
|
double AFuncTemplate<char,bool,int>(char,bool *,int &)
|
|
|
|
What we have now which the TTI will need in order to introspect the function
|
|
template `template<class X,class Y,class Z> double AFuncTemplate(X,Y *,Z &)`
|
|
within the `AType` struct is:
|
|
|
|
* The name of `AFuncTemplate`
|
|
* The template parameters of `char,bool,int`
|
|
* The enclosing type of `AType`
|
|
* The return type of `double`
|
|
* The function parameters of `char,bool *,int &`
|
|
|
|
[heading Generating the metafunction]
|
|
|
|
As with all TTI functionality for introspecting entities within a user-defined
|
|
type introspecting a function template is a two step process. The first
|
|
process is using a macro to generate a metafunction. The macro for
|
|
function templates is [macroref BOOST_TTI_HAS_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_FUNCTION_TEMPLATE(AFuncTemplate,char,bool,int)
|
|
|
|
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_FUNCTION_TEMPLATE(AFuncTemplate,(3,(char,bool,int)))
|
|
|
|
The macro generates a metafunction based on the pattern of
|
|
"has_function_template_'name_of_inner_function_template'",
|
|
which in our example case would be `has_function_template_AFuncTemplate`.
|
|
|
|
[heading Invoking the metafunction]
|
|
|
|
To use this macro to test whether our 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 function template exists,
|
|
or `false` otherwise. We use each of our needed types as separate parameters, with the
|
|
function parameters being enclosed in an MPL forward sequence. We would have:
|
|
|
|
has_function_template_AFuncTemplate<AType,double,boost::mpl::vector<char,bool *,int &> >::value
|
|
|
|
[heading Introspecting the other function template]
|
|
|
|
If we chose to try to introspect the second `AFuncTemplate` within `AType` we might
|
|
choose an instantiation of:
|
|
|
|
int AFuncTemplate<long,7435>(long)
|
|
|
|
Our generation of the metafunction would then be:
|
|
|
|
BOOST_TTI_HAS_FUNCTION_TEMPLATE(AFuncTemplate,long,7435)
|
|
|
|
or
|
|
|
|
BOOST_TTI_HAS_FUNCTION_TEMPLATE(AFuncTemplate,(2,(long,7435)))
|
|
|
|
and our invocation of the metafunction would now be:
|
|
|
|
has_function_template_AFuncTemplate<AType,int,boost::mpl::vector<long> >::value
|
|
|
|
[heading Other considerations]
|
|
|
|
In our two examples above we could not introspect both function templates
|
|
in the same namespace using the BOOST_TTI_HAS_FUNCTION_TEMPLATE macro as we would
|
|
be generating two metafunctions with the same name, which would be
|
|
`has_function_template_AFuncTemplate`, thus violating the One Definition Rule.
|
|
The solution to this is the use of the complex macro form.
|
|
|
|
The macro for generating the metafunction for introspecting 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_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 first example we could have
|
|
|
|
BOOST_TTI_TRAIT_HAS_FUNCTION_TEMPLATE(FirstMetafunction,char,bool,int)
|
|
|
|
or for the non-variadic macro form
|
|
|
|
BOOST_TTI_TRAIT_HAS_FUNCTION_TEMPLATE(FirstMetafunction,(3,(char,bool,int)))
|
|
|
|
which generates a metafunction whose name would be `FirstMetafunction`.
|
|
|
|
For our second example we could have
|
|
|
|
BOOST_TTI_TRAIT_HAS_FUNCTION_TEMPLATE(SecondMetafunction,AFuncTemplate,long,7435)
|
|
|
|
or for the non-variadic macro form
|
|
|
|
BOOST_TTI_TRAIT_HAS_FUNCTION_TEMPLATE(SecondMetafunction,AFuncTemplate,(2,(long,7435)))
|
|
|
|
which generates a metafunction whose name would be `SecondMetafunction`.
|
|
|
|
In all other respects the resulting metafunctions 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 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_FUNCTION_TEMPLATE_GEN` as in
|
|
|
|
BOOST_TTI_HAS_FUNCTION_TEMPLATE_GEN(AFuncTemplate)
|
|
|
|
which would generate the name `has_function_template_AFuncTemplate`.
|
|
|
|
When invoking the appropriate metafunction a fourth
|
|
template argument may optionally be given which holds a Boost FunctionTypes tag
|
|
type. This optional template argument is of much less use for
|
|
function templates than for non-static member function templates since static
|
|
member function templates, like static member functions, can not have
|
|
cv-qualifications. which a number of Boost FunctionTypes tags provide.
|
|
Nonetheless this optional Boost FunctionTypes tag is available for
|
|
end-user use and may come in handy in certain rare cases, as when some calling
|
|
convention qualification for the function template needs to be
|
|
specified. If you do use a Boost FunctionTypes tag type for cv-qualification,
|
|
such as `boost::function_types::const_qualified` to look for a function template
|
|
it will be applied when introspecting for the member function template side of
|
|
the match, but will ensure that introspecting for the static member function
|
|
template side of the match will always fail. In either case no compiler error
|
|
will be generated.
|
|
|
|
[endsect]
|