lambda als Funktionsparameter



  • Ich habe folgenden code:

    #include <iostream>
    #include <functional>
    using namespace std;
    
    template<typename R, typename A>
    void createAccessor(R(*acc)(A))
    {
    	std::function<R(A)> func = acc;
    }
    
    int main() {
    	createAccessor([](int arg){ return 42; });
    	return 0;
    }
    

    prog.cpp: In function ‘int main()’:
    prog.cpp:12:42: error: no matching function for call to ‘createAccessor(main()::__lambda0)’
    createAccessor([](int arg){ return 42; });

    Wieso kann ich nicht das lambda als Funktionsparameter übergeben?


  • Mod

    Weil ein Lambda kein Funktionszeiger ist. Er lässt sich lediglich in einen Konvertieren (da hier keine captures vorhanden sind), aber das hat keinen Einfluss auf die Deduzierung der Template-Argumente.

    Das hier kompiliert

    void createAccessor( int(*acc)(int) )
    {
        std::function<int(int)> func = acc;
    }
    
    createAccessor([](int arg){ return 42; });
    

    Was du natürlich tun könntest ist vor dem Aufruf explizit casten.



  • Die vollständige Meldung beim g++ 4.8.1 lautet:

    lambda.cpp: In function ‘int main()’:
    lambda.cpp:12:45: error: no matching function for call to ‘createAccessor(main()::__lambda0)’
    createAccessor([](int arg){ return 42; });
    ^
    lambda.cpp:12:45: note: candidate is:
    lambda.cpp:6:6: note: template<class R, class A> void createAccessor(R (*)(A))
    void createAccessor(R(acc)(A))
    ^
    lambda.cpp:6:6: note: template argument deduction/substitution failed:
    lambda.cpp:12:45: note: mismatched types ‘R (
    )(A)’ and ‘main()::__lambda0’
    createAccessor([](int arg){ return 42; });

    Da der Lambdaausdruck kein Funktionspointer ist, sondern nur in einen konvertiert werden kann, geht es nicht automatisch. So gehts:

    #include <iostream>
    #include <functional>
    using namespace std;
    
    template<typename R, typename A>
    void createAccessor(R(*acc)(A))
    {
        std::function<R(A)> func = acc;
    }
    
    int main() {
        int(*acc)(int) = [](int arg){ return 42; };
        createAccessor(acc);
        return 0;
    }
    

    Oder du benutzt gleich std::function als Parameter.


  • Mod

    Oder du benutzt gleich std::function als Parameter.

    👍
    Dann stellt sich allerdings die Frage, warum nicht gleich einfach

    template<typename T>
    void foo( T bar )
    {
        // ... bar(arg)
    }
    


  • manni66 schrieb:

    Oder du benutzt gleich std::function als Parameter.

    Dann funktioniert die Typherleitung aber auch nicht.


  • Mod

    TyRoXx schrieb:

    manni66 schrieb:

    Oder du benutzt gleich std::function als Parameter.

    Dann funktioniert die Typherleitung aber auch nicht.

    Ohne Witz, meine erste Version des Postings oben war "Was ändert das?".

    Ich hasse Denkfehler, ich hasse sie so sehr 😞



  • manni66 schrieb:

    Oder du benutzt gleich std::function als Parameter.

    Das bringt doch aber nichts, da kann ich trotzdem nicht

    createAccessor([](int arg){ return 42; });
    

    aufrufen.
    Oder was meinst du?

    Was ich machen könnte ist folgendes:

    #include <iostream>
    #include <functional>
    using namespace std;
    
    template<typename R, typename A>
    void createAccessor(R(*acc)(A))
    {
        std::function<R(A)> func = acc;
    }
    
    int main() {
        createAccessor<int,int>([](int arg){ return 42; });
        return 0;
    }
    

Anmelden zum Antworten