I already asked a similar question here, however I didn't really get the answer I wanted because my question was poorly formulated and the examples were bad. So I give it another shot, with hopefully a better explanation and better code .

The code bellow has been stripped out of unnecessary details but it works . The thing is I would like to use Template Argument Deduction, if possible, to simplify the templated function call .

I have a factory which creates commands. To create a command, I use a call like that one :

mCommandFactory.createCommand<
                        DoSomeStuff, 
                        ParameterType1, 
                        ParameterType2, 
                        ParameterType3, 
                        ParameterType4
                        >
                        (std:string("some description"), 
                         parameter1, 
                         parameter2, 
                         parameter3, 
                         parameter4);

As you probably have guessed, parameter1 type is ParameterType1, and so on ... .

Now if we look at the definition of the command - DoSomeStuff- itself :

class DoSomeStuff : public UndoableCommand< ParameterType1 , ParameterType2, ParameterType3 , ParameterType4 >
    {
    public:
      DoSomeStuff(... /* arguments which are needed for precessing the command and undoing it*/ );
      ~DoSomeStuff() throw();
      void executeImpl();
      void undoImpl();

    protected:
              ... /* members which are needed for precessing the command and undoing it*/ 
    };

As you can see, ParameterTypeN information is already inside DoSomeStuff declaration.

I was wondering if it was possible somehow to replace the createCommand call above by something simpler :

mCommandFactory.createCommand<DoSomeStuff>
                        (std:string("some description"), 
                         parameter1, 
                         parameter2, 
                         parameter3, 
                         parameter4);

Here is the CommandFactory code :

    class CommandFactory
    {
    private:
          // some stuff used to initialize objects created by this factory 

    public:
        CommandFactory(...) : ... /* members initialization */

        {  
        }


        template <class CommandType, typename P1, typename P2, typename P3, typename P4> 
        void createCommand(juce::String& description,P1 p1, P2 p2, P3 p3, P4 p4)
        {
            Undoable* cmdPtr = new CommandType(p1, p2, p3, p4);
            ...
            // init cmdPtr

            (*cmdPtr)();            
        }

Basically the point would be to move the complexity inside CommandFactory, to keep the "client code" (the call to createCommand) as simple and short as possible.

Any ideas ?

有帮助吗?

解决方案

Not sure I understand the question correctly, but this should work.

template<typename ParameterType1 , typename ParameterType2, typename ParameterType3 , typename ParameterType4>
class UndoableCommand
{
public:
    UndoableCommand(ParameterType1 p1, ParameterType2 p2, ParameterType3 p3, ParameterType4 p4)
    {}
};

class DoSomeStuff : public UndoableCommand< int ,double, std::string , int>
{
public:
    DoSomeStuff(int p1, double p2, std::string p3, int p4)
        :UndoableCommand(p1,p2,p3,p4)
    {}
};

class CommandFactory
{
public:
    CommandFactory()
    {}

    template <class CommandType, typename P1, typename P2, typename P3, typename P4> 
    void createCommand( std::string& description,P1 p1, P2 p2, P3 p3, P4 p4)
    {
        UndoableCommand<P1,P2,P3,P4> * cmdPtr = new CommandType(p1, p2, p3, p4);

    }
 };

Used as such

CommandFactory fact;
fact.createCommand<DoSomeStuff>(std::string("description"),1,2.0,std::string("3"),4);

其他提示

You don't need something special here, your approach mCommandFactory.createCommand<DoSomeStuff>(...); shall work. Compiler will automatically deduct types of given arguments from function call expression and instantiate createCommand<> template correctly.

Yes you can replace it with something simpler. Have you considered std::bind?

Once you use change it to use <function>, your DoSomeStuff class will just be a struct that holds a pair of std::functions.

You can make typedefs of Parameter types to Commandtype class, and thus resolve the parameter types inside createCommand function without explicitly addign them as template parameters. To make that happen, you could make typedefs of template parameters passed to UndoableCommand inside that class.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top