c ++ boost :: lambda :: phoenixのret等価
-
01-10-2019 - |
質問
ブーストラムダでは、推定された返品タイプを使用して上書きできます ret<T>
レンプレート。フェニックスで同等のものを探してみましたが、それを見つけることができませんでした。
フェニックスに同等のものはありますか?私は自分で交換する方法を知っていますが、むしろそうではありません。ありがとうございました
解決
書き換え:最初の答えのポイントを逃しました(遅かった)、もう一度やり直してみましょう。
初めてあなたのポイントを逃すかもしれない私のような人々のためにいくつかの博覧会を与えましょう。 boost :: lambdaでは、オペレーター式でユーザー定義のタイプを使用する場合、ret <> functionを使用して戻り型控除をオーバーライドする必要があります。これは、ラムダのリターンタイプ控除システムがネイティブ(および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
しかし、フェニックスでは、ヒントは必要ありません(リテラルと非コンスト一時的な一時的なものは、フェニックスの引数リストに表示されないことに注意してください):
using namespace boost::phoenix;
add_t i(38), j(4);
(_1 + _2)(i, j); // JUST FINE
リターンタイプ控除システムは完全に異なり、フェニックスでははるかに自然です。従来のセマンティクスを使用するオペレーターの返品タイプを適切に推定します。具体的には、リターンタイプは、オペランドの1つのタイプと一致するか、引数タイプの1つへの参照、ポインター、またはconstポインター、またはそれらのタイプの1つのSTLコンテナ/コンテナイテレーターである必要があります。フェニックスのリターンタイプ控除の素晴らしい記事があります type_deduction.hppヘッダー 詳細については。
だから今、私はあなたの質問を読んでいます、そして、フェニックスで非伝統的なオペレーターのセマンティクスをどのように処理することができますか?
次の奇妙なペアのペアを例として考えてみましょう
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
しかし、フェニックスはこのオペレーターに対処することはできません(責任はありますか?)リターンタイプは議論に関連しておらず、フェニックスのリターンタイプを直接示す方法はありません。このようなオペレーターを使用する正当な理由がある場合、ケースをタイプ控除システムに追加することができますが、Type_Deduction.hppをハッキングしたり、Phoenixの大部分を分岐したりせずにこれを行う方法を見ることができません。
あるいは、特定のオペレーターのリターンタイプをオーバーライドするための少しハッキングを見つけました。結果として_手術 ブースト/スピリット/ホーム/フェニックス/オペレーター/arithmetic.hppのテンプレート構造(39〜56行のstructタイプのリスト、ブースト1.43)は、インスタンス化されたときにタイプ控除を実行し、結果を保存します。したがって、必要なのは、問題操作のためにいくつかのテンプレートの専門化を提供することです。例 (完全な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;
}
これは確かに控えめではありませんが、グローバル以来、ある意味ではより良い意味では優れています。オーバーロードするオペレーターがたくさんある場合、完全な操作セットをマクロにすることができます。
他のヒント
Afaik、これ(または同様のもの)はフェニックスではサポートされていません。ただし、ユースケースを説明した場合、私は助けることができるかもしれません。