10

C ++ 11で利用可能な新しい無名関数を使用して、一般的なfold関数を作成しようとしています。これが私が持っているものです。

template<typename T>
T foldl(std::function<T(T,T)> f, T initial, std::vector<T> items) {
    T accum = initial;
    for(typename std::vector<T>::iterator it = items.begin(); it != items.end(); ++it) {
        accum = f(accum, (*it));
    }
    return accum;
}

それを使用する次の試み:

std::vector<int> arr;
arr.assign(8, 2);
foldl([] (int x, int y) -> int { return x * y; }, 1, arr);

エラーが発生します:

main.cpp:44:61: error: no matching function for call to 'foldl(main(int, char**)::<lambda(int, int)>, int, std::vector<int>&)'
main.cpp:44:61: note: candidate is:
main.cpp:20:3: note: template<class T> T foldl(std::function<T(T, T)>, T, std::vector<T>)
main.cpp:20:3: note:   template argument deduction/substitution failed:
main.cpp:44:61: note:   'main(int, char**)::<lambda(int, int)>' is not derived from 'std::function<T(T, T)>'

std::functionを使用することは、のタイプを定義するための正しい方法ではないように思われますf。どうすればこれを修正できますか?

4

3 に答える 3

15

あなたのコードはあまり一般的ではありません。function、、、またはそのようなものを要求する必要はありませんvector。そして一般的に、C ++では、関数は引数リストの最後に配置されます(ラムダは大きくなる可能性があるため、特に重要です)。

したがって、これを次のように書く方が良いでしょう(つまり、より標準的です)。

template<typename Range, typename Accum>
typename Range::value_type foldl(const Range &items, const typename Range::value_type &initial, Accum f)
{
    typename Range::value_type accum = initial;
    for(const auto &val : items) {
        accum = f(accum, val);
    }

    return accum;
}

または、まったく同じことを行うものを使用するstd::accumulateこともできます。

于 2013-03-17T07:31:21.423 に答える
4

このテンプレートが失敗する理由はわかりませんが、関数の代わりにテンプレートパラメーターを使用するように切り替えるstd::function<>と、うまく機能するようです。

template<typename T, typename F>
T foldl(F f, T initial, std::vector<T> items) {
于 2013-03-17T07:25:38.473 に答える
2

単にstd::function最初に変換してからそれを使用すると、次のように機能します。

std::vector<int> arr;
arr.assign(8, 2);
std::function<int(int,int)> f = [] (int x, int y) -> int { return x * y; };
foldl(f, 1, arr);

問題は、ラムダがとは異なるタイプであるということですstd::function。各ラムダは個別のタイプです。ラムダ(および他のすべての関数オブジェクト)はstd::function適切な型パラメーターを使用してに変換可能ですが、コンパイラーは、どのテンプレート引数がT変換可能になるかを認識していません。T( =が機能することはたまたまわかってintいますが、それを理解する一般的な方法はありません。)したがって、コンパイルできません。

于 2013-03-18T00:03:13.450 に答える