You can use Boost.Preprocessor to simulate variadic templates in C++98. What is actually done behind the scenes is that the preprocessor writes all the specializations of the template for different numbers of parameters for you. You can now use the typedef in varadic<...>::type
with up to 256 template arguments.
With templates it is not such a problem because only instantiated templates go into the binary but for non-template entities this can result in massive code bloat.
#include <iostream>
#include <boost/preprocessor/config/limits.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
// Macro to generate specializations
#define MAKE_VARIADIC(Z, N, _) \
template < \
typename R \
BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename T) \
> \
struct variadic < R BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, T) > \
{ \
typedef R (*type)(BOOST_PP_ENUM_PARAMS_Z(Z, N, T)); \
};
// Declare variadic struct with maximum number of parameters
template <
typename R
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_LIMIT_ITERATION, typename T, = void BOOST_PP_INTERCEPT)
>
struct variadic;
// Repeat macro to create all specializations
BOOST_PP_REPEAT(BOOST_PP_LIMIT_ITERATION, MAKE_VARIADIC, nil)
// Function to print what was derived
template < typename T >
void print_T()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
// Test
int main ()
{
print_T< variadic<int, double, float>::type > ();
}
Demo on Wandbox
However, it is much more convenient to use C++11 alias templates for this kind of thing and today in 2017, 6 years after the standard was ratified, there is no reason not to switch to C++11. Still using C++98 is kind of like still using Windows XP.
#include <iostream>
template <typename R, typename ... Args>
using pf = R(*)(Args...);
// Function to print what was derived
template < typename T >
void print_T()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
// Test
int main ()
{
print_T< pf<int, double, float> > ();
}
Demo on Wandbox