-
Notifications
You must be signed in to change notification settings - Fork 3
Open
Labels
questionFurther information is requestedFurther information is requested
Description
#include <iostream>
#include <memory>
#include <concepts>
#include <functional>
struct Object
{
void Method(const char *str)
{
std::cout << "Object::Method(" << str << ")" << std::endl;
}
};
// For diagnostics
template <typename M>
struct PointerType {
// template <typename C, typename T>
// static T get_member_type(T C::*v);
template <typename TClass, typename TReturn, typename TArg>
static TClass get_class_type(TReturn (TClass::*func)(TArg));
template <typename TClass, typename TReturn, typename TArg>
static TReturn get_return_type(TReturn (TClass::*func)(TArg));
template <typename TClass, typename TReturn, typename...TArg>
static std::tuple<TArg...> get_argument_types(TReturn (TClass::*func)(TArg...));
typedef decltype(get_class_type(static_cast<M>(nullptr))) class_type;
typedef decltype(get_return_type(static_cast<M>(nullptr))) return_type;
typedef decltype(get_argument_types(static_cast<M>(nullptr))) argument_types;
};
template <auto method>
class Delegate
{
using TClass = typename PointerType<decltype(method)>::class_type;
using TReturnType = typename PointerType<decltype(method)>::return_type;
using TArgsTuple = typename PointerType<decltype(method)>::argument_types;
std::shared_ptr<TClass> object;
public:
Delegate(std::shared_ptr<TClass> object) : object(std::move(object)) { }
template<typename ...TArgs>
requires std::same_as<TArgsTuple, std::tuple<TArgs...>>
TReturnType operator()(TArgs... args)
{
return (*object.*method)(std::forward<decltype(args)>(args)...);
}
};
auto x = [](const char *str)
{
std::cout << "Setter::Set(" << str << ")" << std::endl;
};
struct Setter : std::enable_shared_from_this<Setter>
{
void Set(const char *str)
{
std::cout << "Setter::Set(" << str << ")" << std::endl;
}
};
struct SetterExtender
{
std::shared_ptr<Setter> setter = std::make_shared<Setter>();
Delegate<&Setter::Set> Set = setter;
};
// template<typename T>
void call(auto&& delegate)
{
delegate("calling delegate passed to funciton");
}
int main()
{
Delegate<&Object::Method> x(std::make_shared<Object>());
x("call from main");
SetterExtender se1;
se1.Set("call from main 1");
call(se1.Set);
call([&](const char *str){ se1.Set(str); });
std::cout << typeid(PointerType<decltype(&Object::Method)>::class_type).name() << std::endl;
std::cout << typeid(PointerType<decltype(&Object::Method)>::return_type).name() << std::endl;
std::cout << typeid(PointerType<decltype(&Object::Method)>::argument_types).name() << std::endl;
}
https://godbolt.org/z/a4v1n6GK8
It is possible to pass a pointer to the function into the template.
Maybe we can make it useful somehow?
What if instead of
Delegate<void(const char *)> memberMethod(std::make_shared<Object>(), &Object::Method);We could write something like this:
Delegate<&Object::Method> memberMethod(std::make_shared<Object>());
Metadata
Metadata
Assignees
Labels
questionFurther information is requestedFurther information is requested