39

折り畳みに関するC++17 の論文(およびcppreferenceに関するもの) を見てみると、なぜ演算子のみで動作するように選択されたのかについて混乱していますか? 一見すると、 の要素の間にトークンを(... + args)押し込むだけで簡単に拡張できるように見えますが、これが素晴らしい決定であるとは確信が持てません。 +args

バイナリ ラムダ式が同様に機能し、上記の後者と同じ展開ができないのはなぜですか? 任意の callable をサポートせずに折り畳み構文が言語に追加されることは私には不快です。


更新:min()これは、clangを使用した可変引数関数で機能します

template <typename T>
struct MinWrapper {
    const T& obj;
};

template <typename T, typename U, typename V=std::common_type_t<T,U>>
constexpr MinWrapper<V> operator%(
        const MinWrapper<T>& lhs, const MinWrapper<U>& rhs) {
    return {lhs.obj < rhs.obj ? lhs.obj : rhs.obj};
}


template <typename... Ts>
constexpr auto min(Ts&&... args) {
    return (MinWrapper<Ts>{args} % ...).obj;
}
4

2 に答える 2

5

まず第一に、私が書いたものがclangで機能することをうれしく思います(あなたの更新は、私が言及した4つのステップのうち3つを実装していることがわかります)。これを書く前に、この方法について私と議論したこのテクニックについては、Nick Athanasiouの功績を 称えなければなりません。

私が今これに言及する理由は、彼がこのようなものを実装するライブラリを(ブーストライブラリインキュベーターで)リリースと知らされたからです。関連ドキュメントはこちらにあります。これは最初のアイデア (ここで使用するもの) のようで、次のようなコードが許可されています。

(Op<Max>(args) + ...); // Op is a function producing the custom fold type

遅延評価とステートフルな演算子を支持して除外されました (またはまだ含まれていないか、確かなことはわかりません)。

于 2016-04-07T16:50:49.963 に答える
5

これは素晴らしい論文であり、素晴らしい言語機能です。私が特に好きではない標準的な話をスキップする場合は、回避策を提案したいと思います。私は C++17 コンパイラ (またはタイム マシン) を持っていないので、私の答えは、言語ステータスをそのままにして、任意の関数でフォールド式を提供するソリューションであると私が信じていることの概要のみです。

1. 型ラッパー (軽量のもの) を定義する

template<typename T>
struct wp {
    T const& val; 
    // yes there should be constructors
};

2.パックをラップパックに変える機械

template<typename Op, typename Ts...>
using wrapped_pack = make_wrapped<Op, Ts..>

3.組み込み演算子をオーバーロードしますwp<T>

template<typename T, typename U>
ret_val operator+(wp<T> const& lhs, wp<U> const& rhs) {...}

4.折り込み式のラップパックを使用する

argsこれには、折り畳みの がラップされた引数に変換される追加のレイヤーが必要になります


上記の明らかな欠点は、一意性 (またはスケーラビリティ) が保証されないことです。カスタム callable を持つすべての折り畳みは、組み込みの演算子のオーバーロードを消費します。

遭遇する表現に基づいて型を変えるためのハックが必要ですが、私は思考実験に深く飛び込みたくありません (例えばOp、ラッパーの型での型を使用すると、すでにスケーリングするためのスペースがはるかに多くなります)の中へ)。

于 2015-01-02T20:11:47.690 に答える