boost.preprocessor
can do this kind of stuff and you can have descent tutorial here: Intro to preprocessor metaprogramming
For your specific example here's the code I came up with (note: I just ran it under the preprocessor to check that the resulting code was what I would expect but did not try to compile the code itself).
This uses both the enum_params
macro that helps generate list of attributes and local_iterate
that allow to expand a macro with a range of argument. I have also a macro if to handle your special case with ": " vs "," for the first argument sent to your stream.
Overall when you start to understand how boost.preprocessor
work searching for the feature you need in its reference manual becomes relatively easy and its a "reasonable" replacement until variadic templates are supported by most compilers. Do note though that it is very intensive at compilation time, so use with caution.
edit: While I did consider this as a general exercise with a relatively simple example I do agree though that in term of coding for this specific example using a pseudo stream class as suggested by synek317 would be a more flexible and "lightweight" solution. Again implementing such stream do not require you to do the specialization of all the operators and in fact boost again provide the IOStreams library to help you implement a class as a standard C++ stream (http://www.boost.org/doc/libs/1_52_0/libs/iostreams/doc/index.html)
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/control/if.hpp>
# ifndef MY_SEND_MAX
# define MY_SEND_MAX 15
# endif
/*
* macros called through BOOST_PP_REPEAT to generate lists
* J : I don't know what it is
* I : the current counter number
* D : the 3rd argument of BOOST_PP_REPEAT
*/
// Generate the list of arguments after std::string
# define MY_SEND_PARAM(J,I,D) , BOOST_PP_CAT(const T,I) & BOOST_PP_CAT(arg,I)
// Generate the stream's <<s adter the string
# define MY_SEND_STREAM(J,I,D) <<BOOST_PP_IF(I,",",": ")<<BOOST_PP_CAT(arg,I)
/*
* Macro to call for generating onde function
* N : the number of arguments
*/
// Create one function with a string and N extra aarguments
# define MY_SEND(N) \
template<BOOST_PP_ENUM_PARAMS(N,typename T)> \
void send(std::string const &fn BOOST_PP_REPEAT(N,MY_SEND_PARAM,~)) { \
std::ostringstream s; \
s<<fn BOOST_PP_REPEAT(N,MY_SEND_STREAM,~); \
sendMessage(s.str()); \
}
// End of my macro
/*
* BOOST_PP local loop to generate all the the function
*/
// What macro to call in the loop
#define BOOST_PP_LOCAL_MACRO(n) MY_SEND(n)
// do the job form 0 to MY_SEND_MAX
#define BOOST_PP_LOCAL_LIMITS (0,MY_SEND_MAX)
// execute the loop
#include BOOST_PP_LOCAL_ITERATE()
// undefine all my stuff
# undef MY_SEND_PARAM
# undef MY_SEND_STREAM
# undef MY_SEND
# undef BOOST_PP_LOCAL_MACRO
# undef BOOST_PP_LOCAL_LIMITS