2012-08-14 85 views
0

其实,所有的答案都很好,而且内容翔实,但它们不能解决我的特殊问题。我不认为这是回答非常有帮助的人的错,而是我严厉地解释了我的问题。因此,我决定在这里发布一个全新的问题,其中包含更多相关的代码示例:Mixing Command pattern, Factory pattern and templates all together ...。如果有人关心一下......在函数调用中使用模板模板参数

现在,原题:

我不认为这是可以做到我想要什么,但我要问,以防万一....

我有一个familly我希望通过工厂创建模板类。 我使用工厂的原因是工厂有一些数据成员,用于初始化通过该工厂创建的每个类。

例如,让我们考虑这个类:

class DoSomething : public UndoableCommand< int, float > 

我试图创建一个命令工厂,所以它可以创建类像上面的,并照顾他们的初始化,寿命等等

在我的(非模板)的CommandFactory,我定义了以下方法:

template < template <typename P1, typename P2, typename P3, typename P4> class CommandType> 
void createCommand(P1 p1, P2 p2, P3 p3, P4 p4) 
{ 
UndoableCommand* cmdPtr; 
cmdPtr=new CommandType(P1 p1, P2 p2, P3 p3, P4 p4); 
//... 
} 

然而,这并不编译。行 “void运算符()(P1 P1,P2 P2,P3 P3,P4 P4)” 产生以下错误:

错误C2065:P1':未声明的标识符

因为类等“DoSomething的”只有一个声明(DoSomething的总是会使用<整数,浮点>),我以为我可以使用模板参数推导,并用语法落得像:

myCommandFactory.createCommand<DoSomething>(1 /*int*/, 1.0f /*float*/); 

是否有可能在所有?如果是这样,什么是适当的语法?

我想我随时可以定义我的工厂方法,如:

template <class CommandType, typename P1, typename P2, typename P3, typename P4> 
void createCommand(P1 p1, P2 p2, P3 p3, P4 p4) 
{ 
UndoableCommand* cmdPtr; 
cmdPtr=new CommandType(P1 p1, P2 p2, P3 p3, P4 p4); 
//... 
} 

,然后调用

myCommandFactory.createCommand<DoSomething, int, float>(1 /*int*/, 1.0f /*float*/); 

但这是多余的,不是很优雅......

+1

有没有这样的事,作为一个'模板class',只有'类模板'。 – pmr 2012-08-14 16:12:52

回答

1

尝试如下:

struct UndoableCommand { }; 

template < 
    template <typename P1, typename P2> class CommandType, 
    typename P1a, typename P2a 
     > 
void createCommand(P1a p1, P2a p2) 
{ 
    UndoableCommand *cmdPtr = new CommandType<P1a,P2a>(p1, p2); 
} 

template <typename P1, typename P2> class MyCommand : public UndoableCommand 
{ 
public: 
    MyCommand(P1, P2) { } 
}; 

int main() 
{ 
    createCommand<MyCommand>(1, 2.0); 
} 

它编译于:http://ideone.com/tEWR5

+1

我将首先使用template-template参数,以便它可以用作'createCommand (args)',而不必指定参数的类型。 – 2012-08-14 15:51:08

+0

我更新了我的答案。 – 2012-08-14 16:02:44

+0

哇你们比我更深刻的模板undertsanding!基里尔,你的代码似乎工作。我没有尝试实际调用create方法,因为我有其他错误,但至少编译了它。戴夫,你介意发展你的答案吗? – Dinaiz 2012-08-14 16:03:40

1

首先,定义喜欢这里

class DoSomething : public UndoableCommand< int, float > 

DoSomething是一个类型,而不是一个模板,所以你不能用这样的功能使用。

让我们考虑,你喜欢

template <typename T, typename V> 
struct DoSmth: public UndoableCommand { 
    DoSmth(T, V){} 
}; 

定义DoSomething然后,我注意到,你的函数有4个参数,可以,但你的DoSomething只有2.如果你真的想使用的参数变量数,你应该使用可变模板。

所以,你的函数应该看起来像:

struct Factory 
{ 
    template < template <typename...> class CommandType, typename... T> 
    void createCommand(T... args) 
    { 
     UndoableCommand* cmdPtr = new CommandType<T...>(args...); 
    } 
}; 

而且你可以用它的方式如下:

int main() 
{ 
    Factory f; 
    f.createCommand<DoSmth>(1, false); 
} 
+0

你是绝对正确的。你的例子就是我真正在代码中做的事情,我只是简化了它,并使其错误。我的错。但是,我真的想有一个成员函数,而不是一个自由函数。没有办法,是吗? – Dinaiz 2012-08-14 16:10:38

+0

@Dinaiz,你想让'createCommand'成员函数?去做就对了!没有任何问题,除了它应该_defined_(与_declared_相反)在头文件中(不在'cpp'文件中) – Lol4t0 2012-08-14 16:13:03

+0

@Dinaiz,将'createCommand'移到'struct' – Lol4t0 2012-08-14 16:15:57