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