2

ネストされた可変個引数クラス テンプレートを持つ可変個引数クラス テンプレートがあります。外側のクラス テンプレートには、任意の数の引数を受け入れ、タイプ inner のオブジェクトを返す関数テンプレートがあります。私の問題は、関数に受け入れられた型がネストされたメンバーであることを保証しながら、外部型のバリアントに関係なく、それらの内部型の任意の数の任意のバリエーション (および内部型のみ) を受け入れる完全に別個の関数を作成することですその外部クラス テンプレートのみ。私がそれを適切に説明したかどうかはわかりません...これが基本的に私が取り組んでいるものです:

template<typename... ArgsOuter> class Outer {
    typedef Outer<ArgsOuter...> outer_t;

    template<typename... ArgsInner> class Inner {
        //static const outer_t* outer;
        typedef outer_t outer;

        Inner(const ArgsInner&... args_inner) {
            //do stuff
        }
    };

    /*
      What's passed in here will be related to and will be a subset of
      the types used to define the Outer class, but I'm not really
      concerned about checking what's being passed in right now.
    */
    template<typename... ArgsFunc>
    make_inner(ArgsFunc... args_func) {
        return Inner<ArgsFunc...> (args_func...);
    }
};

struct ThingA : Outer<int, int, float> {
};

struct ThingB : Outer<int, string, int> {
};

struct ThingC : Outer<string, string, int, int> {
};

//struct ThingN : Outer<random types...> {}

//...meanwhile, over at main...

ThingA tA;
ThingB tB;
ThingC tC;

auto tA_inner = tA.make_inner(1, 1.1);
auto tB_inner = tB.make_inner(2, "foo");
auto tC_inner = tC.make_inner("bar", 2, "foobar");

//mystery_func() is the function I'm not sure how to define.
auto meatloaf = mystery_func(tA_inner, tB_inner, tC_inner);

このための SFINAE または variadic 関数テンプレート (またはその他の) ソリューションを持っている人はいますか?

4

2 に答える 2

2

これは実際には不可能かもしれないと思います。あなたが望んでいるように見えるのは、次のようなことをする能力です:

template < typename ... Args1, typename ... Args2, typename ... Args3>
?? mystery_func(Inner<Args1...>,Inner<Args2...>,Inner<Args3...>);

私はあなたがそれを行うことができるとは思わない. できれば、あなたの答えがあります。

それができるとは思えないので、代わりに 3 つの異なる型を取り、SFINAE を使用してそれらが Inner<> であることをテストするだけです。これは、基本的な is_a メタ関数を使用するのと同じくらい簡単です。

template < typename T > is_inner : boost::mpl::false_ {};
template < typename ... Pack > is_inner< Inner<Pack...> > : boost::mpl::true_ {};
于 2010-12-10T22:23:41.533 に答える
1

ええと、私は自分自身の質問に答えるつもりはありませんでしたが、ここ数日間、これを理解するのに十分なだけ頭を壁にぶつけたと思います...そして確かに途中でいくつかの新しいことを学びました(そこに苦情はありません)。少し醜いアヒルの子 (SFINAE + 型特性メタ関数 + 可変個引数関数テンプレート) ですが、いくつかの簡単なテストを実行したところ、期待どおりに動作するようです。

//Use SFINAE to limit the types accepted
template<typename A, typename Result>
struct require_1_type { };

//Limit to Outer class
template<typename... ArgsA, typename Result>
struct require_1_type<Outer<ArgsA...>, Result> {
    typedef Result type;
};

//Zero argument, base case for variadic function template.
void mystery_func() {}

//Recursive portion of variadic function template.
template<template<typename...> class First, typename... ArgsA, typename... Others>
typename std::enable_if<
    std::is_same<
        First<ArgsA...>
        , typename require_1_type<
            typename First<ArgsA...>::outer_t
            , typename First<ArgsA...>::outer_t::template Inner<ArgsA...>
        >::type
    >::value
    , some_lib::list<First<ArgsA...>, Others...>
>::type
mystery_func (First<ArgsA...> first, Others... others) {
    mystery_func(others...);
    return some_lib::make_list(first, others...);
}

私の目標は、渡されるタイプを、アウターのバリエーションのインナーのバリエーションに制限することでした。これは私が探していたものだと思います。少なくともそのように見えます。

これがどのように機能するかについての私の理解は次のとおりです。必要に応じて修正してください。

一連のInnerオブジェクトが渡されます。各オブジェクトには、その型Innerを参照する typedef があります。Outerパラメーター パックから1 つのオブジェクトを取り除きInner、その型を参照する typedef をチェックしてOuter、期待される型と一致することを確認しOuterます。一致する場合は、Inner渡された最初のオブジェクトで使用されているパラメーター パックを取得し、最初の によって参照される typedefInnerを介して参照するテンプレートにパックを渡します。次に、これら 2 つの を相互にチェックして、それらが同じであることを確認します。そうである場合、その特定の関数テンプレートのインスタンス化が有効になります。OuterInnerInner

可変引数関数テンプレート自体は、単純に再帰的に自身を呼び出します。これにより、パラメーター パック内のすべてのオブジェクトに対して同じチェックが実行され、引数がなくなるまで、空のバージョンの関数が呼び出されます。最後に、各再帰は、(この場合は) オブジェクトをリストにまとめる関数を呼び出します。

確信が持てないことの 1 つは、コンパイラが make_list へのすべての呼び出しを最適化しているかどうかです。ただし、最初の呼び出しによって行われる最後の呼び出しとmystery_func()、意図的な戻り値を持つ唯一の呼び出しを除きます。 .

とにかく、改善、コメント、簡素化は大歓迎です。

于 2010-12-14T21:47:47.240 に答える