Type induction in function templates

As a simple but very useful example, consider the following:

This actually figures out the size of an array as a compile-time constant value, without using any sizeof( ) operations! Thus you can have a much more succinct way to calculate the size of an array at compile time:

Of course, just making a variable of a built-in type a const does not guarantee it?s actually a compile-time constant, but if it?s used to define the size of an array (as it is in the last line of main( )), then it must be a compile-time constant.

Taking the address of a generated function template
There are a number of situations where you need to take the address of a function. For example, you may have a function that takes an argument of a pointer to another function. Of course it?s possible that this other function might be generated from a template function so you need some way to take that kind of address :

This example demonstrates a number of different issues. First, even though you?re using templates, the signatures must match ? the function h( ) takes a pointer to a function that takes an int* and returns void, and that?s what the template f produces. Second, the function that wants the function pointer as an argument can itself be a template, as in the case of the template g.

In main( ) you can see that type induction works here, too. The first call to h( ) explicitly gives the template argument for f, but since h( ) says that it will only take the address of a function that takes an int*, that part can be induced by the compiler. With g( ) the situation is even more interesting because there are two templates involved. The compiler cannot induce the type with nothing to go on, but if either f or g is given int, then the rest can be induced.

Member function templates

It?s also possible to make apply( ) a member function template of the class. That is, a separate template definition from the class? template, and yet a member of the class. This may produce a cleaner syntax:

The definition of the apply( ) functions turn out to be cleaner, as well, because they are members of the container. To accomplish this, a new container is inherited from one of the existing STL sequence containers and the member function templates are added to the new type. However, for maximum flexibility we?d like to be able to use any of the STL sequence containers, and for this to work a template-template must be used, to tell the compiler that a template argument is actually a template, itself, and can thus take a type argument and be instantiated. Here is what it looks like after bringing the apply( ) functions into the new type as member functions:

Because they are members, the apply( ) functions don?t need as many arguments, and the iterator class doesn?t need to be qualified. Also, begin( ) and end( ) are now member functions of the new type and so look cleaner as well. However, the basic code is still the same.
You can see how the function calls are also simpler for the client programmer:

Conceptually, it reads more sensibly to say that you?re calling apply( ) for the dogs container.

Share
Tweet
Share
Pin