c++templatesboostboost-functionboost-preprocessor

How does boost::function support template class with different length template parameters


I want to use boost preprocessor to declare template classes with different template variable length, basically like what boost::function does.

#if !BOOST_PP_IS_ITERATING

#ifndef D_EXAMPLE_H
#define D_EXAMPLE_H
#include <boost/function>
#include <boost/preprocessor/iteration/iterate.hpp>
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 2, "example.h"))
#include BOOST_PP_ITERATE()

#else
template<class T, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class T)>
class Example
{
    boost::function<T, (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))> func;
};
#endif

the code above will obviously won't work because it declares the same class with different template variable length in the same header file. What I want to achieve is to include a single file and define classes with different template variable length just like boost::function.

#include "example.h"
Example<int, int, float> example1;
Example<double, int> example2;

I looked up boost::function's code but I can't figure it out how it works. Any ideas?


Solution

  • You need to declare the template class with the most parameters first, with default values for all parameters except the first one. The template classes with less parameters can then be defined as specializations of the main template class. Example:

    #include <iostream>
    
    template<class A, class B = void, class C = void>
    class Example
    {
    public:
        static const int x = 3;
    };
    
    template<class A, class B>
    class Example<A, B, void>
    {
    public:
        static const int x = 2;
    };
    
    template<class A>
    class Example<A, void, void>
    {
    public:
        static const int x = 1;
    };
    
    int main()
    {
        Example<int, int, int> e3;
        Example<int, int> e2;
        Example<int> e1;
        std::cout << e3.x << e2.x << e1.x << std::endl;
    }