| [/ |
| (C) Copyright Edward Diener 2011,2019 |
| 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_function_templates Introspecting function templates technique] |
| [#sectti_function_templates] |
| |
| Function templates, like functions, can be entities within a user-defined |
| type. Just as functions within a user-defined type can be member functions |
| or static member functions, function templates within a user-defined type |
| can be member function templates or static member function templates. |
| In this respect function templates are related to functions. Function templates |
| represent a family of possible functions. In this respect they are similar to |
| class templates, which represent a family of possible class types. |
| |
| The technique for introspecting class templates in the TTI library is taken |
| from the implementation of the technique in the Boost MPL library. In the case |
| of `BOOST_TTI_HAS_TEMPLATE` using the template type parameters form it directly |
| uses the Boost MPL library functionality while in the case of `BOOST_TTI_HAS_TEMPLATE` |
| using the specific form it replicates much of the technique in the Boost MPL library. |
| Either technique for introspecting class templates depends directly on the fact that in |
| C++ we can pass a template as a parameter to another template using what is called |
| a "template template" parameter type. |
| |
| One obvious thing about a template template parameter type is that it is a |
| class template. The fact that we can pass class templates as a template parameter but not |
| function templates as a template parameter is the major factor why there is no equivalent |
| method for introspecting a function template signature at compile time as there is for |
| introspecting class templates signature. |
| |
| [heading Introspection using an instantiated function template] |
| |
| Although there is no way to introspect for a function template signature in TTI, there is |
| an alternate way of introspecting a function template. It is possible to check whether some |
| particular [*instantiation] of a nested function template exists at compile-time without |
| generating a compiler error, as long as all the lower level indidual types in that instantiation |
| exist at the time introspection of a function template occurs. In plainer C++ terms we call the |
| instantiation of a function template "calling ( or invoking ) the function template". Although |
| checking whether some particular instantiation of a nested function template exists at compile-time |
| does not prove that the nested function template itself has a particular signature, since the |
| instantiation itself may fail even when the nested function template does exist, it provides |
| a viable way of introspecting function templates because the vast majority of function |
| templates are designed to accept any type(s) and avoid compile time failure. Also when we |
| introspect using a function template instantiation for a nested function template we are |
| replicating how function templates are actually used in C++. |
| |
| To see how this works in general in the TTI library I will give an example of a nested |
| function template in a user-defined type. |
| |
| 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; } |
| }; |
| |
| The code shows a member function template within a user-defined struct called `AType`. |
| Ideally what we would like to do is to be able to verify that the function template |
| signature of `template<class X,class Y,class Z> double AFuncTemplate(X,Y *,Z &)` |
| exists within the `AType` type, but we can not do that in TTI. If we were to call `AFuncTemplate` |
| from within some functionality within the `AType` type, we would substitute some arguments |
| for `X,Y *,Z &` and the C++ compiler would be able to figure out the types for X, Y, and Z |
| and create a function to be called. |
| |
| If we look at this in terms of compile time programming ( aka template metaprogramming ) |
| what we are really interested in is whether there is a function template called `AFuncTemplate` |
| within a type called `AType` which can be invoked with the X, Y, and Z types as some set |
| of types which are equivalent to calling `AFuncTemplate` with some set of arguments. Let's suppose |
| we want to call `AFuncTemplate` with an `int` value as the first argument, `long *` as the |
| second argument, and a `bool &` as the third argument. In TTI introspection terms for a function |
| template what we therefore are going to do is to check if we can instantiate the function |
| template as: |
| |
| double AFuncTemplate<int,long,bool>(int,long *,bool &) |
| |
| This is the form of a single possible instantiation of function template `AFuncTemplate`. When it is |
| subsequently explained how to use an instantiation of a function template to check if an inner function template |
| exists, this is what we mean. The instantiation itself does not exist when we introspect a function template |
| but all the parts of our instantiation signature are used in the process of introspection. |
| It should be realized that we could use any combination of valid types or values to create our |
| theoretical instantiation of a given function template, as long as those type and/or values produces |
| a valid callable function which does not contain compile time errors. |
| |
| The actual types and/or values we use in an instantiation of a function template we introspect |
| must be declared when we do the introspection. For built-in types this is always the case. |
| If we use instead, for whatever reason, a user-defined type in a given instantiation, that type |
| must be declared when we invoke the metafunction which does the introspection. |
| |
| Further areas of the documentation will explain in its place how we use an instantiation of |
| a function template to introspect respectively a member function template, a static member |
| function template, or any inner function template. The technique we use is very similar to |
| the way we introspect any nested entity, but instead of looking for a signature that declares |
| that nested entity, with function templates we look for a signature representing some |
| instantiation of the function template. |
| |
| [endsect] |