mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-10-29 11:05:43 +00:00
92 lines
2.0 KiB
C++
92 lines
2.0 KiB
C++
|
#ifndef LLARP_UTIL_MEMFN
|
||
|
#define LLARP_UTIL_MEMFN
|
||
|
|
||
|
#include <util/memfn_traits.hpp>
|
||
|
#include <util/object.hpp>
|
||
|
#include <util/traits.hpp>
|
||
|
|
||
|
#include <functional>
|
||
|
#include <utility>
|
||
|
|
||
|
namespace llarp
|
||
|
{
|
||
|
namespace util
|
||
|
{
|
||
|
template < typename Obj >
|
||
|
struct MemFnDereference
|
||
|
{
|
||
|
// clang-format off
|
||
|
static inline Obj& derefImp(Obj& obj, std::false_type)
|
||
|
{
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
template < typename Type >
|
||
|
static inline Obj& derefImp(Type& obj, std::true_type)
|
||
|
{
|
||
|
return *obj;
|
||
|
}
|
||
|
|
||
|
template < typename Type >
|
||
|
static inline Obj& derefImp(const Type& obj, std::true_type)
|
||
|
{
|
||
|
return *obj;
|
||
|
}
|
||
|
|
||
|
template < typename Type >
|
||
|
static inline Obj& deref(Type& obj)
|
||
|
{
|
||
|
return derefImp(obj, traits::is_pointy< Type >());
|
||
|
}
|
||
|
|
||
|
template < typename Type >
|
||
|
static inline Obj& deref(const Type& obj)
|
||
|
{
|
||
|
return derefImp(obj, traits::is_pointy< Type >());
|
||
|
}
|
||
|
// clang-format on
|
||
|
};
|
||
|
|
||
|
template < typename Prototype, typename Instance >
|
||
|
class MemFn
|
||
|
{
|
||
|
using traits = MemFnTraits< Prototype >;
|
||
|
|
||
|
static_assert(traits::IsMemFn, "");
|
||
|
|
||
|
public:
|
||
|
using result_type = typename traits::result_type;
|
||
|
|
||
|
private:
|
||
|
Prototype m_func;
|
||
|
object::Proxy< Instance > m_instance;
|
||
|
|
||
|
using Deref = MemFnDereference< typename traits::class_type >;
|
||
|
|
||
|
public:
|
||
|
MemFn(Prototype prototype, const Instance& instance)
|
||
|
: m_func(prototype), m_instance(instance)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template < typename... Args >
|
||
|
result_type
|
||
|
operator()(Args&&... args) const
|
||
|
{
|
||
|
return (Deref::deref(m_instance.value())
|
||
|
.*m_func)(std::forward< Args >(args)...);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template < typename Prototype, typename Instance >
|
||
|
MemFn< Prototype, Instance >
|
||
|
memFn(Prototype prototype, const Instance& instance)
|
||
|
{
|
||
|
return MemFn< Prototype, Instance >(prototype, instance);
|
||
|
}
|
||
|
|
||
|
} // namespace util
|
||
|
} // namespace llarp
|
||
|
|
||
|
#endif
|