2

そこで、最近、c ++ 11の可変個引数テンプレートを使用してデリゲートシステムを構築しました。これは、魅力として機能します。

ただし、システムでは、関数への引数を作成時に(必要に応じて)指定しましたが、呼び出し時に(可変の)数の引数を渡すこともできるようにしたいと思います。これを実現するために、コードをやり直しましたが、ここで問題が発生します。

error: parameter packs must be at the end of the parameter list
sorry, unimplemented: cannot expand ‘Arguments ...’ into a fixed-length argument list
error: type/value mismatch at argument 1 in template parameter list for ‘template<<declaration error>, class ... Params> class FunctionDelegate’

...そして今後さらに多くのことが起こるので、これが問題を引き起こしたスニペットです。

template<typename... Params> 
class Runnable
{
    public:
        virtual void invoke(tuple<Params...> params) = 0;
        virtual ~Runnable() 
        {
        }
};

これは、私の2つのデリゲート(FunctionDelegateとObjectDelegate)の親クラスです。これは以前はテンプレート化されていないクラスでした(invokeは引数を取らなかったため)が、可変個引数のテンプレートリストがあるため、サブクラスも変更する必要があり(明らかに)、別の可変個引数を追加しましたそれらへのテンプレート;

template<typename... Arguments, typename... Params>
class FunctionDelegate : public Runnable<Params...>
{
    public:
        typedef void (*FunctionType)(Arguments..., Params...);

        FunctionDelegate(FunctionType function, tuple<Arguments...> args)
            : function(function), args(args)
        {
        }

        void invoke(tuple<Params...> params) 
        {
            callFunction(typename gens<sizeof...(Arguments)>::type(), params, typename gens<sizeof...(Params)>::type());
        }
    private:
        template<int... S, int... R>
        void callFunction(seq<S...>, tuple<Params...> params, seq<R...>)
        {
            function(get<S>(args)..., get<R>(params)...);
        }
    private:
        FunctionType function;
        tuple<Arguments...> args;
};

ただし、これは許可されていないようです。少なくとも、私が思うにそうです。

  1. 2つの可変個引数テンプレートリストを持つことは許可されていますか?
  2. コンパイラにヒントを与える方法はありますか?それについては、どのリストに行きますか?(つまり、コンストラクターで使用されるものは引数に送られ、残りはParamsに送られます)。
  3. これを行う方法がない場合(2つの可変個引数テンプレートリストを使用)、同じ可変個引数リストで1つの引数とパラメーターを使用し、コンストラクターへの引数を使用してそれを単純に分割することはできませんか?
  4. 私が試みていることを達成する他の方法はありますか?(単純な古い、型チェックされていない可変個引数パラメーターの受け渡しを使用する場合を除く)。

ヘルプや洞察は大歓迎です。

4

2 に答える 2

5

いいえ、そのようなコードは使用できません。たとえば、以下を使用できます

template<typename... Params>
class FunctionDelegate;

また

template<typename Arguments, typename Params>
class FunctionDelegate;

Xeoが示唆するように。

template<typename... Arguments, typename... Params>
class FunctionDelegate<tuple<Arguments...>, tuple<Params...>> : 
public Runnable<Params...> { // };
于 2013-03-05T11:38:21.843 に答える
4

最初の2つの質問(答えは「いいえ」と「いいえ」)に関して、C++11標準の14.1/11項は次のように指定しています。

クラステンプレートまたはエイリアステンプレートのtemplate-parameterにデフォルトのtemplate-argumentがある場合、後続の各template-parameterには、デフォルトのtemplate-argumentが提供されるか、テンプレートパラメーターパックである必要があります。プライマリクラステンプレートまたはエイリアステンプレートのテンプレートパラメータがテンプレートパラメータパックである場合、それが最後のテンプレートパラメータになります。関数テンプレートのテンプレートパラメータパックの後に、そのテンプレートパラメータを推定できるか、デフォルトの引数(14.8.2)がない限り、別のテンプレートパラメータを続けてはなりません。[ 例:

template<class T1 = int, class T2> class B; // error
// U cannot be deduced or specified
template<class... T, class... U> void f() { }
template<class... T, class U> void g() { }

—例を終了]

あなたの例は明らかに太字の文に違反しています。これは、(プライマリ)クラステンプレートに複数のテンプレート引数パックを含めることを禁止しています。

于 2013-03-05T11:35:02.030 に答える