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
(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.