0

I have a base class MessageBase, from which I derive various other message classes, e.g., MessageDerived. I have another class that does some processing on various types of data, including a catchall method template:

struct Process {
  void f(int a);
  void f(const char* b);
  template<typename T> void f(const T &t) { ... }
};

So if I call Process::f on a message object, the template method is called.

Now I want to add custom functionality for for my message classes. I am not allowed to change Process, so I want to derive from it (but even if I could change it, I can't find a way to get the custom functionality). I tried:

struct ProcessDerived : public Process {
  void f(const MesaageBase& m) { ... }  // Custom functionality for messages.
};

But that only works when I call ProcessDerived::f on a MessageBase object. If I invoke it on a MessageDerived object, the template method gets selected instead.

Is there a way to get the custom function selected on all message classes while letting the template catch all other types?

Ari
  • 3,460
  • 3
  • 24
  • 31

2 Answers2

2

You need to use SFINAE here. Here is an example (note that it needs c++11 to work):

struct ProcessDerived : public Process
{
  template<typename T> void f(const T &t, typename std::conditional<std::is_base_of<MessageBase, T>::value, int, void>::type = 0)
  {
    /// do something specific
  }

  template<typename T> void f(const T &t, ...)
  {
    return Process::f (t);
  }
};

};

You can read more about it at http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error

Alex Telishev
  • 2,264
  • 13
  • 15
0

ProcessDerived::f shadows all definitions of Process::f (see here: Overloading rules for inheritance in C++). So calling ProcessDerived::f with a MessageDerived object calls ProcessDerived::f(const MessageBase&) as this is the only visible f, but e.g.

ProcessDerived pd; 
pd(42);

won't compile. You need to add a

using Process::f;

in ProcessDerived for the problem you described showing up. The solution proposed by Alex Telishev while I was writing fixes both problems at once, however.

Community
  • 1
  • 1
gTcV
  • 2,446
  • 1
  • 15
  • 32