double template parameter pack

Magix

Here is what my class looks like :

template<typename ...events_t, std::uint32_t ...stackDepth>
class Module {
    protected: std::tuple<EventHandler<events_t, stackDepth>...> evtHandlers;
    public: Module(std::tuple<EventHandler<events_t, stackDepth>...> _evtHandlers) : 
         evtHandlers{_evtHandlers}{ /* ... */ }
    // ...
}

I am constrained to give the EventHandler a pair of template arguments, one being the handled event type and the other one an std::uint32_t for the task's stack depth.

The double template parameter pack cannot compile as-is, but I could not find a trick that would do. Is there any way to make this work cleanly ?

max66

A template variadic parameter, for a template class/struct, must be at the end of the list of template parameters. So, directly, you can use only one.

But you can wrap one (or both) your variadic packs with, by example, std::tuple, for types, and, std::integer_sequence, for integer values.

Unfortunately, you have to use template specialization: you have to declare the main template receiving, by example, a couple of types

template <typename, typename>
class Module;

and a specialization that uses the single typename as template wrapper as follows

template <typename ... event_t, std::uint32_t ... stackDepth>
class Module<std::tuple<event_t...>, 
             std::integer_sequence<std::uint32_t, stackDepth...>>
 {
   // ...
 };

Given that you can place a variadic list at the end, you can avoid the second wrapper, so, by example,

template <typename, std::uint32_t...>
class Module;

template <typename ... event_t, std::uint32_t ... stackDepth>
class Module<std::tuple<event_t...>, stackDepth...>>
 {
   // ...
 };

Given that, if I understand correctly, the types (event_t) and the numbers (stackDepth) are related and that you have a template class/struct that accept a single type and a single number as template parameter (Event_Handler), I suppose you can directly use Event_Handler as variadic parameter.

I mean something as follows (full compiling example)

#include <cstdint>

template <typename, std::uint32_t>
struct Event_Handler
 { };

template <typename...>
class Module;

template <typename ... event_t, std::uint32_t ... stackDepth>
class Module <Event_Handler<event_t, stackDepth>...>
 {
   // ...
 };

int main ()
 {
   Module<Event_Handler<int, 0u>, Event_Handler<long, 1u>>  m;
 }

-- EDIT --

The OP asks

Actually I'd like to take it not as a pure template parameter but as an instance in the constructor. Is this possible with this trick ?

If I understand correctly, you're looking for "template deduction guides", available starting from C++17 (and you tagged C++17, so should works for you.

The following is a full (C++17) compiling example; the "explicit deduction guide" is the construct immediately before the main()

#include <cstdint>

template <typename, std::uint32_t>
struct Event_Handler
 { };

template <typename...>
class Module;

template <typename ... event_t, std::uint32_t ... stackDepth>
class Module <Event_Handler<event_t, stackDepth>...>
 {
   public: 
      Module (Event_Handler<event_t, stackDepth>...)
       { }
 };

// explicit deduction guide
template <typename ... event_t, std::uint32_t ... stackDepth>
Module (Event_Handler<event_t, stackDepth>...)
   -> Module<Event_Handler<event_t, stackDepth>...>;

int main ()
 {
   Module  m(Event_Handler<int, 0u>{}, Event_Handler<long, 1u>{});
 }

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related