Is it possible to subclass a non-template class with a template class?

I have a template class defined like this:

template <class T>
class Command {
public:
    virtual T HandleSuccess(std::string response) = 0;
    virtual std::string FullCommand() const = 0;
    // ... other methods here ...
};

      

Does C ++ allow a non-classical subclass of a template class? I mean, can I do something like this:

class NoopCommand : public Command<NoopResult> {
public:
    NoopResult HandleSuccess(std::string response);
    std::string FullCommand() const;
    // ... other methods here ...
};

      

How it doesn't work for me because it says the following virtual functions are undefined:

T admix::Command<T>::HandleSuccess(std::string) [with T = admix::NoopResult]
std::string admix::Command<T>::FullCommand() const [with T = admix::NoopResult]

      

How can I specifically define them for a given T?

+2


source to share


5 answers


litb found a solution in ## C ++ last night.

The problem was that I was passing a NoopCommand to a function like this:

void SendCommand(Command<T> command);

      



When I should have done the signature:

void SendCommand(Command<T>& command);

      

Making this change compiles everything.

-1


source


As we found out on IRC, it was because you had

  • Made your functions impure
  • Slice a portion of a derived object. Thus, the base class functions were called because the object was no longer a fully derived object.

(The following is my suspicion of earlier versions of your question - I'm keeping it for further consideration and keeping the comments meaningful)




<sub> I think the problem here is that the compiler can instantiate any element of the virtual function of the class template, even if it is not used (i.e. not called). To create a function, a function definition is required. Try adding this to the header, where the compiler will find them and create a definition from:

template<typename T>
T Command<T>::HandleSuccess(std::string response) { /* put some default action ... */ }

template<typename T>
std::string Command<T>::FullCommand() const { /* put some default action ... */ }

      

C ++ Standard 14.7.1/9

:

An implementation must not implicitly create a function template, member template, non-virtual member, member class, or static data member of a class template that does not require instantiation. It is unclear if the implementation would implicitly implement an instance of the virtual member function of the class template if the virtual member function had not been implemented otherwise.

+4


source


"virtual functions are undefined" means that you have not defined the bodies of the NoopCommand :: HandleSuccess and NoopCommand :: FullCommand functions.

The following should solve your problem.

class NoopCommand : public Command<NoopResult> {
public:
    NoopResult HandleSuccess(std::string response) {}
    std::string FullCommand() const {}
    // ... other methods here ...
};

      

Or you have NoopCommand.cpp make sure it is included in your build process.

+3


source


The pattern you are using is commonly known as the " Curious Duplicate Pattern . " So yes, you can do that.
I can't think of why it won't compile.

+2


source


The code you provided for me is error free (after adding struct NoopResult { };

). Maybe the problem is in the code you left behind?

0


source







All Articles