0

実際、すべての回答は素晴らしく、有益ですが、私の問題を解決するものではありません。回答してくれた非常に親切な人々のせいではないと思いますが、代わりに、私の質問の言い回しがまずかったです。したがって、より関連性の高いコード例を含む完全に新しい質問をここに投稿することにしました: Mixing Command pattern , Factory pattern and templates all together .... 気になる人がいたら...

元の質問:

私がやりたいことをすることは可能だとは思いませんが、念のためお願いします....

ファクトリを使用して作成したい一連のテンプレート クラスがあります。ファクトリを使用する理由は、ファクトリには、そのファクトリを通じて作成されたすべてのクラスを初期化するために使用されるデータ メンバーがあるためです。

たとえば、このクラスを考えてみましょう:

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 operator()(P1 p1, P2 p2, P3 p3, P4 p4)」という行は、次のエラーを生成します。

エラー C2065: 'P1': 宣言されていない識別子

"DoSomething" のようなクラスには宣言が 1 つしかないため (DoSomething は常に < int, float > を使用します)、テンプレート引数推定を使用して、次のような構文になると考えました。

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

しかし、それは冗長であり、あまりエレガントではありません...

4

2 に答える 2

1

まず第一に、ここのように定義されます

class DoSomething : public UndoableCommand< int, float >

DoSomethingは型であり、テンプレートではないため、このような関数では使用できません。

考えてみましょう、あなたは次DoSomethingのように定義しました

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

次に、関数には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);
}
于 2012-08-14T16:04:53.523 に答える
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でコンパイルされます。

于 2012-08-14T15:46:26.690 に答える