mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
Delegate support for lambdas and std::functions in general, also supporting const members now [Miodrag Milanovic]
This commit is contained in:
parent
f05e7ffad0
commit
dedf3c9b9d
@ -17,7 +17,7 @@
|
||||
// fatal error if not found
|
||||
//-------------------------------------------------
|
||||
|
||||
delegate_late_bind &device_delegate_helper::bound_object(device_t &search_root)
|
||||
delegate_late_bind &device_delegate_helper::bound_object(device_t &search_root) const
|
||||
{
|
||||
device_t *device = search_root.subdevice(m_device_name);
|
||||
if (device == nullptr)
|
||||
|
@ -30,7 +30,7 @@ protected:
|
||||
device_delegate_helper(const char *devname) : m_device_name(devname) { }
|
||||
|
||||
// internal helpers
|
||||
delegate_late_bind &bound_object(device_t &search_root);
|
||||
delegate_late_bind &bound_object(device_t &search_root) const;
|
||||
static const char *safe_tag(device_t *object);
|
||||
|
||||
// internal state
|
||||
@ -54,20 +54,24 @@ public:
|
||||
device_delegate(const basetype &src) : basetype(src), device_delegate_helper(src.m_device_name) { }
|
||||
device_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), device_delegate_helper(src.m_device_name) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
|
||||
#ifdef USE_STATIC_DELEGATE
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
|
||||
#endif
|
||||
device_delegate(std::function<_Signature> funcptr) : basetype(funcptr), device_delegate_helper(nullptr) { }
|
||||
device_delegate &operator=(const thistype &src) { *static_cast<basetype *>(this) = src; m_device_name = src.m_device_name; return *this; }
|
||||
|
||||
// provide additional constructors that take a device name string
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, (_FunctionClass *)nullptr), device_delegate_helper(devname) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)nullptr), device_delegate_helper(devname) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
|
||||
#ifdef USE_STATIC_DELEGATE
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)nullptr), device_delegate_helper(devname) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)nullptr), device_delegate_helper(devname) { }
|
||||
device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)nullptr), device_delegate_helper(nullptr) { }
|
||||
device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)nullptr), device_delegate_helper(nullptr) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
|
||||
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
|
||||
device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
|
||||
device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
|
||||
#endif
|
||||
|
||||
// and constructors that provide a search root
|
||||
|
@ -79,11 +79,11 @@
|
||||
#define __DELEGATE_H__
|
||||
|
||||
// standard C++ includes
|
||||
#include <exception>
|
||||
#include <cstring>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS
|
||||
@ -134,7 +134,7 @@
|
||||
//**************************************************************************
|
||||
|
||||
// generic function type
|
||||
typedef void (*delegate_generic_function)();
|
||||
using delegate_generic_function = void(*)();
|
||||
|
||||
|
||||
// ======================> generic_class
|
||||
@ -180,9 +180,10 @@ public:
|
||||
template<typename _ClassType, typename _ReturnType, typename... Params>
|
||||
struct delegate_traits
|
||||
{
|
||||
typedef _ReturnType (*static_func_type)(_ClassType *, Params...);
|
||||
typedef _ReturnType (*static_ref_func_type)(_ClassType &, Params...);
|
||||
typedef _ReturnType (_ClassType::*member_func_type)(Params...);
|
||||
using static_func_type = _ReturnType(*)(_ClassType *, Params...);
|
||||
using static_ref_func_type = _ReturnType(*)(_ClassType &, Params...);
|
||||
using member_func_type = _ReturnType(_ClassType::*)(Params...);
|
||||
using const_member_func_type = _ReturnType(_ClassType::*)(Params...) const;
|
||||
};
|
||||
|
||||
|
||||
@ -247,7 +248,7 @@ private:
|
||||
static _ReturnType method_stub(delegate_generic_class *object, Params ... args)
|
||||
{
|
||||
delegate_mfp *_this = reinterpret_cast<delegate_mfp *>(object);
|
||||
typedef _ReturnType (_FunctionClass::*mfptype)(Params...);
|
||||
using mfptype = _ReturnType(_FunctionClass::*)(Params...);
|
||||
mfptype &mfp = *reinterpret_cast<mfptype *>(&_this->m_rawdata);
|
||||
return (reinterpret_cast<_FunctionClass *>(_this->m_realobject)->*mfp)(std::forward<Params>(args)...);
|
||||
}
|
||||
@ -256,7 +257,7 @@ private:
|
||||
// helper to convert a function of a given type to a generic function, forcing template
|
||||
// instantiation to match the source type
|
||||
template <typename _SourceType>
|
||||
delegate_generic_function make_generic(_SourceType funcptr)
|
||||
static delegate_generic_function make_generic(_SourceType funcptr)
|
||||
{
|
||||
return reinterpret_cast<delegate_generic_function>(funcptr);
|
||||
}
|
||||
@ -310,7 +311,7 @@ public:
|
||||
bool isnull() const { return (m_function == 0 && m_this_delta==0); }
|
||||
|
||||
// getters
|
||||
delegate_generic_class *real_object(delegate_generic_class *original) const { return original; }
|
||||
static delegate_generic_class *real_object(delegate_generic_class *original) { return original; }
|
||||
|
||||
// binding helper
|
||||
template<typename _FunctionType>
|
||||
@ -341,11 +342,15 @@ class delegate_mfp
|
||||
public:
|
||||
// default constructor
|
||||
delegate_mfp()
|
||||
: m_function(0) { }
|
||||
: m_function(0), m_this_delta(0), m_dummy1(0), m_dummy2(0), m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
delegate_mfp(const delegate_mfp &src)
|
||||
: m_function(src.m_function) { }
|
||||
: m_function(src.m_function), m_this_delta(0), m_dummy1(0), m_dummy2(0), m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
// construct from any member function pointer
|
||||
template<typename _MemberFunctionType, class _MemberFunctionClass, typename _ReturnType, typename _StaticFunctionType>
|
||||
@ -361,7 +366,7 @@ public:
|
||||
bool isnull() const { return (m_function == 0); }
|
||||
|
||||
// getters
|
||||
delegate_generic_class *real_object(delegate_generic_class *original) const { return original; }
|
||||
static delegate_generic_class *real_object(delegate_generic_class *original) { return original; }
|
||||
|
||||
// binding helper
|
||||
template<typename _FunctionType>
|
||||
@ -407,19 +412,22 @@ public:
|
||||
template<class _FunctionClass>
|
||||
struct traits
|
||||
{
|
||||
typedef typename delegate_traits<_FunctionClass, _ReturnType, Params...>::member_func_type member_func_type;
|
||||
typedef typename delegate_traits<_FunctionClass, _ReturnType, Params...>::static_func_type static_func_type;
|
||||
typedef typename delegate_traits<_FunctionClass, _ReturnType, Params...>::static_ref_func_type static_ref_func_type;
|
||||
using member_func_type = typename delegate_traits<_FunctionClass, _ReturnType, Params...>::member_func_type;
|
||||
using const_member_func_type = typename delegate_traits<_FunctionClass, _ReturnType, Params...>::const_member_func_type;
|
||||
using static_func_type = typename delegate_traits<_FunctionClass, _ReturnType, Params...>::static_func_type;
|
||||
using static_ref_func_type = typename delegate_traits<_FunctionClass, _ReturnType, Params...>::static_ref_func_type;
|
||||
};
|
||||
typedef typename traits<delegate_generic_class>::static_func_type generic_static_func;
|
||||
typedef MEMBER_ABI generic_static_func generic_member_func;
|
||||
using functional_type = std::function<_ReturnType(Params...)>;
|
||||
using generic_static_func = typename traits<delegate_generic_class>::static_func_type;
|
||||
using generic_member_func = MEMBER_ABI generic_static_func;
|
||||
// generic constructor
|
||||
delegate_base()
|
||||
: m_function(nullptr),
|
||||
m_object(nullptr),
|
||||
m_name(nullptr),
|
||||
m_latebinder(nullptr),
|
||||
m_raw_function(nullptr) { }
|
||||
m_raw_function(nullptr),
|
||||
m_std_func(nullptr){ }
|
||||
|
||||
// copy constructor
|
||||
delegate_base(const delegate_base &src)
|
||||
@ -428,7 +436,8 @@ public:
|
||||
m_name(src.m_name),
|
||||
m_latebinder(src.m_latebinder),
|
||||
m_raw_function(src.m_raw_function),
|
||||
m_raw_mfp(src.m_raw_mfp)
|
||||
m_raw_mfp(src.m_raw_mfp),
|
||||
m_std_func(src.m_std_func)
|
||||
{
|
||||
bind(src.object());
|
||||
}
|
||||
@ -440,7 +449,8 @@ public:
|
||||
m_name(src.m_name),
|
||||
m_latebinder(src.m_latebinder),
|
||||
m_raw_function(src.m_raw_function),
|
||||
m_raw_mfp(src.m_raw_mfp)
|
||||
m_raw_mfp(src.m_raw_mfp),
|
||||
m_std_func(src.m_std_func)
|
||||
{
|
||||
late_bind(object);
|
||||
}
|
||||
@ -453,7 +463,21 @@ public:
|
||||
m_name(name),
|
||||
m_latebinder(&late_bind_helper<_FunctionClass>),
|
||||
m_raw_function(nullptr),
|
||||
m_raw_mfp(funcptr, object, (_ReturnType *)nullptr, static_cast<generic_static_func>(nullptr))
|
||||
m_raw_mfp(funcptr, object, static_cast<_ReturnType *>(nullptr), static_cast<generic_static_func>(nullptr)),
|
||||
m_std_func(nullptr)
|
||||
{
|
||||
bind(reinterpret_cast<delegate_generic_class *>(object));
|
||||
}
|
||||
|
||||
template<class _FunctionClass>
|
||||
delegate_base(typename traits<_FunctionClass>::const_member_func_type funcptr, const char *name, _FunctionClass *object)
|
||||
: m_function(nullptr),
|
||||
m_object(nullptr),
|
||||
m_name(name),
|
||||
m_latebinder(&late_bind_helper<_FunctionClass>),
|
||||
m_raw_function(nullptr),
|
||||
m_raw_mfp(funcptr, object, static_cast<_ReturnType *>(nullptr), static_cast<generic_static_func>(nullptr)),
|
||||
m_std_func(nullptr)
|
||||
{
|
||||
bind(reinterpret_cast<delegate_generic_class *>(object));
|
||||
}
|
||||
@ -465,7 +489,8 @@ public:
|
||||
m_object(nullptr),
|
||||
m_name(name),
|
||||
m_latebinder(&late_bind_helper<_FunctionClass>),
|
||||
m_raw_function(reinterpret_cast<generic_static_func>(funcptr))
|
||||
m_raw_function(reinterpret_cast<generic_static_func>(funcptr)),
|
||||
m_std_func(nullptr)
|
||||
{
|
||||
bind(reinterpret_cast<delegate_generic_class *>(object));
|
||||
}
|
||||
@ -477,11 +502,24 @@ public:
|
||||
m_object(nullptr),
|
||||
m_name(name),
|
||||
m_latebinder(&late_bind_helper<_FunctionClass>),
|
||||
m_raw_function(reinterpret_cast<generic_static_func>(funcptr))
|
||||
m_raw_function(reinterpret_cast<generic_static_func>(funcptr)),
|
||||
m_std_func(nullptr)
|
||||
{
|
||||
bind(reinterpret_cast<delegate_generic_class *>(object));
|
||||
}
|
||||
|
||||
// construct from static reference function with object reference
|
||||
delegate_base(functional_type funcptr, const char *name)
|
||||
: m_function(nullptr),
|
||||
m_object(nullptr),
|
||||
m_name(name),
|
||||
m_latebinder(nullptr),
|
||||
m_raw_function(nullptr),
|
||||
m_std_func(funcptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// copy operator
|
||||
delegate_base &operator=(const delegate_base &src)
|
||||
{
|
||||
@ -493,6 +531,8 @@ public:
|
||||
m_latebinder = src.m_latebinder;
|
||||
m_raw_function = src.m_raw_function;
|
||||
m_raw_mfp = src.m_raw_mfp;
|
||||
m_std_func = src.m_std_func;
|
||||
|
||||
bind(src.object());
|
||||
}
|
||||
return *this;
|
||||
@ -501,24 +541,26 @@ public:
|
||||
// comparison helper
|
||||
bool operator==(const delegate_base &rhs) const
|
||||
{
|
||||
return (m_raw_function == rhs.m_raw_function && object() == rhs.object() && m_raw_mfp == rhs.m_raw_mfp);
|
||||
return (m_raw_function == rhs.m_raw_function && object() == rhs.object() && m_raw_mfp == rhs.m_raw_mfp && m_std_func.target_type().name() == rhs.m_std_func.target_type().name());
|
||||
}
|
||||
|
||||
#define DELEGATE_CALL(x) \
|
||||
if (is_mfp() && (HAS_DIFFERENT_ABI)) \
|
||||
return (*reinterpret_cast<generic_member_func>(m_function)) x; \
|
||||
else \
|
||||
return (*m_function) x;
|
||||
|
||||
// call the function
|
||||
_ReturnType operator()(Params... args) const { DELEGATE_CALL((m_object, std::forward<Params>(args)...)); }
|
||||
_ReturnType operator()(Params... args) const {
|
||||
if (is_mfp() && (HAS_DIFFERENT_ABI))
|
||||
return (*reinterpret_cast<generic_member_func>(m_function)) (m_object, std::forward<Params>(args)...);
|
||||
else if (m_std_func)
|
||||
return m_std_func(std::forward<Params>(args)...);
|
||||
else
|
||||
return (*m_function) (m_object, std::forward<Params>(args)...);
|
||||
}
|
||||
|
||||
// getters
|
||||
bool has_object() const { return (object() != nullptr); }
|
||||
bool has_object() const { return (object() != nullptr) || (m_std_func); }
|
||||
const char *name() const { return m_name; }
|
||||
|
||||
// helpers
|
||||
bool isnull() const { return (m_raw_function == nullptr && m_raw_mfp.isnull()); }
|
||||
bool isnull() const { return (m_raw_function == nullptr && m_raw_mfp.isnull() && !m_std_func); }
|
||||
bool is_mfp() const { return !m_raw_mfp.isnull(); }
|
||||
|
||||
// late binding
|
||||
@ -529,7 +571,7 @@ protected:
|
||||
delegate_generic_class *object() const { return is_mfp() ? m_raw_mfp.real_object(m_object) : m_object; }
|
||||
|
||||
// late binding function
|
||||
typedef delegate_generic_class *(*late_bind_func)(delegate_late_bind &object);
|
||||
using late_bind_func = delegate_generic_class*(*)(delegate_late_bind &object);
|
||||
|
||||
// late binding helper
|
||||
template<class _FunctionClass>
|
||||
@ -559,6 +601,7 @@ protected:
|
||||
late_bind_func m_latebinder; // late binding helper
|
||||
generic_static_func m_raw_function; // raw static function pointer
|
||||
delegate_mfp m_raw_mfp; // raw member function pointer
|
||||
functional_type m_std_func; // std::function pointer
|
||||
};
|
||||
|
||||
|
||||
@ -574,7 +617,7 @@ class delegate;
|
||||
template<typename _ReturnType, typename... Params>
|
||||
class delegate<_ReturnType (Params...)> : public delegate_base<_ReturnType, Params...>
|
||||
{
|
||||
typedef delegate_base<_ReturnType, Params...> basetype;
|
||||
using basetype = delegate_base<_ReturnType, Params...>;
|
||||
|
||||
public:
|
||||
// create a standard set of constructors
|
||||
@ -582,6 +625,8 @@ public:
|
||||
delegate(const basetype &src) : basetype(src) { }
|
||||
delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object) { }
|
||||
template<class _FunctionClass> delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
|
||||
template<class _FunctionClass> delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
|
||||
delegate(std::function<_ReturnType(Params...)> funcptr) : basetype(funcptr, "") { }
|
||||
#ifdef USE_STATIC_DELEGATE
|
||||
template<class _FunctionClass> delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
|
||||
template<class _FunctionClass> delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
|
||||
|
@ -105,8 +105,6 @@ public:
|
||||
uint8_t m_last_coin;
|
||||
DECLARE_WRITE8_MEMBER(statriv2_videoram_w);
|
||||
DECLARE_READ8_MEMBER(question_data_r);
|
||||
DECLARE_READ8_MEMBER(laserdisc_io_r);
|
||||
DECLARE_WRITE8_MEMBER(laserdisc_io_w);
|
||||
DECLARE_CUSTOM_INPUT_MEMBER(latched_coin_r);
|
||||
DECLARE_WRITE8_MEMBER(ppi_portc_hi_w);
|
||||
DECLARE_DRIVER_INIT(addr_xlh);
|
||||
@ -1141,25 +1139,23 @@ DRIVER_INIT_MEMBER(statriv2_state,addr_lmhe)
|
||||
DRIVER_INIT_CALL(addr_lmh);
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER(statriv2_state::laserdisc_io_r)
|
||||
{
|
||||
uint8_t result = 0x00;
|
||||
if (offset == 1)
|
||||
result = 0x18;
|
||||
osd_printf_debug("%s:ld read ($%02X) = %02X\n", machine().describe_context(), 0x28 + offset, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(statriv2_state::laserdisc_io_w)
|
||||
{
|
||||
osd_printf_debug("%s:ld write ($%02X) = %02X\n", machine().describe_context(), 0x28 + offset, data);
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(statriv2_state,laserdisc)
|
||||
{
|
||||
address_space &iospace = m_maincpu->space(AS_IO);
|
||||
iospace.install_readwrite_handler(0x28, 0x2b, read8_delegate(FUNC(statriv2_state::laserdisc_io_r), this), write8_delegate(FUNC(statriv2_state::laserdisc_io_w), this));
|
||||
iospace.install_readwrite_handler(0x28, 0x2b,
|
||||
read8_delegate([this](address_space &space, offs_t offset, uint8_t mem_mask) -> uint8_t
|
||||
{
|
||||
uint8_t result = 0x00;
|
||||
if (offset == 1)
|
||||
result = 0x18;
|
||||
osd_printf_debug("%s:ld read ($%02X) = %02X\n", machine().describe_context(), 0x28 + offset, result);
|
||||
return result;
|
||||
}),
|
||||
write8_delegate([this](address_space &space, offs_t offset, uint8_t data, uint8_t mem_mask)
|
||||
{
|
||||
osd_printf_debug("%s:ld write ($%02X) = %02X\n", machine().describe_context(), 0x28 + offset, data);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user