0

I am trying to compile the following code

#include <iostream>
#include <string>

struct Bar{  };

struct Foo {
    
    template<class T>
    void setCallback(std::function<void(T)> f) {
    } 
};

int main() {
    Foo foo;
    foo.setCallback<Bar>([](Bar v) { }); // <--- compilation ok
    foo.setCallback([](Bar v) { });      // <--- compilation error. How to fix?
}

But the result of the compilation is fail:

main.cpp:16:9: error: no matching member function for call to 'setCallback'
    foo.setCallback([](Bar v) { });      // <--- compilation error
    ~~~~^~~~~~~~~~~
main.cpp:9:10: note: candidate template ignored: could not match 'std::function<void (T)>' against '(lambda at main.cpp:16:21)'
    void setCallback(std::function<void(T)> f) {
         ^
1 error generated.

How to tell to the compiler to deduct argument type of the lambda from lambda passing to the function?

UPDATE: I found solution for my problem:

template<typename F, typename R, typename E>
static E ArgHelper(R(F::*)(E) const);

template<typename F, typename R, typename E>
static E ArgHelper(R(F::*)(E));

struct Foo {

    template<class T>
    void setFunction(T func) {
        using Arg = decltype(ArgHelper(&T::operator()) );
        //use Arg
    }
};

// use:
foo.setFunction([](Bar b){
    //...
});

Working example

chabapok
  • 921
  • 1
  • 8
  • 14
  • Why does the function take a `std::function` parameter specifically anyway if it is already templated? It can just take `T f` as function parameter and then it will work with any callable. – user17732522 Aug 10 '22 at 07:33
  • Just replace the parameter `std::function` with `T`. See [demo](https://onlinegdb.com/8AMPkIJO0Q) – Jason Aug 10 '22 at 07:35
  • If you're on [tag:c++17], you can exploit CTAD and do: `foo.setCallback(std::function { [](Bar) {} });`. – paolo Aug 10 '22 at 07:37
  • *"I needs the argument type `T` inside my function, so I can't replace `std::function` to `T`"*. You can, you just need a type_traits to extract first parameter type (so generic lambda won't work) ([unpacking-arguments-of-a-functional-parameter-to-a-c-template-class](https://stackoverflow.com/questions/24948277/unpacking-arguments-of-a-functional-parameter-to-a-c-template-class) might help in this regard with `T` or `T::operator()`). – Jarod42 Aug 10 '22 at 08:51

0 Answers0