问题
Actually, all the answers are nice, and informative but they don't solve my particular problem. I don't think that's the fault of the very helpful people who replied but instead, I badly phrased my question. Therefore I decided to post a completely new question with more relevant code examples here : Mixing Command pattern, Factory pattern and templates all together ... . If anyone cares to look ...
Now the original question :
I dont think it's possible to do what I want but I ask, just in case....
I have a familly of template classes I'd like to create through a factory. The reason why I use a factory is because the factory has some data members which are used for initializing every class created through that factory.
For example, let's consider this class :
class DoSomething : public UndoableCommand< int, float >
I tried to create a command factory, so it can create classes like the one above, and take care of their initialization, lifetime etc ...
In my (non-template) CommandFactory, I defined the following method :
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);
//...
}
However, this doesn't compile. The line "void operator()(P1 p1, P2 p2, P3 p3, P4 p4)" produces the following error :
error C2065: 'P1' : undeclared identifier
Because classes like "DoSomething" have only one declaration (DoSomething will always use < int, float >), I thought that I could use template argument deduction, and end up with a syntax like :
myCommandFactory.createCommand<DoSomething>( 1 /*int*/, 1.0f /*float*/);
Is it possible at all ? If so, what's the appropriate syntax ?
I guess I could always define my factory method like :
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);
//...
}
and then call
myCommandFactory.createCommand<DoSomething, int, float>( 1 /*int*/, 1.0f /*float*/);
but that is redundant and not very elegant...
回答1:
Try the following:
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);
}
It compiles at: http://ideone.com/tEWR5
回答2:
First of all, defined like here
class DoSomething : public UndoableCommand< int, float >
DoSomething
is a type, not a template, so you cannot use it with such a function.
Lets consider, you defined DoSomething
like
template <typename T, typename V>
struct DoSmth: public UndoableCommand {
DoSmth(T, V){}
};
Then, I noted, that your function has 4 params, but your DoSomething
has only 2. If you really want use variable count of parameters, you should use variadic templates.
So, your function should look like that:
struct Factory
{
template < template <typename...> class CommandType, typename... T>
void createCommand(T... args)
{
UndoableCommand* cmdPtr = new CommandType<T...>(args...);
}
};
And you can use it the following way:
int main()
{
Factory f;
f.createCommand<DoSmth>(1, false);
}
来源:https://stackoverflow.com/questions/11955859/using-template-template-parameter-on-function-call