Voici mon code si quelqu'un est intéressé
En gros, au moment de la compilation, le compilateur va dérouler récursivement tous les arguments dans les différents appels de fonctions inclusives <N> -> appels <N-1> -> appels ... -> appels <0> qui est le dernier et le compilateur va optimiser les différents appels de fonctions intermédiaires pour ne garder que le dernier qui est l'équivalent de func(arg1, arg2, arg3, ...).
Il existe 2 versions, l'une pour une fonction appelée sur un objet et l'autre pour une fonction statique.
#include <tr1/tuple>
/**
* Object Function Tuple Argument Unpacking
*
* This recursive template unpacks the tuple parameters into
* variadic template arguments until we reach the count of 0 where the function
* is called with the correct parameters
*
* @tparam N Number of tuple arguments to unroll
*
* @ingroup g_util_tuple
*/
template < uint N >
struct apply_obj_func
{
template < typename T, typename... ArgsF, typename... ArgsT, typename... Args >
static void applyTuple( T* pObj,
void (T::*f)( ArgsF... ),
const std::tr1::tuple<ArgsT...>& t,
Args... args )
{
apply_obj_func<N-1>::applyTuple( pObj, f, t, std::tr1::get<N-1>( t ), args... );
}
};
//-----------------------------------------------------------------------------
/**
* Object Function Tuple Argument Unpacking End Point
*
* This recursive template unpacks the tuple parameters into
* variadic template arguments until we reach the count of 0 where the function
* is called with the correct parameters
*
* @ingroup g_util_tuple
*/
template <>
struct apply_obj_func<0>
{
template < typename T, typename... ArgsF, typename... ArgsT, typename... Args >
static void applyTuple( T* pObj,
void (T::*f)( ArgsF... ),
const std::tr1::tuple<ArgsT...>& /* t */,
Args... args )
{
(pObj->*f)( args... );
}
};
//-----------------------------------------------------------------------------
/**
* Object Function Call Forwarding Using Tuple Pack Parameters
*/
// Actual apply function
template < typename T, typename... ArgsF, typename... ArgsT >
void applyTuple( T* pObj,
void (T::*f)( ArgsF... ),
std::tr1::tuple<ArgsT...> const& t )
{
apply_obj_func<sizeof...(ArgsT)>::applyTuple( pObj, f, t );
}
//-----------------------------------------------------------------------------
/**
* Static Function Tuple Argument Unpacking
*
* This recursive template unpacks the tuple parameters into
* variadic template arguments until we reach the count of 0 where the function
* is called with the correct parameters
*
* @tparam N Number of tuple arguments to unroll
*
* @ingroup g_util_tuple
*/
template < uint N >
struct apply_func
{
template < typename... ArgsF, typename... ArgsT, typename... Args >
static void applyTuple( void (*f)( ArgsF... ),
const std::tr1::tuple<ArgsT...>& t,
Args... args )
{
apply_func<N-1>::applyTuple( f, t, std::tr1::get<N-1>( t ), args... );
}
};
//-----------------------------------------------------------------------------
/**
* Static Function Tuple Argument Unpacking End Point
*
* This recursive template unpacks the tuple parameters into
* variadic template arguments until we reach the count of 0 where the function
* is called with the correct parameters
*
* @ingroup g_util_tuple
*/
template <>
struct apply_func<0>
{
template < typename... ArgsF, typename... ArgsT, typename... Args >
static void applyTuple( void (*f)( ArgsF... ),
const std::tr1::tuple<ArgsT...>& /* t */,
Args... args )
{
f( args... );
}
};
//-----------------------------------------------------------------------------
/**
* Static Function Call Forwarding Using Tuple Pack Parameters
*/
// Actual apply function
template < typename... ArgsF, typename... ArgsT >
void applyTuple( void (*f)(ArgsF...),
std::tr1::tuple<ArgsT...> const& t )
{
apply_func<sizeof...(ArgsT)>::applyTuple( f, t );
}
// ***************************************
// Usage
// ***************************************
template < typename T, typename... Args >
class Message : public IMessage
{
typedef void (T::*F)( Args... args );
public:
Message( const std::string& name,
T& obj,
F pFunc,
Args... args );
private:
virtual void doDispatch( );
T* pObj_;
F pFunc_;
std::tr1::tuple<Args...> args_;
};
//-----------------------------------------------------------------------------
template < typename T, typename... Args >
Message<T, Args...>::Message( const std::string& name,
T& obj,
F pFunc,
Args... args )
: IMessage( name ),
pObj_( &obj ),
pFunc_( pFunc ),
args_( std::forward<Args>(args)... )
{
}
//-----------------------------------------------------------------------------
template < typename T, typename... Args >
void Message<T, Args...>::doDispatch( )
{
try
{
applyTuple( pObj_, pFunc_, args_ );
}
catch ( std::exception& e )
{
}
}