blob: f8fff6a08725069299e5fa93a2980018e6f07897 [file] [log] [blame]
[/
(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]