3

ret<T>ブースト ラムダにより、テンプレートを使用して推定された戻り値の型を上書きできます。フェニックスで同等のものを検索しようとしましたが、見つかりませんでした。

フェニックスに相当するものはありますか?私は自分で交換品を作る方法を知っていますが、むしろしたくありません。ありがとうございました

4

2 に答える 2

8

書き換え: 最初の回答でポイントを逃しました (遅かった)。もう一度やり直させてください。

初めてあなたの要点を見逃すかもしれない私のような人々のために、いくつかの説明をさせてください. boost::lambda では、演算子式でユーザー定義型を使用する場合、ret<> 関数を使用して戻り値の型推論をオーバーライドする必要があります。これは、ラムダの戻り値の型推論システムがネイティブ (および stl? 私は覚えていません) 型のみを直接サポートするためです。簡単な例:

using namespace boost::lambda;

struct add_t{
    add_t(int i) : i(i) {};
    add_t operator+(const add_t& other) const{
        return add_t(i + other.i);
    }
    int i;
};

(_1 + _2)(add_t(38), add_t(4));           // RETURN TYPE DEDUCTION FAILS
ret<add_t>(_1 + _2)(add_t(38), add_t(4)); // OK

ただし、phoenix では、ヒントは必要ありません (リテラルおよび非 const 一時変数は phoenix 引数リストに表示できないことに注意してください)。

using namespace boost::phoenix;

add_t i(38), j(4);
(_1 + _2)(i, j);    // JUST FINE

リターンタイプの控除システムは完全に異なり、フェニックスではより自然です。従来のセマンティクスを使用する演算子の戻り値の型を適切に推測します。具体的には、戻り値の型はオペランドの 1 つの型と一致するか、引数の型の 1 つへの参照、ポインター、または const ポインターであるか、それらの型の 1 つの stl コンテナー/コンテナー反復子である必要があります。詳細については、 type_deduction.hpp ヘッダーにある phoenix の戻り値の型推定に関する優れた記述があります。

だから今、私はあなたの質問を読んでいます。従来とは異なる演算子のセマンティクスをフェニックスでどのように処理できますか?

例として、次の奇妙なタイプのペアを考えてみましょう

struct add_ret_t{
    add_ret_t(int i) : i(i) {};
    int i;
};

struct add_t{
    add_t(int i) : i(i) {};
    add_ret_t operator+(const add_t& other) const{
        return add_ret_t(i + other.i);
    }
    int i;
};

ラムダの場合、これは問題ありません。ret 関数を使用するだけです。

using namespace boost::lambda;

ret<add_ret_t>(_1 + _2)(add_t(38), add_t(4)); // OK

しかし、phoenix はこの演算子を扱うことができません (責められますか?)。なぜなら、戻り値の型は引数とは関係がなく、phoenix では戻り値の型を直接示す方法がないからです。このような演算子を使用する正当な理由がある場合は、型推論システムにケースを追加できますが、type_deduction.hpp をハッキングするか、phoenix のかなりの部分を分岐しない限り、これを行う方法がわかりません。

別の方法として、特定の演算子の戻り値の型をオーバーライドするちょっとしたハックを見つけました。boost/spirit/home/phoenix/operator/arithmetic.hppの result_of_演算テンプレート構造体 (39 ~ 56 行に構造体型がリストされています。boost 1.43) は、インスタンス化されたときに型推定を実行し、結果を格納します。したがって、必要なのは、問題の操作にいくつかのテンプレートの特殊化を提供することだけです。戻り値の型を指定する typedef を 1 つだけ含める必要があります。例 (完全な src のコードパッド):

using namespace boost::phoenix;

namespace boost{ namespace phoenix{

//override add_t addition to give add_ret_t
template <> struct result_of_plus<add_t&, add_t&> { typedef add_ret_t type; };

//override int addition to give char
template <> struct result_of_plus<int&, int&> { typedef char type; };

}}

int main()
{
    add_t i = 1, j = 7;
    std::cout << ((_1 + _2)(i, j)).i << std::endl;

    int k = 51, l = 37;
    std::cout << ((_1 + _2)(k, l)) << std::endl;

    return 0;
}

これは確かに ret の代替品ではありませんが、グローバルであるため、ある意味では優れています。オーバーロードする演算子が多数ある場合は、操作の完全なセットをマクロ化できます。

于 2010-05-26T07:14:47.523 に答える
0

私の知る限り、これ(または同様のもの)はフェニックスではサポートされていません。ただし、ユースケースを説明していただければ、お役に立てるかもしれません。

于 2010-05-24T23:56:21.493 に答える