2021年3月3日星期三

Variadic template inheritance order and syntax

I am trying to implement a signal/slot system via templates to get into some advanced usage of templates. I looked up existing implementations and found one at https://github.com/skypjack/eventpp. I have been trying to understand how it works and pretty much figured it out but there are still some things I can't wrap my head around and couldn't find anything on the internet (didn't know what to search for).

Following is an executable minimal example of the code I took from the github repo plus additional code I implemented myself:

//Signal implementation (own code)  template <typename S>  struct Signal  {    using type = S;  };    struct KeyPressedEvent : Signal<KeyPressedEvent>  {    KeyPressedEvent(int keyCode) : keyCode_{keyCode} {}    int keyCode() {return keyCode_;}      private:      int keyCode_;  };    struct KeyReleasedEvent : Signal<KeyReleasedEvent>  {    KeyReleasedEvent(int keyCode) : keyCode_{keyCode} {}    int keyCode() {return keyCode_;}      private:      int keyCode_;  };        //Signal Bus implementation (github repo code)  template<int S, typename... E>  struct BusBase;    template<int S, typename E, typename... O>  struct BusBase<S, E, O...> : BusBase<S, O...>  {    BusBase()    {      if(std::is_same<E, KeyPressedEvent>::value)      {        std::cout << "BusBase<S, E, O...> KeyPressedEvent" << std::endl;      }      if(std::is_same<E, KeyReleasedEvent>::value)      {        std::cout << "BusBase<S, E, O...> KeyReleasedEvent" << std::endl;      }    }      Signal<E> signal_;  };    template<int S>  struct BusBase<S>  {    BusBase()    {      std::cout << "BusBase<S>" << std::endl;    }  };    template <typename... E>  struct Bus : BusBase<sizeof...(E), E...>  {    Bus()    {      std::cout << "Bus" << std::endl;    }  };    int main(int& argc, const char* args[])  {    Bus<KeyPressedEvent, KeyReleasedEvent> eventBus;      std::cin.get();  }  

Here is the output i get when i run the program:

BusBase<S>  BusBase<S, E, O...> KeyReleasedEvent  BusBase<S, E, O...> KeyPressedEvent  Bus  

I will state what i understood from the implementation. Please correct me if I am wrong.

template<int S, typename... E>  struct BusBase;  

is needed to expand the parameter pack from Bus

BusBase<S, E, O...>  

is instantiated for every Signal in Bus

BusBase<S>  

is needed when the parameter pack has been fully expanded

My questions:

1.

BusBase<S>  

Why is this specialization instantiated first? I would have expected it to be last (before Bus).

2.

template<int S>  struct BusBase<S>    template<int S, typename E, typename... O>  struct BusBase<S, E, O...> : BusBase<S, O...>  

From what i understood, template specialization is written as

template<>  struct BusBase<S, E, O...>  

So why are the parameters both in the template declaration and in the struct declaration?

Thank you for your help.

https://stackoverflow.com/questions/66467562/variadic-template-inheritance-order-and-syntax March 04, 2021 at 10:06AM

没有评论:

发表评论