Search code examples
c++xcodec++20clang++std-function

Problem converting member function pointer to std::function with CRTP


I am trying to pass a bound member function as an std::function while hiding the std::bind_front invocation in a base class. Minimal example:

#include <functional>

static void runIt(std::function<void()> f) { f(); }

template<typename T>
struct Base {
    using PFn = void (T::*)();
    void run(PFn fun) { runIt(std::bind_front(fun, this)); }
};

struct Derived : Base<Derived> {
    void main() { run(&Derived::func); }
    void func() {}
};

Unfortunately, the compiler does not like it:

static void runIt(std::function<void()> f)
No matching function for call to 'runIt' clang(ovl_no_viable_function_in_call)
test.cpp(12, 19): In instantiation of member function 'Base<Derived>::run' requested here
test.cpp(3, 13): Candidate function not viable: no known conversion from 'std::__perfect_forward_impl<std::__bind_front_op, std::__tuple_types<void (Derived::*)(), Base<Derived> *>, std::__tuple_indices<0, 1>>' to 'std::function<void ()>' for 1st argument

What am I missing?


Solution

  • You can't std::invoke(fun, this) since this is of type Base<Derived>* and the function pointer is of type void (Derived::*)() (And Derived is not a base of Base<Derived>, but the other way around).

    Either upcast the pointer to member function or the pointer to the object. Preferably the object pointer:

    runIt(std::bind_front(fun, static_cast<T*>(this)));