| [/ |
| (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] |