Reputation: 19031
i got the error from code below. What is wrong? Everything seems to be in place.
error C2784: 'void Menu::AddLeaf(Command,const int)' : could not deduce template argument for 'Command' from 'LauncherCommandChangeSimulation'
Command.h
template <class Receiver>
class Command
{
virtual void Execute() = 0;
...
};
LauncherCommand.h
#include "Menu/Command.h"
#include "Internal/Launcher.h"
class LauncherCommand : public Command<Launcher>
{ ... };
class LauncherCommandChangeSimulation : public LauncherCommand
{ ... };
Menu.h
template <class T>
class Command;
class Menu
{
public:
template <class T>
void AddLeaf(Command<T> command, const int parentId);
};
Game.cpp
#include "Internal/Launcher.h"
#include "Menu/Menu.h"
#include "Menu/LauncherCommand.h"
LauncherCommandChangeSimulation command(...);
menu.AddLeaf(command, ...); // Error here
If i change call to AddLeaf on
menu.AddLeaf<Launcher>(command, simsNodeId);
then i get next error
error C2770: invalid explicit template argument(s) for 'void Menu::AddLeaf(Command,const int)'
Upvotes: 1
Views: 56
Reputation: 14714
It works if the command
parameter is taken by reference.
This is because of §14.8.2.1(4):
In general, the deduction process attempts to find template argument values that will make the deduced
A
identical toA
(after the typeA
is transformed as described above). However, there are three cases that allow a difference:
- ...
- ...
- If
P
is a class andP
has the form simple-template-id, then the transformedA
can be a derived class of the deducedA
. Likewise, ifP
is a pointer to a class of the form simple-template-id, the transformedA
can be a pointer to a derived class pointed to by the deducedA
.
But then you would need to deal with the object's lifetime management, so Mike is correct that you'll be wanting a smart pointer instead.
Upvotes: 2
Reputation: 254651
You're trying to pass a derived-class object to a function that takes the Command
base class by value. That will try to slice the object, copying the base sub-object and discarding everything that makes it a LauncherCommand
and a LauncherCommandChangeSimulation
. Even if that worked, it would not be what you want; and in this case it won't work, since the base class is abstract and so can't be instantiated as a complete object.
You'll need some kind of indirection in order to store polymorphic objects in the menu. It looks like you'll need a further, non-template, base class, and AddLeaf
will need to take and store a (preferably smart) pointer to that.
Upvotes: 3