1

私は現在、boost::mpl::apply のような式を評価するためのメタ関数を書いています。

template<typename EXPRESSION , typename... ARGS>
using eval = typename eval_impl<EXPRESSION,ARGS...>::result;

ご覧のとおりtypename ::result、エバリュエーターを使用する際の書き込みを避けるために、C++11 テンプレート エイリアスを使用しています。

他の特殊化の中でも、eval_impl(評価メタ関数の実装) には、ユーザーがパラメーター化された式 (メタ関数など) とパラメーターのセットを渡す場合の特殊化があります。つまり、eval指定されたパラメーターのセットでメタ関数を評価するための高次メタ関数として使用します。

その場合、私は次のように専門化を書きました。

template<template<typename...> class F , typename... PLACEHOLDERS , typename... ARGS>
struct eval_impl<F<PLACEHOLDERS...>,ARGS...> : public F<ARGS...> {}

ここでユースケースを考えてみましょう:

template<typename ARG , typename... ARGS> using first_of = ARG;

using call = eval<first_of<_1,_2,_3,_4> , bool,float,char,int>;

ここでは、カスタム メタ関数をテンプレート エイリアスとして定義し、 呼び出し (評価) に使用する一連のパラメーターと共にfirst_ofに渡します。、... は単なるプレースホルダーです。eval_1_2

上記で定義された特殊化のインスタンスを呼び出すことを期待してevalいましたが、そうではありません。また、エイリアス化された型が型自体ではなく、1 つのパラメーターのテンプレートである場合、GCC 4.8.1 は次のように述べています。

エラー: 1 つのテンプレート パラメーターが必要ですが、2 つ指定されました

そのeval_impl専門化のインスタンス化の時点で。

エラーにより、テンプレート エイリアスが部分特殊化のテンプレート テンプレート パラメータに取り込まれず、代わりにエイリアス化された型が一致すると考えられます。

例でわかるように、それは私が望まないことではありません。テンプレート エイリアスを他のメタ関数と一致させる必要があります。それを達成する方法はありますか?

4

1 に答える 1

3

あなたはこの近くです!エイリアスの代わりにクラスを使用するだけです。

template<typename ARG, typename... ARGS>
struct first_of { using type = ARG; };

実際の例を参照してください。

エイリアスを直接使用することはできません。

 first_of<_1,_2,_3,_4>

すぐに に置き換えられますが_1、これは が期待する形式ではありませんeval_impl

通常、上記の形式でテンプレート関数を定義してから、次のような追加のエイリアスを定義するため、これが制限であるとは思いません

template<typename ARG, typename... ARGS>
using first_of_t = typename first_of<ARG, ARGS...>::type;

より簡単に使用できます。したがって、通常は両方を持っています。で前者を使用する必要がありますeval


試行 2.また、プレースホルダーなしでエイリアスを直接使用できることにも注意してください。

template<template<typename...> class F, typename... ARGS>
using alias_eval = F<ARGS...>;

その場合、あなたは言うことができます

using alias_call = alias_eval<first_of_t, bool, float, char, int>;

あなたの最初の試みのように。更新された例を参照してください。しかし、プレースホルダーをより簡単な方法で使用するつもりなので、これは役に立たないと思います。


試行 3.さらに別のオプションは、エイリアスの置換を遅らせることです。

template<template<typename...> class F, typename... PLACEHOLDERS>
struct holder {};

template<typename EXPRESSION, typename... ARGS>
struct holder_eval_impl;

template<template<typename...> class F, typename... PLACEHOLDERS, typename... ARGS>
struct holder_eval_impl<holder<F, PLACEHOLDERS...>, ARGS...> :
    public F<ARGS...> {};

template<typename EXPRESSION, typename... ARGS>
using holder_eval = typename holder_eval_impl<EXPRESSION, ARGS...>::type;

これは意図した構文に非常に近い

using holder_call =
    holder_eval<holder<first_of,_1,_2,_3,_4>, bool, float, char, int>;

特に の短い名前を使用する場合holder。繰り返しますが、ライブの例です。

于 2014-04-07T22:23:01.837 に答える