Pergunta

Im currently implementing a generic event class. Event handlers have a sender parameter and a variable number of event args. So the declaration of the event class is as bellow:

template<typename SENDER , typename... ARGS>
class event;

To allow certain implementation details, I need a CRTP of the event, like this:

template<typename SENDER , typename... ARGS>
class event : public CRTPBase<event<SENDER,ARGS...>> { ... };

And the CRTP base needs to know the event parameters. So I have tried with a template template param:

template<typename SENDER , template<typename SENDER , typename... ARGS> class EVENT, typename ARGS>
class CRTPBase { ... };

But this doesn't work (Im using GCC 4.8.1).

So: What is the best way to extract the variadic and non-variadic template parameters of the argument of a CRTP?

EDIT: Another way is to provide event parameters directly through the CRTP template (template<typename EVENT , typename EVENT_SENDER , typename... EVENT_ARGS> class CRTPBase; ), but I think there is a way to do this directly, without writting the params in a explicit way.

Foi útil?

Solução

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top