mkosler
mkosler

Reputation: 322

Passing a generic struct as a parameter in an interface

In C++, suppose I have a messaging system that wraps messages in a generic struct:

template<typename T>
struct Message
{
  std::string Name;
  T Data;
};

I also have an interface that includes functions that need to use the purely generic version of this struct:

class Interface
{
  public:
    virtual ~Interface() { }
    virtual void Receive(Message& message) = 0;
    virtual Message Send() = 0;
};

However, Message no longer names a type; things like Message<float> and Message<std::string> name types. Since the classes that will be implementing Interface will want to catch different Message, I can't just define a specific type.

The only way I can think to fix this is to rip out the template and using inheritance, but then I'd have littered throughout my code things like IntMessage and BoolMessage, which looks extraordinarily ugly. Any thoughts on how I can do this the way I want?

Upvotes: 3

Views: 2034

Answers (2)

A simple approach is to split the Message type into a hierarchy:

struct MessageBase {
  std::string Name;
};
template<typename T>
struct Message : MessageBase
{
  T Data;
};

Then you can just pass MessageBase& through interfaces.

[The previous won't work. The function will be able to accept any MessageBase& object, but Receive seems to be about storing in the argument a message for which the type is unknown a compile time. Although if you don't mind dynamic allocations you could have a Message that holds the name and a pointer to a MessageBase and then different implementations of MessageImpl (the template above)]

Another common approach is to add all possible messages to an union and pass the union around.

Upvotes: 2

yms
yms

Reputation: 10418

Why don't you define your interface as a template?

template<typename T>
class Interface
{
  public:
    virtual ~Interface() { }
    virtual void Receive(Message<T>& message) = 0;
    virtual Message<T> Send() = 0;
};

Upvotes: 1

Related Questions