I know I’m repeating this everytime I write a new article, but it’s one of the key points to make template metaprogramming feasible, which means: **TMP is just a functional language**. A language with a “*Aghhhh, my eyes, please!!! Aaahhhhhg!!!*” syntax, but still a functional language.

To start a C++ metaprogramming library the right way, we’d better have a clear idea of what a metafunction is, and how our library represents and manages a metafunction.

## Functions

What’s a metafunction? Forget that. Enter in our Haskell metaphor first. **What’s a function?** From Wikipedia:

“[…] a function is a relation between a set of inputs and a set of permissible outputs with the property that each input is related to exactly one output.”

I hope you noticed that’s the mathematical definition of function, instead of a *programming-related* one. In general, I think calling programming entities *functions* is not a good idea. They have more to do with old subroutines than with math functions: Most of our code depends on side effects, generates side effects, or depends on reading and changing an external state in some way.

This is C++, but not the C++ most of us usually play with. This is a functional language: There are no side effects, there’s no external state. A function only takes an input, does some transformations on it, producing an output. Functions are mathematical functions, not some kind of prettified subroutines.

### Metafunctions

*“Something that takes an input, does something with it, producing a result”*

1 2 3 4 5 | template<typename T> struct add_const { using type = const T; }; |

This is a struct template parametrized with a type parameter `T`

. Whatever type you instance the template with, the instance struct has a public member type called `type`

equivalent to `const T`

.

For example: If you instance the template with `int`

as parameter:

1 | using a = add_const<int> |

The member type `type`

will be an alias of `const int`

:

1 | using b = add_const<int>::type; //b is const int |

Something that takes an input, `T`

, does something with it (add `const`

), returning and output `type`

.

A template is just a way to represent a function operating on C++ types. That’s what we call **metafunction**. A function operating on C++ types. Since a type cannot be modified, metafunctions are pure functions, which have no side effects.

The functional language metaphor has much more sense now, right?

## Metafunctions in our tiny metaprogramming library

We are playing with the C++ type system, using types or type generators (templates) as elements of our abstract metaprogramming type system.

We will have functions, values, “arrays”, etc. But these are really sets of C++ types.

Since C++ lacks type categories (I’m waiting for the Concepts proposal) there’s no direct way to arrange C++ types into different groups, and use those groups to simulate a high-order type system for our metaprogramming library. *Take a look at Boost.Hana for an approximation of type categories for a metaprogramming library, based on tag dispatching*.

Instead of building a complex category system like Hana (I’m not a good mathematician, nor an specialist on category theory :) ), my library will be based on some conventions and rules.

#### Return value of metafunctions

Using a template as a function operating on types, as a metafunction, is not a new concept. Take a look at `:`

1 | using ptr = std::decay<int[3]>::type; |

The templates defined there, called type traits, provide information and transformations of given types. For example, `std::decay`

simulates the decay applied to a type when a parameter is passed by value to a function.

To be compatible with the Standard Library, in my Tiny Metaprogramming Library I**‘m assuming that any type with a type public member type is a metafunction**.

Following that convention, a simple template alias can be a way to get rid of the `typename ::type`

construction, accessing directly to the return value of a metafunction:

1 2 3 4 | template<typename F> alias eval = typename F::type; alias myint = eval<std::remove_reference<int&>>; |

Of course this only works for simple expressions. Follow this series to see how this simple but powerful tool evolves.

## Parameters of metafunctions

A C++ template can take many kinds of parameters: Types, pointers, values, etc. But let’s keep it simple and **only allow type parameters**. Why? Because that simplifies a lot our metafunctions.

In fact, a simple variadic template-template parameter like the following represents any function our library can deal with:

1 | template<typename... ARGS> class F |

*Using this little jewel, imagine the next step of the eval tool above.*

But you may think: *“Manu, I need value parameters too. And template-template parameters”*. Don’t worry, we can simulate this using type parameters. Stay tuned for the next post!

## Summary

We’ve just learned what does “TMP is a functional language” means. We also learned a way to represent functions operating on C++ types, metafunctions, and two simple conventions for our tiny metaprogramming library:

– **Any type with a type public member type is considered a metafunction. That member contains the result of the function**.

–

**Our metafunctions, represented via templates, can take type parameters only**.

In the next post we will see how to use boxing to simulate value parameters and template-template parameters for our metafunctions.

Related Posts

Pingback: A Tiny Metaprogramming Library: Boxing - biicode Blog()