3

I'm still trying to get the swing of metaprogramming, and I'm stumped.

What's I'd like to do is create a class/struct/whatever, supply it a std::tuple and have it automatically generate member functions based on the object types in the tuple. The goal is to have classes derive from MessageHandler

e.g.

typedef std::tuple< MessageA, MessageB, MessageC > MessageSet;

template< class T >
class MessageHandler
{
  // some magic metaprogramming would "create"...
  virtual void processMsg( const MessageA& ) = 0;
  virtual void processMsg( const MessageB& ) = 0;
  virtual void processMsg( const MessageC& ) = 0;
};

I've read that you can't have virtual functions in templates, but I didn't know if that was still true for C++11.

Thanks.

Michael
  • 2,827
  • 4
  • 30
  • 47
RMHarris157
  • 269
  • 2
  • 9
  • 2
    You can have virtual functions in templates. What you cannot have are `virtual member function templates`. – pmr Jul 29 '12 at 14:28
  • 1
    On second though: It would be interesting what you are actually trying to achieve. Solutions like mine or nawaz do what you show, but there is probably not going to be the kind of polymorphism you would want. – pmr Jul 29 '12 at 14:37

2 Answers2

5

The answer is variadic template, partial specialization, and inheritance as:

//primary template!
template<typename T>
class MessageHandler;

//variadic template, partial specialization and inheritance!
template<typename H, typename ...T>
class MessageHandler<std::tuple<H,T...>>  : public MessageHandler<std::tuple<T...>>
{
    virtual void processMsg( const H& ) = 0;
};

template<typename T>
class MessageHandler<std::tuple<T>>
{
    virtual void processMsg( const T& ) = 0;
};
Nawaz
  • 353,942
  • 115
  • 666
  • 851
4

You don't need tuple to do that:

struct MessageA{};struct MessageB{};struct MessageC{};

template <typename T>
struct message_interface {
  virtual void processMessage(const T& t) = 0;
};

template< typename... Args >
struct message_handler : public message_interface<Args>...
{};

struct message_impl : message_handler<MessageA, MessageB, MessageC>
{
  void processMessage(const MessageA&){}
  void processMessage(const MessageB&){}
  void processMessage(const MessageC&){}
};

int main()
{
  message_impl i;
  return 0;
}

It would probably be a good idea to check if the argument list is unique and static assert on that. Also make sure it does not contain reference types or other undesirables. Those will usually end up as errors when you try to form the argument type but it will safe your users some trouble.

EDIT: If you absolutely require to support tuple add a specialization:

template< typename... Args >
struct message_handler< std::tuple<Args...> > : public message_interface<Args>...
{};
pmr
  • 58,701
  • 10
  • 113
  • 156
  • 2
    Rather than provide a specialization for `std::tuple` it is possible to write a utility such that `bind>::type` is `message_impl`. Always useful when manipulating type lists. – Luc Danton Jul 29 '12 at 15:09
  • @LucDanton Yes, argument-list extraction from tuples is a must have. In general, I stay away from variadic templates for meta-programming and use the MPL exclusively. Avoids a ton of those problems. – pmr Jul 29 '12 at 15:10
  • Perfect. Thanks! What do you suggest as a reference for dealing with the variadic templates? I've been scouring the intertubes all weekend and I had no idea that you could put the ... after the base class definition (a la message handler). – RMHarris157 Jul 29 '12 at 17:01
  • Yet one thing still perplexes me... given all of the above, why can't I introduce a `template< class T > void processMsg( const T& ) { }` in the body of `message_impl`? If the compiler knows enough to create the virtual signatures, how does it not know enough to create stub functions? This would allow me to create a "default" object handler and only override the messages I care about. Thanks! – RMHarris157 Jul 29 '12 at 17:16
  • Nevermind. Got it. If I change `message_interface` from = 0 to { } then I can specialize selectively in `message_impl`. – RMHarris157 Jul 29 '12 at 17:28
  • @user1561041 I'm a little bit confused with what you are asking. Especially I don't see what you mean by `specializing selectively`. As for variadic templates. I had a list of tutorials, but have no idea how to get them to SO. – pmr Jul 30 '12 at 07:30