简体   繁体   中英

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

I have a template class defined like so:

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

Will C++ allow me to create a non-template subclass of a template class? What I mean is can I do something like this:

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

As is that is not working 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 the given T?

As we figured out in IRC, that was because you have

  1. Made your functions non-pure
  2. Sliced the derived object part. So the base class functions were called because the object wasn't a complete derived object anymore.

(Below follows my suspicion on earlier versions of your question - i keep it for further consideration and to keep the comments meaningful)


I think the issue here is that the compiler is free to instantiate any virtual function member of a class template even if it's not used (ie not called). Instantiating a function will need a function definition to be provided. Try to add this in the header, where the compiler will find them and instantiate 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 shall not implicitly instantiate a function template, a member template, a non-virtual member function, a member class or a static data member of a class template that does not require instantiation. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.

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

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 you have a NoopCommand.cpp, make sure it's included in your build process.

The pattern you use is widely known as the " Curiously Recurring Template Pattern ". so, yes, you can do that.
I can't think of a reason why it does not compile.

The code you gave compiles for me, without errors (after adding a struct NoopResult { }; ). Maybe there's a problem in the code you left out?

litb found the solution on ##c++ last night.

The issue was I was passing a NoopCommand to a function like this:

void SendCommand(Command<T> command);

When I should have made the signature this:

void SendCommand(Command<T>& command);

Making that change allows everything to compile.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM