1

I'm developing on an embedded platform using C++14 and I'm trying to design an event bus for task to task communications. I've structured by hierarchy such that the super class is of type Event * and my sub-classes are classes such as button events, logging, comms, etc. Now because I'm working on such a small embedded platform (STM32), I only want to store an array list of Event * types within the event bus and when a task submits an event for another task to consume, all I need to do is cast the Event * to the appropriate type for consuming. However, I want to avoid the situation of having huge case statements to figure out which type to cast the Event * to, as it'll be another thing to change when I add more user events to the system.

What features (if any) does C++14 offer to avoid such as situation. I'm currently reading into typeid() operator. I've also disabled RTTI too.

Thanks

nasher128
  • 11
  • 1
  • 4
    To avoid down casting and a huge case statement, C++ provides `virtual` functions that derived classes can use to `override`. – Eljay Oct 06 '19 at 12:41
  • If there's a possibility of moving to c++17 I would suggest looking at `std::variant`. There may be other non-std implementations too if you're not interested in changing version. – Chris Pearce Oct 06 '19 at 12:51
  • 1
    Personally this makes me think that polymorphism is what you're lokking for – Xatyrian Oct 06 '19 at 13:02
  • @Xatyrian as long as it's to interact with some sort of common interface. I'd only suggest variant as an option if the point was to store a heterogeneous buffer and later extract the specific events from it. – Chris Pearce Oct 06 '19 at 13:10
  • Seconding polymorphism; disabling RTTI does not disable virtual methods as the vtable is still present https://stackoverflow.com/questions/34353751/no-rtti-but-still-virtual-methods – jwimberley Oct 06 '19 at 13:17
  • 1
    @ChrisPearce well, OP is talking about `Event*` which makes me think that they uses a common interface somehow... – Xatyrian Oct 06 '19 at 13:31
  • Simply mark each event type with an enum member. Polymorphism sounds like overkill/overengineering. – Lundin Oct 07 '19 at 07:54

1 Answers1

0

Here is my simple solution of your issue:

#include <iostream>
#include <string>

enum class EventType {
  A,
  B,
};

struct Event {
  EventType type_;
};

class AEvent : public Event {
 public:
  AEvent(const std::string description)
    : Event{EventType::A}
    , description_{description} {
  }

  std::string get_description() const {
    return description_;
  }

 private:
  std::string description_;
};

class BEvent : public Event {
 public:
  BEvent(const std::string description)
      : Event{EventType::B}
      , description_{description} {
  }

  std::string get_description() const {
    return description_;
  }

 private:
  std::string description_;
};

void handling_event(Event * event) {
  switch (event->type_) {
    case EventType::A: {
      AEvent * aEvent = static_cast<AEvent *>(event);
    }
      break;
    case EventType::B: {
      BEvent * bEvent = static_cast<BEvent *>(event);
    }
      break;
  }
}

int main() {
  AEvent a{"Some stange event"};
  handling_event(&a);
  return 0;
}

It is simplest solution without RTTI and other indirection that can help

I hope it is helped ;)

Denis Kotov
  • 857
  • 2
  • 10
  • 29
  • Sorry for the late reply. To avoid casting, I could use a visitor design pattern to avoid static casts. As I'm working on an embedded platform, I'll try a few methods to achieve what I want. Your solution certainly helps – nasher128 Oct 09 '19 at 10:22
  • @nasher128 Yes you can use visitor, you also can use std::visitor, but it introduce additional complexity from my point of view. Solution that I suggest from my point of view is the simplest ;) – Denis Kotov Oct 09 '19 at 20:58