Reputation: 30615
I produce messages and each is receive by one object, chosen by an enum class
member:
enum class ReceiverID
{
R1,
R2,
MAX_NUM_RECEIVERS
};
struct Msg
{
ReceiverID _receiverID;
Data _data;
};
The receiving classes are stored in an array. The enum member indexes the array to access the receiving object:
void receive(const Msg& msg)
{
const size_t arrIndex = static_cast<size_t>(msg._receiverID);
if(nullptr == _array[arrIndex])
{
_array[arrIndex] = ??? // How do I associate the enum to the class?
}
_array[arrIndex].processMsg(msg);
}
It is possible the receiving object is missing. If this happens I'd like to use the enum to instantiate the missing object. However, this would require mapping the enum values to the receiving object type.
How can I map a class to each enum? (for all enums).
I'd like to generate a compiler error if a new enum is added but without a corresponding receiver class.
UPDATE
The receiving objects are polymorphic and so have a base class. The array is:
std::array<Base*, MAX_NUM_RECEIVERS> _array;
(removed unique_ptr
to simplify question)
Upvotes: 1
Views: 270
Reputation: 1168
For on-the-fly creation of objects we could go for some kind of a factory method, e.g.:
//In the Base class:
static Base* createReceiver(ReceiverID recvID) //static member function
{
switch (recvID)
{
case ReceiverID::R1: return new R1Receiver();
case ReceiverID::R2: return new R2Receiver();
//...
default: throw std::logic_error("Invalid ReceiverID");
}
}
//...
void receive(const Msg& msg) except(true)
{
const size_t arrIndex = static_cast<size_t>(msg._receiverID);
if(nullptr == _array[arrIndex])
{
_array[arrIndex] = Base::createReceiver(msg._receiverID);
}
_array[arrIndex]->processMsg(msg);
}
Upvotes: 3
Reputation: 66922
Instead of having a global std::array<Base*, MAX_NUM_RECEIVERS> _array;
and then lazily filling it out on demand, I believe the normal thing to do is make it filled out at construction time:
std::array<Base*, MAX_NUM_RECEIVERS>& _array() {
//use a method to bypass https://stackoverflow.com/questions/1005685/c-static-initialization-order
static std::array<Base*, MAX_NUM_RECEIVERS> array = make_array();
return array;
}
std::array<Base*, MAX_NUM_RECEIVERS> make_array() {
std::array<Base*, MAX_NUM_RECEIVERS> array;
array[static_cast<size_t>(R1)] = &myR1ProcessorObject();
array[static_cast<size_t>(R2)] = &myR2ProcessorObject();
return array;
}
Then your receive method is simple:
void receive(const Msg& msg)
{
const size_t arrIndex = static_cast<size_t>(msg._receiverID);
assert(arrIndex< MAX_NUM_RECEIVERS);
_array()[arrIndex].processMsg(msg);
}
Upvotes: 1