10

数字のリストがあります。

リストをフィルタリングして、正の数のみを保持しようとしています。

ラムダを引数として渡すことでそれをやろうとしています。

なぜ関数の不一致エラーが発生するのだろうか。

#include <vector>
#include <algorithm>
#include <functional>

template<typename T>
std::vector<T> keep(
        const std::vector<T> &original,
        std::function<bool(const T&)> useful)
{
    std::vector<T> out;
    for(T item:original)
    {
        if(useful(item))
            out.push_back(item);
    }
    return out;
}

int main()
{
    std::vector<int> a={4,6,2,-5,3,-8,13,-11,27};
    a=keep(a,[](const int& x)->bool{return x>0;});
    for(int y:a)
    {
        std::cout<<y<<std::endl;
    }
    return 0;
}

そして、これはエラーメッセージです:

error: no matching function for call to ‘keep(std::vector<int>&, main()::<lambda(const int&)>)’
     a=keep(a,[](const int& x)->bool{return x>0;});
                                                 ^
4

1 に答える 1

15

keep関数を次のように変更します

template<typename T, typename Func>
std::vector<T> keep(const std::vector<T> &original,
                    Func useful)
{
    // code as usual
}

実例

usefulこれは、次のいずれかであるという引数で機能します。

ドキュメントから:

ラムダ式は、クロージャー型として知られる、一意の名前のない非共用体非集約型の名前のない prvalue 一時オブジェクトを構築します。

これは、同じコードを持つ 2 つのラムダが、2 つの異なる型付きオブジェクトを生成することを意味します。

auto f1 = [](int) { return true; };
auto f2 = [](int) { return false; };
f2 = f1;                               // error: no viable '='

ただし、これらは両方とも対応するstd::function型に暗黙的に変換可能です。

std::function<bool(int)> fn = f1;
fn = f2;

しかし、なぜあなたの場合はうまくいかないのですか?これは、テンプレート タイプの推定によるものです。keepに変更

template<typename T>
std::vector<T> keep(const std::vector<T> &original,
                    std::function<bool(const int &)> useful)
// no type deduction for std::function's template, explicitly mentioned

呼び出し元サイトでキャストせずに例をコンパイルします。

std::function<T>ただし、テンプレートの型推定では変換が考慮されないため、それを照合しようとしてもうまくいきません。テンプレート引数推定は、正確な型の一致を探します。この段階では、暗黙的な変換は重要ではありません。Atomic_alarmコメントstd::functionとして、一致するものに明示的にキャストする必要があります。ジョセフがテンプレートを使用してラムダを std::function に変換する方法で言っているように:

std::function<T>テンプレートの型推定は、ラムダ関数の型を、この場合にはできない型に一致させようとします- これらの型は同じではありません。テンプレートの型推定では、型間の変換は考慮されません。

代替ソリューションでは、次のようなことが起こります。

auto f = [](int i) { return (i >= 0); }

ここの型はfそうではありませんstd::functionが、上記のテンプレート パラメーターのように推定される名前のない型Funcです。

それでもやりたい場合は、テンプレートの間接化を追加して行うこの回答std::functionを参照してください。関連する詳細については、この回答この投稿を参照してください。

于 2015-09-29T09:34:43.640 に答える