CRTP + вариативный шаблон + извлечение параметров подкласса CRTP

В настоящее время я реализую общий класс событий. Обработчики событий имеют параметр отправителя и переменное количество аргументов событий. Итак, объявление класса событий выглядит следующим образом:

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

Чтобы разрешить определенные детали реализации, мне нужен CRTP события, например:

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

А база CRTP должна знать параметры события. Итак, я попробовал с параметром шаблона шаблона:

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

Но это не работает (я использую GCC 4.8.1).

Итак: Как лучше всего извлечь вариативные и не вариативные параметры шаблона аргумента CRTP?

РЕДАКТИРОВАТЬ: Другой способ - предоставить параметры события непосредственно через шаблон CRTP (template<typename EVENT , typename EVENT_SENDER , typename... EVENT_ARGS> class CRTPBase;), но я думаю, что есть способ сделать это напрямую, без явного написания параметров.


person Manu343726    schedule 07.07.2013    source источник


Ответы (1)


Вы можете оставить основной шаблон CRTPBase неопределенным:

template<typename T> class CRTPBase;

А затем частично специализируем его таким образом:

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

Вот простая программа, которая показывает, что аргументы типа могут быть получены в 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, "!");
}

Вот соответствующий живой пример.

person Andy Prowl    schedule 07.07.2013
comment
Я пробовал это, но не знаю, почему это не сработало :( Но спасибо - person Manu343726; 07.07.2013
comment
Ой, исправлено. Здорово! Спасибо! - person Manu343726; 07.07.2013
comment
Почему утверждение не сработает? - person George Robinson; 15.05.2018
comment
Он не должен стрелять. Почему вы этого ожидали? event ‹X, int, double› :: type на самом деле является кортежем ‹X, int, double›, поэтому они одного типа. Единственная причина, по которой это не будет компилироваться, заключается в том, что тип является частным и, следовательно, недоступен из main. - person Chris Uzdavinis; 15.05.2018