summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/devdelegate.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/devdelegate.h')
-rw-r--r--src/emu/devdelegate.h441
1 files changed, 380 insertions, 61 deletions
diff --git a/src/emu/devdelegate.h b/src/emu/devdelegate.h
index 8bdef60f880..3a63c874d92 100644
--- a/src/emu/devdelegate.h
+++ b/src/emu/devdelegate.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
devdelegate.h
@@ -15,98 +15,417 @@
#include "delegate.h"
+#include <array>
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+
+// older versions of libc++ are missing deduction guides that the things using this constructor require
+#if defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION < 10000)
+namespace std { inline namespace __1 {
+template<class R, class... ArgTypes > function( R(*)(ArgTypes...) ) -> function<R(ArgTypes...)>;
+} }
+#endif
+
+
+namespace emu {
//**************************************************************************
-// TYPE DEFINITIONS
+// FORWARD DECLARATIONS
//**************************************************************************
-// ======================> device_delegate_helper
-
-// device_delegate_helper does non-template work
-class device_delegate_helper
-{
-protected:
- // constructor
- device_delegate_helper(const char *devname) : m_device_name(devname) { }
+template <typename Signature, unsigned Count> class device_delegate_array;
- // internal helpers
- delegate_late_bind &bound_object(device_t &search_root) const;
- static const char *safe_tag(device_t *object);
- // internal state
- const char *m_device_name;
-};
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
-// ======================> named_delegate
template <typename Signature>
class named_delegate : public delegate<Signature>
{
private:
using basetype = delegate<Signature>;
- const char * m_name; // name string
+ char const *m_name = nullptr; // name string
protected:
template <class FunctionClass> using member_func_type = typename basetype::template member_func_type<FunctionClass>;
template <class FunctionClass> using const_member_func_type = typename basetype::template const_member_func_type<FunctionClass>;
template <class FunctionClass> using static_ref_func_type = typename basetype::template static_ref_func_type<FunctionClass>;
+ template <typename T> using suitable_functoid = typename basetype::template suitable_functoid<T>;
+
public:
// create a standard set of constructors
- named_delegate() : basetype(), m_name(nullptr) { }
- explicit named_delegate(const basetype &src) : basetype(src), m_name(src.m_name) { }
- named_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), m_name(src.m_name) { }
- template <class FunctionClass> named_delegate(member_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
- template <class FunctionClass> named_delegate(const_member_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
- explicit named_delegate(std::function<Signature> funcptr, const char *name) : basetype(funcptr), m_name(name) { }
- template <class FunctionClass> named_delegate(static_ref_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
- named_delegate &operator=(const basetype &src) { basetype::operator=(src); m_name = src.m_name; return *this; }
-
- const char *name() const { return m_name; }
+ named_delegate() = default;
+ named_delegate(named_delegate const &) = default;
+ named_delegate(named_delegate const &src, delegate_late_bind &object) : basetype(src, object), m_name(src.m_name) { }
+ template <class FunctionClass> named_delegate(member_func_type<FunctionClass> funcptr, char const *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
+ template <class FunctionClass> named_delegate(const_member_func_type<FunctionClass> funcptr, char const *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
+ template <class FunctionClass> named_delegate(static_ref_func_type<FunctionClass> funcptr, char const *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
+ template <typename T> named_delegate(T &&funcptr, std::enable_if_t<suitable_functoid<T>::value, char const *> name) : basetype(std::forward<T>(funcptr)), m_name(name) { }
+
+ // allow assignment
+ named_delegate &operator=(named_delegate const &) = default;
+ named_delegate &operator=(named_delegate &&) = default;
+ named_delegate &operator=(std::nullptr_t) noexcept { reset(); return *this; }
+
+ // getters
+ char const *name() const noexcept { return m_name; }
+
+ // unsetter
+ void reset() noexcept { basetype::reset(); m_name = nullptr; }
};
-// ======================> device_delegate
+template <class FunctionClass, typename ReturnType, typename... Params>
+named_delegate(ReturnType (FunctionClass::*)(Params...), char const *, FunctionClass *) -> named_delegate<ReturnType (Params...)>;
-// device_delegate is a delegate that wraps with a device tag and can be easily
-// late bound without replicating logic everywhere
-template <typename Signature>
-class device_delegate : public named_delegate<Signature>, public device_delegate_helper
+template <class FunctionClass, typename ReturnType, typename... Params>
+named_delegate(ReturnType (FunctionClass::*)(Params...) const, char const *, FunctionClass *) -> named_delegate<ReturnType (Params...)>;
+
+template <class FunctionClass, typename ReturnType, typename... Params>
+named_delegate(ReturnType (*)(FunctionClass &, Params...), char const *, FunctionClass *) -> named_delegate<ReturnType (Params...)>;
+
+
+namespace detail {
+
+// device_delegate_helper does non-template work
+
+class device_delegate_helper
{
- using thistype = device_delegate<Signature>;
- using basetype = named_delegate<Signature>;
- template <class FunctionClass> using member_func_type = typename basetype::template member_func_type<FunctionClass>;
- template <class FunctionClass> using const_member_func_type = typename basetype::template const_member_func_type<FunctionClass>;
- template <class FunctionClass> using static_ref_func_type = typename basetype::template static_ref_func_type<FunctionClass>;
+public:
+ // accessors
+ char const *finder_tag() const { return m_tag; }
+ std::pair<device_t &, char const *> finder_target() const { return std::make_pair(m_base, m_tag); }
+
+protected:
+ // construct/assign
+ device_delegate_helper(device_t &owner, char const *tag = nullptr) : m_base(owner), m_tag(tag) { }
+ template <class DeviceClass, bool Required> device_delegate_helper(device_finder<DeviceClass, Required> const &finder);
+ device_delegate_helper(device_delegate_helper const &) = default;
+ device_delegate_helper &operator=(device_delegate_helper const &) = default;
+
+ // internal helpers
+ delegate_late_bind &bound_object() const;
+ void set_tag(device_t &object) { m_base = object; m_tag = nullptr; }
+ void set_tag(device_t &base, char const *tag) { m_base = base; m_tag = tag; }
+ void set_tag(char const *tag);
+ template <class DeviceClass, bool Required> void set_tag(device_finder<DeviceClass, Required> const &finder);
+
+private:
+ std::reference_wrapper<device_t> m_base;
+ char const *m_tag;
+};
+
+
+// device_delegate_base doesn't need to be specialised on return type
+
+template <typename Signature> class device_delegate_base;
+
+template <typename ReturnType, typename... Params>
+class device_delegate_base<ReturnType (Params...)> : protected named_delegate<ReturnType (Params...)>, public device_delegate_helper
+{
+private:
+ using basetype = named_delegate<ReturnType (Params...)>;
+
+ template <typename T>
+ using suitable_functoid = typename basetype::template suitable_functoid<T>;
+
+ template <class T, class U>
+ using is_related_device_implementation = std::bool_constant<std::is_base_of_v<T, U> && std::is_base_of_v<device_t, U> >;
+ template <class T, class U>
+ using is_related_device_interface = std::bool_constant<std::is_base_of_v<T, U> && std::is_base_of_v<device_interface, U> && !std::is_base_of_v<device_t, U> >;
+ template <class T, class U>
+ using is_related_device = std::bool_constant<is_related_device_implementation<T, U>::value || is_related_device_interface<T, U>::value>;
+
+ template <class T> static std::enable_if_t<is_related_device_implementation<T, T>::value, device_t &> get_device(T &object) { return object; }
+ template <class T> static std::enable_if_t<is_related_device_interface<T, T>::value, device_t &> get_device(T &object) { return object.device(); }
+
+public:
+ // construct/assign
+ explicit device_delegate_base(device_t &owner) : basetype(), device_delegate_helper(owner) { }
+ device_delegate_base(device_delegate_base const &) = default;
+ device_delegate_base &operator=(device_delegate_base const &) = default;
+
+ // construct with prototype and target
+ device_delegate_base(basetype const &proto, device_t &object) : basetype(proto, object), device_delegate_helper(object) { }
+ device_delegate_base(device_delegate_base const &proto, device_t &object) : basetype(proto, object), device_delegate_helper(object) { }
+
+ // construct with base and tag
+ template <class D>
+ device_delegate_base(device_t &base, char const *tag, ReturnType (D::*funcptr)(Params...), char const *name)
+ : basetype(funcptr, name, static_cast<D *>(nullptr))
+ , device_delegate_helper(base, tag)
+ { }
+ template <class D>
+ device_delegate_base(device_t &base, char const *tag, ReturnType (D::*funcptr)(Params...) const, char const *name)
+ : basetype(funcptr, name, static_cast<D *>(nullptr))
+ , device_delegate_helper(base, tag)
+ { }
+ template <class D>
+ device_delegate_base(device_t &base, char const *tag, ReturnType (*funcptr)(D &, Params...), char const *name)
+ : basetype(funcptr, name, static_cast<D *>(nullptr))
+ , device_delegate_helper(base, tag)
+ { }
+
+ // construct with device finder
+ template <class D, bool R, class E>
+ device_delegate_base(device_finder<D, R> const &finder, ReturnType (E::*funcptr)(Params...), char const *name)
+ : basetype(funcptr, name, static_cast<E *>(nullptr))
+ , device_delegate_helper(finder)
+ { }
+ template <class D, bool R, class E>
+ device_delegate_base(device_finder<D, R> const &finder, ReturnType (E::*funcptr)(Params...) const, char const *name)
+ : basetype(funcptr, name, static_cast<E *>(nullptr))
+ , device_delegate_helper(finder)
+ { }
+ template <class D, bool R, class E>
+ device_delegate_base(device_finder<D, R> const &finder, ReturnType (*funcptr)(E &, Params...), char const *name)
+ : basetype(funcptr, name, static_cast<E *>(nullptr))
+ , device_delegate_helper(finder)
+ { }
+
+ // construct with target object
+ template <class T, class D>
+ device_delegate_base(T &object, ReturnType (D::*funcptr)(Params...), std::enable_if_t<is_related_device<D, T>::value, char const *> name)
+ : basetype(funcptr, name, static_cast<D *>(&object))
+ , device_delegate_helper(get_device(object))
+ { }
+ template <class T, class D>
+ device_delegate_base(T &object, ReturnType (D::*funcptr)(Params...) const, std::enable_if_t<is_related_device<D, T>::value, char const *> name)
+ : basetype(funcptr, name, static_cast<D *>(&object))
+ , device_delegate_helper(get_device(object))
+ { }
+ template <class T, class D>
+ device_delegate_base(T &object, ReturnType (*funcptr)(D &, Params...), std::enable_if_t<is_related_device<D, T>::value, char const *> name)
+ : basetype(funcptr, name, static_cast<D *>(&object))
+ , device_delegate_helper(get_device(object))
+ { }
+
+ // construct with callable object
+ template <typename T>
+ device_delegate_base(device_t &owner, T &&funcptr, std::enable_if_t<suitable_functoid<T>::value, char const *> name)
+ : basetype(std::forward<T>(funcptr), name)
+ , device_delegate_helper(owner)
+ { }
+ // setters that implicitly bind to the current device
+ template <class D> void set(ReturnType (D::*funcptr)(Params...), char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(nullptr))); set_tag(nullptr); }
+ template <class D> void set(ReturnType (D::*funcptr)(Params...) const, char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(nullptr))); set_tag(nullptr); }
+ template <class D> void set(ReturnType (*funcptr)(D &, Params...), char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(nullptr))); set_tag(nullptr); }
+
+ // setters that take a tag-like object specifying the target
+ template <typename T, class D> void set(T &&tag, ReturnType (D::*funcptr)(Params...), char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(nullptr))); set_tag(std::forward<T>(tag)); }
+ template <typename T, class D> void set(T &&tag, ReturnType (D::*funcptr)(Params...) const, char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(nullptr))); set_tag(std::forward<T>(tag)); }
+ template <typename T, class D> void set(T &&tag, ReturnType (*funcptr)(D &, Params...), char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(nullptr))); set_tag(std::forward<T>(tag)); }
+
+ // setters that take a target object
+ template <class T, class D> std::enable_if_t<std::is_base_of<D, T>::value> set(T &object, ReturnType (D::*funcptr)(Params...), char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(&object))); set_tag(finder_target().first); }
+ template <class T, class D> std::enable_if_t<std::is_base_of<D, T>::value> set(T &object, ReturnType (D::*funcptr)(Params...) const, char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(&object))); set_tag(finder_target().first); }
+ template <class T, class D> std::enable_if_t<std::is_base_of<D, T>::value> set(T &object, ReturnType (*funcptr)(D &, Params...), char const *name)
+ { basetype::operator=(basetype(funcptr, name, static_cast<D *>(&object))); set_tag(finder_target().first); }
+
+ // setter that takes a functoid
+ template <typename T> std::enable_if_t<suitable_functoid<T>::value> set(T &&funcptr, char const *name)
+ { basetype::operator=(basetype(std::forward<T>(funcptr), name)); }
+
+ // unsetter
+ void set(std::nullptr_t)
+ { reset(); }
+ void reset()
+ { basetype::reset(); set_tag(finder_target().first); }
+
+ // accessors
+ using basetype::operator();
+ using basetype::isnull;
+ using basetype::has_object;
+ using basetype::name;
+
+ // perform the binding
+ void resolve()
+ {
+ if (!this->isnull() && !this->has_object())
+ this->late_bind(bound_object());
+ }
+};
+
+} // namespace detail
+
+
+// device_delegate is a delegate that can be late bound to a device specification
+
+template <typename Signature> class device_delegate;
+
+template <typename ReturnType, typename... Params>
+class device_delegate<ReturnType (Params...)> : protected detail::device_delegate_base<ReturnType (Params...)>
+{
public:
- // provide the same constructors as the base class
- device_delegate() : basetype(), device_delegate_helper(nullptr) { }
- 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(member_func_type<FunctionClass> 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(const_member_func_type<FunctionClass> 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(static_ref_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
- device_delegate(std::function<Signature> funcptr, const char *name) : basetype(funcptr, name), device_delegate_helper(nullptr) { }
- device_delegate &operator=(const thistype &src) { basetype::operator=(src); m_device_name = src.m_device_name; return *this; }
-
- // provide additional constructors that take a device name string
- template <class FunctionClass> device_delegate(member_func_type<FunctionClass> funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template <class FunctionClass> device_delegate(member_func_type<FunctionClass> funcptr, const char *name, const char *devname, FunctionClass *) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template <class FunctionClass> device_delegate(const_member_func_type<FunctionClass> funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template <class FunctionClass> device_delegate(const_member_func_type<FunctionClass> funcptr, const char *name, const char *devname, FunctionClass *) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template <class FunctionClass> device_delegate(static_ref_func_type<FunctionClass> funcptr, const char *name, const char *devname, FunctionClass *) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- device_delegate(static_ref_func_type<device_t> funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
-
- // and constructors that provide a search root
- device_delegate(const thistype &src, device_t &search_root) : basetype(src), device_delegate_helper(src.m_device_name) { bind_relative_to(search_root); }
+ template <unsigned Count> using array = device_delegate_array<ReturnType (Params...), Count>;
+
+ template <typename T>
+ using supports_callback = std::bool_constant<std::is_constructible_v<device_delegate, device_t &, char const *, T, char const *> >;
+
+ // constructors
+ using detail::device_delegate_base<ReturnType (Params...)>::device_delegate_base;
+ device_delegate(device_delegate const &) = default;
+ device_delegate(device_delegate const &proto, device_t &object) : detail::device_delegate_base<ReturnType (Params...)>(proto, object) { }
+
+ // assignment
+ device_delegate &operator=(device_delegate const &) = default;
+ device_delegate &operator=(std::nullptr_t) { this->reset(); }
+
+ // setters/unsetters
+ void set(device_delegate const &src) { operator=(src); }
+ using detail::device_delegate_base<ReturnType (Params...)>::set;
+ using detail::device_delegate_base<ReturnType (Params...)>::reset;
+
+ // accessors
+ using detail::device_delegate_base<ReturnType (Params...)>::operator();
+ using detail::device_delegate_base<ReturnType (Params...)>::isnull;
+ using detail::device_delegate_base<ReturnType (Params...)>::has_object;
+ using detail::device_delegate_base<ReturnType (Params...)>::name;
+ using detail::device_delegate_base<ReturnType (Params...)>::finder_tag;
+ using detail::device_delegate_base<ReturnType (Params...)>::finder_target;
+
+ // perform the binding
+ using detail::device_delegate_base<ReturnType (Params...)>::resolve;
+
+ template <typename T>
+ void resolve_safe(T &&dflt)
+ {
+ if (this->isnull())
+ this->set([result = std::decay_t<T>(std::forward<T>(dflt))] (Params...) { return ReturnType(result); }, "default");
+ else if (!this->has_object())
+ this->late_bind(this->bound_object());
+ }
+};
+
+template <typename... Params>
+class device_delegate<void (Params...)> : protected detail::device_delegate_base<void (Params...)>
+{
+public:
+ template <unsigned Count> using array = device_delegate_array<void (Params...), Count>;
+
+ template <typename T>
+ using supports_callback = std::bool_constant<std::is_constructible_v<device_delegate, device_t &, char const *, T, char const *> >;
+
+ // constructors
+ using detail::device_delegate_base<void (Params...)>::device_delegate_base;
+ device_delegate(device_delegate const &) = default;
+ device_delegate(device_delegate const &proto, device_t &object) : detail::device_delegate_base<void (Params...)>(proto, object) { }
+
+ // assignment
+ device_delegate &operator=(device_delegate const &) = default;
+ device_delegate &operator=(std::nullptr_t) { this->reset(); }
+
+ // setters/unsetters
+ void set(device_delegate const &src) { operator=(src); }
+ using detail::device_delegate_base<void (Params...)>::set;
+ using detail::device_delegate_base<void (Params...)>::reset;
+
+ // accessors
+ using detail::device_delegate_base<void (Params...)>::operator();
+ using detail::device_delegate_base<void (Params...)>::isnull;
+ using detail::device_delegate_base<void (Params...)>::has_object;
+ using detail::device_delegate_base<void (Params...)>::name;
+ using detail::device_delegate_base<void (Params...)>::finder_tag;
+ using detail::device_delegate_base<void (Params...)>::finder_target;
// perform the binding
- void bind_relative_to(device_t &search_root) { if (!basetype::isnull()) basetype::late_bind(bound_object(search_root)); }
+ using detail::device_delegate_base<void (Params...)>::resolve;
- // getter (for validation purposes)
- const char *device_name() const { return m_device_name; }
+ void resolve_safe()
+ {
+ if (this->isnull())
+ this->set([] (Params...) { }, "default");
+ else if (!this->has_object())
+ this->late_bind(this->bound_object());
+ }
};
+// simplifies constructing an array of delegates with a single owner
+
+template <typename Signature, unsigned Count>
+class device_delegate_array : public std::array<device_delegate<Signature>, Count>
+{
+private:
+ template <unsigned... V>
+ device_delegate_array(device_t &owner, std::integer_sequence<unsigned, V...> const &)
+ : std::array<device_delegate<Signature>, Count>{{ make_one<V>(owner)... }}
+ {
+ }
+
+ template <unsigned N>
+ device_delegate<Signature> make_one(device_t &owner)
+ {
+ return device_delegate<Signature>(owner);
+ }
+
+public:
+ using std::array<device_delegate<Signature>, Count>::array;
+
+ device_delegate_array(device_t &owner)
+ : device_delegate_array(owner, std::make_integer_sequence<unsigned, Count>())
+ {
+ }
+
+ void resolve_all()
+ {
+ for (device_delegate<Signature> &elem : *this)
+ elem.resolve();
+ }
+
+ template <typename... T>
+ void resolve_all_safe(T &&... args)
+ {
+ for (device_delegate<Signature> &elem : *this)
+ elem.resolve_safe(args...);
+ }
+};
+
+template <class D, typename ReturnType, typename... Params>
+device_delegate(device_t &, char const *, ReturnType (D::*)(Params...), char const *) -> device_delegate<ReturnType (Params...)>;
+
+template <class D, typename ReturnType, typename... Params>
+device_delegate(device_t &, char const *, ReturnType (D::*)(Params...) const, char const *) -> device_delegate<ReturnType (Params...)>;
+
+template <class D, typename ReturnType, typename... Params>
+device_delegate(device_t &, char const *, ReturnType (*)(D &, Params...), char const *) -> device_delegate<ReturnType (Params...)>;
+
+template <class D, bool R, class E, typename ReturnType, typename... Params>
+device_delegate(device_finder<D, R> const &, ReturnType (E::*)(Params...), char const *) -> device_delegate<ReturnType (Params...)>;
+
+template <class D, bool R, class E, typename ReturnType, typename... Params>
+device_delegate(device_finder<D, R> const &, ReturnType (E::*)(Params...) const, char const *) -> device_delegate<ReturnType (Params...)>;
+
+template <class D, bool R, class E, typename ReturnType, typename... Params>
+device_delegate(device_finder<D, R> const &, ReturnType (*)(E &, Params...), char const *) -> device_delegate<ReturnType (Params...)>;
+
+template <class T, class D, typename ReturnType, typename... Params>
+device_delegate(T &, ReturnType (D::*)(Params...), char const *) -> device_delegate<ReturnType (Params...)>;
+
+template <class T, class D, typename ReturnType, typename... Params>
+device_delegate(T &, ReturnType (D::*)(Params...) const, char const *) -> device_delegate<ReturnType (Params...)>;
+
+template <class T, class D, typename ReturnType, typename... Params>
+device_delegate(T &, ReturnType (*)(D &, Params...), char const *) -> device_delegate<ReturnType (Params...)>;
+
+} // namespace emu
+
+
+using emu::named_delegate;
+using emu::device_delegate;
+
#endif // MAME_EMU_DEVDELEGATE_H