C++: "specializing" a member function template to work for derived classes from a certain base class

StackOverflow https://stackoverflow.com/questions/21509542

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?

有帮助吗?

解决方案

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

其他提示

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top