0

すでにここで同様の質問をしましたが、質問の定式化が不十分で例が悪かったため、希望する答えが得られませんでした。だから私はそれに別のショットを与えます、うまくいけばより良い説明とより良いコードで。

以下のコードは不要な詳細が削除されていますが、機能します。可能であれば、テンプレート化された関数呼び出しを単純化するために、テンプレート引数の推定を使用したいと思います。

コマンドを作成するファクトリがあります。コマンドを作成するには、次のような呼び出しを使用します。

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

ご想像のとおり、parameter1のタイプはParameterType1などです。

ここで、コマンドの定義-DoSomeStuff-自体を見ると:

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*/ 
    };

ご覧のとおり、ParameterTypeN情報はすでにDoSomeStuff宣言内にあります。

上記のcreateCommand呼び出しをもっと単純なものに置き換えることがどういうわけか可能かどうか疑問に思いました:

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

CommandFactoryコードは次のとおりです。

    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)();            
        }

基本的に重要なのは、CommandFactory内の複雑さを移動して、「クライアントコード」(createCommandの呼び出し)をできるだけ単純かつ短く保つことです。

何か案は ?

4

4 に答える 4

1

質問を正しく理解しているかどうかはわかりませんが、これでうまくいくはずです。

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);

    }
 };

そのまま使用

CommandFactory fact;
fact.createCommand<DoSomeStuff>(std::string("description"),1,2.0,std::string("3"),4);
于 2012-08-20T14:52:31.333 に答える
1

ここでは特別なものは必要ありません。あなたのアプローチmCommandFactory.createCommand<DoSomeStuff>(...);はうまくいくでしょう。コンパイラは、関数呼び出し式から指定された引数のタイプを自動的に差し引き、createCommand<>テンプレートを正しくインスタンス化します。

于 2012-08-20T16:33:30.060 に答える
0

パラメータタイプのtypedefをCommandtypeクラスに作成できるため、テンプレートパラメータとして明示的に追加しなくても、createCommand関数内でパラメータタイプを解決できます。これを実現するには、そのクラス内のUndoableCommandに渡されるテンプレートパラメーターのtypedefを作成できます。

于 2012-08-18T19:21:31.240 に答える
0

はい、もっと簡単なものに置き換えることができます。考えたことはありstd::bindますか?

を使用するように変更すると<function>、DoSomeStuffクラスはstd::functionsのペアを保持する構造体になります。

于 2012-08-15T16:08:34.467 に答える