web-dev-qa-db-ja.com

lambdaをstd :: functionとして渡すことができません

この例に注目しましょう:

template<typename T>
class C{
    public:
    void func(std::vector<T>& vec, std::function<T( const std::string)>& f){
        //Do Something
    }
};

そして今、私はしようとしています:

std::vector<int> vec;
auto lambda = [](const std::string& s) { return std::stoi(s); };
C<int> c;
c.func(vec, lambda);

エラーの原因:

no matching function for call to ‘C<int>::func(std::vector<int, std::allocator<int> >&, main()::<lambda(const string&)>&)’
     ref.parse(vec, lambda);

何がうまくいかないのか、またstd :: bindでそれを実装する方法を説明してください。

41
Gilgamesz

ラムダ関数が_std::function<...>_ではないためです。のタイプ

_auto lambda = [](const std::string& s) { return std::stoi(s); };
_

std::function<int(const std::string&)>ではなく、_std::function_に割り当てることができる未指定のものです。メソッドを呼び出すと、コンパイラは型が一致しないと文句を言います。変換とは、非const参照にバインドできない一時的なものを作成することを意味するためです。

通常の関数を渡すとエラーが発生するため、これはラムダ関数に固有ではありません。これも機能しません:

_int f(std::string const&) {return 0;}

int main()
{
    std::vector<int> vec;
    C<int> c;
    c.func(vec, f);
}
_

ラムダを_std::function_に割り当てることができます

_std::function<int(const std::string&)> lambda = [](const std::string& s) { return std::stoi(s); };
_

、メンバー関数を変更して、値またはconst参照によって関数を取得するか、関数パラメーターをテンプレート型にします。ラムダまたは通常の関数ポインターを渡す場合、これはわずかに効率的ですが、個人的には、シグネチャの表現力のある_std::function_型が好きです。

_template<typename T>
class C{
    public:
    void func(std::vector<T>& vec, std::function<T( const std::string)> f){
        //Do Something
    }

    // or
    void func(std::vector<T>& vec, std::function<T( const std::string)> const& f){
        //Do Something
    }

    // or
    template<typename F> func(std::vector<T>& vec, F f){
        //Do Something
    }
};
_
30
Jens

引数(std::function)は参照です。そのはず:

void func(std::vector<T>& vec, std::function<T(const std::string&)> f)
                                                                ^  ^
                                                                   |
                                                                   f not a reference

そのため、引数をパラメーター型に変換できます。

また、関数のタイプが一致する必要があります。つまり文字列参照を受け入れる必要があります。

22
bolov