'Take the address of operator() as a non-type template parameter

I am implementing a delegate class and at the moment I am trying to deduplicate some code that I have. At first I had a Bind function that take an instance(the delegate target object) and the address of the function as a non-type template parameter. The second Bind function would deal with functor like object it would therefore only take the instance. But I figured I could implement the second Bind by calling the first and passing the operator() as a non-type template parameter. But I can't figure out how to accomplish this.

template <typename Ret, typename... Args>
template <auto Callable, typename Instance_T>
void Delegate<Ret(Args...)>::Bind(Instance_T&& instance)
{
// Implementation detail that deals with lvalue and rvalue
}

template <typename Ret, typename... Args>
template <typename Instance_T>
void Delegate<Ret(Args...)>::Bind(Instance_T&& instance)
{
  using Type = std::remove_reference_t<Instance_T>;
  using Functor_Ptr = decltype(&Type::operator());
  constexpr Functor_Ptr function = &Type::operator();
  
  //The template parameter here is what I don't know how to do.
  Bind<&Type::operator()>(std::forward<Instance_T>(instance));
}

//example uses
struct TestStruct
{
  constexpr static int m_staticValue = 42;

  void memberFunction(int& value)
  {
    value = m_staticValue ;
  }

  void operator()(int& value) const
  {
    value = m_staticValue ;
  }

};

Delegate<void(int&)> delegate;
delegate.Bind<&TestStruct::memberFunction>(TestStruct{});
delegate.Bind(TestStruct{});
delegate.Bind([](int& value) { value = TestStruct::m_staticValue; });


Solution 1:[1]

Because nothing is happening around this question: why reinvent the wheel? std::function combined with lambda's does what you want:

#include <functional>
#include <iostream>

struct TestStruct
{
  constexpr static int m_staticValue = 42;

  void memberFunction(int& value) const
  {
    value = 69;
  }

  void operator()(int& value) const
  {
    value = 420;
  }
};

int main() {
    int i{};
    std::function<void(int&)> delegate;

    delegate = [test=TestStruct{}](int& i){ test.memberFunction(i); };
    delegate(i);
    std::cout << i << '\n'; // 69

    delegate = [test=TestStruct{}](int& i){ test(i); };
    delegate(i);
    std::cout << i << '\n'; // 420

    delegate = [](int& i){ i = TestStruct::m_staticValue; };
    delegate(i);
    std::cout << i << '\n'; // 42
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JHBonarius