Motivation

The C++ function and template parameter lists are special syntactic constructs, and it is impossible to directly manipulate or generate them using C++ constructs.  This leads to unnecessary code repetition.
Consider the implementation of the is_function<> metafunction is Boost.  The implementation uses an overloaded is_function_tester() function that is used for testing if a type is convertible to a pointer to a function.  Because of the special treatment of parameter lists, it is not possible to directly match a function with an arbitrary parameter list.  Instead, the is_function_tester() must be overloaded for every distinct number of parameters that is to be supported.  For example:
template<class R>
yes_type is_function_tester(R (*)());

template<class R, class A0>
yes_type is_function_tester(R (*)(A0));

template<class R, class A0, class A1>
yes_type is_function_tester(R (*)(A0, A1));

template<class R, class A0, class A1, class A2>
yes_type is_function_tester(R (*)(A0, A1, A2));

// ...
The need for this kind of repetition occurs particularly frequently while implementing generic components or metaprogramming facilities, but the need also manifests itself in many far simpler situations.

Typical Solutions

Typically the repetition is done manually.  Manual code repetition is highly unproductive, but sometimes more readable to the untrained eye.
Another solution is to write an external program for generating the repeated code or use some other extra linguistic means such as a smart editor.  Unfortunately, using external code generators has many disadvantages:

What about the preprocessor?

Because C++ comes with a preprocessor, one would assume that it would support these kinds of needs directly.  Using the preprocessor in this case is highly desirable because:
Most unfortunately, the preprocessor is a very low level preprocessor that specifically does not support repetition or recursive macros.  Library support is needed!
For detailed information on the capabilities and limitations of the preprocessor, please refer to the C++ standard [Std].

The Motivation Example Revisited

Using the primitives of the preprocessor library, the is_function_tester()'s could be implemented like this:
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition.hpp>

#ifndef MAX_IS_FUNCTION_TESTER_PARAMS
#define MAX_IS_FUNCTION_TESTER_PARAMS 15
#endif

#define IS_FUNCTION_TESTER(Z, N, _) \
   template<class R BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, class A)> \
   yes_type is_function_tester(R (*)(BOOST_PP_ENUM_PARAMS(N, A))); \
   /**/

BOOST_PP_REPEAT(BOOST_PP_INC(MAX_IS_FUNCTION_TESTER_PARAMS), IS_FUNCTION_TESTER, _)

#undef IS_FUNCTION_TESTER
In order to change the maximum number of function parameters supported, you now simply change the MAX_IS_FUNCTION_TESTER_PARAMS definition and recompile.

© Copyright Housemarque Oy 2002
Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies.  This document is provided "as is" without express or implied warranty and with no claim as to its suitability for any purpose.

© Copyright Housemarque Oy 2002
© Copyright Paul Mensonides 2002

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at www.boost.org/LICENSE_1_0.txt)