You could leave the primary template of CRTPBase
undefined:
template<typename T> class CRTPBase;
And then partially specialize it this way:
template<template<typename, typename...> class TT,
typename SENDER, typename... ARGS>
class CRTPBase<TT<SENDER, ARGS...>>
{
// ...
};
Here is a simple program that shows the type arguments could be retrieved in CRTPBase
:
#include <tuple>
#include <type_traits>
template<typename T> class CRTPBase;
template<template<typename, typename...> class TT,
typename SENDER, typename... ARGS>
class CRTPBase<TT<SENDER, ARGS...>>
{
using type = std::tuple<SENDER, ARGS...>;
};
template<typename SENDER , typename... ARGS>
class event : public CRTPBase<event<SENDER,ARGS...>>
{
// ...
};
struct X { };
int main()
{
event<X, int, double> e;
// This assertion will not fire!
static_assert(std::is_same<
decltype(e)::type,
std::tuple<X, int, double>
>::value, "!");
}
Here is the corresponding live example.