推导使用重复模板的函数的参数

时间:2014-12-10 11:53:00

标签: c++ templates

我从下面的代码中得到了错误。怎么了?一切似乎都到位了。

  

错误C2784:'void Menu :: AddLeaf(Command,const int)':不能   推导出'Command'的模板参数   '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

如果我在

上更改了对AddLeaf的调用
menu.AddLeaf<Launcher>(command, simsNodeId);

然后我得到下一个错误

  

错误C2770:'void的显式模板参数无效   Menu :: AddLeaf(Command,const int)'

2 个答案:

答案 0 :(得分:3)

您尝试将派生类对象传递给按值获取Command基类的函数。这将尝试切片对象,复制基础子对象并丢弃使其成为LauncherCommandLauncherCommandChangeSimulation的所有内容。即使这样有效,也不会是你想要的;在这种情况下,它不会起作用,因为基类是抽象的,因此无法实例化为完整的对象。

为了在菜单中存储多态对象,您需要某种间接方式。看起来你需要一个非模板的基类,而AddLeaf需要采用并存储一个(最好是智能的)指针。

答案 1 :(得分:2)

如果通过引用获取command参数,则它有效。

LIVE DEMO

这是因为§14.8.2.1(4):

  

通常,演绎过程会尝试查找模板参数值,这些参数值会使推导的AA相同(在A类型转换后如上所述)。但是,有三种情况可以产生差异:

     
      
  • ...
  •   
  • ...
  •   
  • 如果P是一个类而P的格式为 simple-template-id ,则转换后的A可以是推导出的派生类A。同样,如果P是指向 simple-template-id 形式的类的指针,则转换后的A可以是指向推导出的派生类的指针。 A
  •   

但是你需要处理对象的生命周期管理,所以迈克是正确的,你会想要一个智能指针。