Gerald
Gerald

Reputation: 23489

Variadic templates in class definitions

So I'm trying to wrap my head around the new variadic templates in C++, and I'm wondering if I can use it to simplify some code that I have. I have something like this:

template<typename FinalPatch,typename ReturnType, typename P1>
class Patch1: public PatchBase
{
   public:
      typedef Patch1<FinalPatch,ReturnType,P1> patch_type;
      typedef ReturnType(WINAPI* FuncType)( P1 );
      typedef std::function<ReturnType(P1)> function_type;


      static ReturnType __stdcall exec( P1 p1 )
      {
         return _function(p1);
      }
};

template<typename FinalPatch,typename ReturnType, typename P1, typename P2>
class Patch2: public PatchBase
{
   public:
      typedef Patch2<FinalPatch,ReturnType,P1,P2> patch_type;
      typedef ReturnType(WINAPI* FuncType)( P1, P2 );
      typedef std::function<ReturnType(P1,P2)> function_type;

      static ReturnType __stdcall exec( P1 p1, P2 p2 )
      {
         return _function(p1, p2);
      }
};

And on until about 10 P... parameters.

The exec static method is used in a Detours-like system where it replaces a WINAPI function, then proxies it to a std::function delegate.

FuncType represents a 'normal' function pointer.

Is it possible to reduce this to a single class using variadic templates? And if so, how?

Upvotes: 0

Views: 124

Answers (1)

dyp
dyp

Reputation: 39111

Something along the lines of:

template<typename FinalPatch,typename ReturnType, typename... Ps>
class PatchN: public PatchBase
{
   public:
      typedef PatchN patch_type;
      typedef ReturnType(WINAPI* FuncType)( Ps... );
      typedef std::function<ReturnType(Ps...)> function_type;
      // more "modern" C++11 notation
      //using patch_type = PatchN;
      //using FuncType = ReturnType(WINAPI*)(Ps...);
      //using function_type = std::function<ReturnType(Ps...)>;

      static ReturnType __stdcall exec( Ps... ps )
      {
         return _function(ps...);
      }
      // or, using perfect forwarding:
      //static ReturnType __stdcall exec( Ps&&... ps )
      //{
      //   return _function(std::forward<Ps>(ps)...);
      //}
};

Typically, the function type is extracted from a single template argument (like in std::function), e.g.

template<typename FinalPatch, typename Func>
class PatchN;

template<typename FinalPatch, typename ReturnType, typename... Ps>
class PatchN<FinalPatch, ReturnType(Ps...)>;

Upvotes: 2

Related Questions