'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 |
