/*
-Copyright (C) 2001-2006, William Joseph.
-All Rights Reserved.
+ Copyright (C) 2001-2006, William Joseph.
+ All Rights Reserved.
-This file is part of GtkRadiant.
+ This file is part of GtkRadiant.
-GtkRadiant is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ GtkRadiant is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-GtkRadiant is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GtkRadiant is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
+ You should have received a copy of the GNU General Public License
+ along with GtkRadiant; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
-#if !defined(INCLUDED_GENERIC_CLOSURE_H)
+#if !defined( INCLUDED_GENERIC_CLOSURE_H )
#define INCLUDED_GENERIC_CLOSURE_H
/// \file
-/// \brief Type-safe techniques for binding the first argument of an anonymous callback.
+/// \brief Type-safe techniques for binding the first argument of an opaque callback.
#include <cstddef>
+#include "functional.h"
-/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer.
-///
-/// Use with the callback constructors MemberCaller, ConstMemberCaller, ReferenceCaller, ConstReferenceCaller, PointerCaller, ConstPointerCaller and FreeCaller.
-class Callback
-{
- typedef void (*Thunk)(void*);
- void* m_environment;
- Thunk m_thunk;
-
- static void nullThunk(void*)
- {
- }
+namespace detail {
-public:
- Callback() : m_environment(0), m_thunk(nullThunk)
- {
- }
- Callback(void* environment, Thunk function) : m_environment(environment), m_thunk(function)
- {
- }
- void* getEnvironment() const
- {
- return m_environment;
- }
- Thunk getThunk() const
- {
- return m_thunk;
- }
- void operator()() const
- {
- m_thunk(m_environment);
- }
-};
+ template<typename Thunk_>
+ class CallbackBase {
+ void *m_environment;
+ Thunk_ m_thunk;
+ public:
+ typedef Thunk_ Thunk;
-inline bool operator==(const Callback& self, const Callback& other)
-{
- return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
-}
-inline bool operator<(const Callback& self, const Callback& other)
-{
- return self.getEnvironment() < other.getEnvironment() ||
- (!(other.getEnvironment() < self.getEnvironment()) && self.getThunk() < other.getThunk());
-}
+ CallbackBase(void *environment, Thunk function) : m_environment(environment), m_thunk(function) {
+ }
-/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and one other argument.
-///
-/// Use with the callback constructors MemberCaller1, ConstMemberCaller1, ReferenceCaller1, ConstReferenceCaller1, PointerCaller1, ConstPointerCaller1 and FreeCaller1.
-template<typename FirstArgument>
-class Callback1
-{
- typedef void (*Thunk)(void*, FirstArgument);
- void* m_environment;
- Thunk m_thunk;
-
- static void nullThunk(void*, FirstArgument)
- {
- }
+ void *getEnvironment() const {
+ return m_environment;
+ }
-public:
- typedef FirstArgument first_argument_type;
-
- Callback1() : m_environment(0), m_thunk(nullThunk)
- {
- }
- Callback1(void* environment, Thunk function) : m_environment(environment), m_thunk(function)
- {
- }
- void* getEnvironment() const
- {
- return m_environment;
- }
- Thunk getThunk() const
- {
- return m_thunk;
- }
- void operator()(FirstArgument firstArgument) const
- {
- m_thunk(m_environment, firstArgument);
- }
-};
+ Thunk getThunk() const {
+ return m_thunk;
+ }
+ };
-template<typename FirstArgument>
-inline bool operator==(const Callback1<FirstArgument>& self, const Callback1<FirstArgument>& other)
-{
- return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
-}
-template<typename FirstArgument>
-inline bool operator<(const Callback1<FirstArgument>& self, const Callback1<FirstArgument>& other)
-{
- return self.getEnvironment() < other.getEnvironment() ||
- (!(other.getEnvironment() < self.getEnvironment()) && self.getThunk() < other.getThunk());
-}
+ template<typename Thunk>
+ inline bool operator==(const CallbackBase<Thunk> &self, const CallbackBase<Thunk> &other) {
+ return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
+ }
-template<typename Functor>
-class FunctorInvoke
-{
-public:
- inline void operator()(Functor functor)
- {
- functor();
- }
-};
+ template<typename Thunk>
+ inline bool operator!=(const CallbackBase<Thunk> &self, const CallbackBase<Thunk> &other) {
+ return !(self == other);
+ }
-typedef FunctorInvoke<Callback> CallbackInvoke;
+ template<typename Thunk>
+ inline bool operator<(const CallbackBase<Thunk> &self, const CallbackBase<Thunk> &other) {
+ return self.getEnvironment() < other.getEnvironment() ||
+ (!(other.getEnvironment() < self.getEnvironment()) && self.getThunk() < other.getThunk());
+ }
+}
-template<typename Functor, typename FirstArgument>
-class Functor1Invoke
-{
- FirstArgument m_firstArgument;
-public:
- Functor1Invoke(FirstArgument firstArgument) : m_firstArgument(firstArgument)
- {
- }
- inline void operator()(Functor functor)
- {
- functor(m_firstArgument);
- }
-};
+namespace detail {
+
+ template<class Type>
+ struct ConvertFromOpaque {
+ };
+
+ // reference
+
+ template<class T>
+ inline const void *convertToOpaque(const T &t) {
+ return &t;
+ }
+
+ template<class T>
+ struct ConvertFromOpaque<const T &> {
+ static T const &apply(void *p) {
+ return *static_cast<const T *>(p);
+ }
+ };
+
+ template<class T>
+ inline void *convertToOpaque(T &t) {
+ return &t;
+ }
+
+ template<class T>
+ struct ConvertFromOpaque<T &> {
+ static T &apply(void *p) {
+ return *static_cast<T *>( p );
+ }
+ };
+
+ // pointer
+
+ template<class T>
+ inline const void *convertToOpaque(const T *t) {
+ return t;
+ }
+
+ template<class T>
+ struct ConvertFromOpaque<const T *> {
+ static const T *apply(void *p) {
+ return static_cast<const T *>(p);
+ }
+ };
+
+ template<class T>
+ inline void *convertToOpaque(T *t) {
+ return t;
+ }
+
+ template<class T>
+ struct ConvertFromOpaque<T *> {
+ static T *apply(void *p) {
+ return static_cast<T *>(p);
+ }
+ };
+
+ // function pointer
+
+ template<class R, class... Ts>
+ inline const void *convertToOpaque(R(*const &t)(Ts...)) {
+ return &t;
+ }
+
+ template<class R, class... Ts>
+ struct ConvertFromOpaque<R(*const &)(Ts...)> {
+ using Type = R(*)(Ts...);
+
+ static Type const &apply(void *p) {
+ return *static_cast<Type *>(p);
+ }
+ };
+
+ template<class R, class... Ts>
+ inline void *convertToOpaque(R(*&t)(Ts...)) {
+ return &t;
+ }
+
+ template<class R, class... Ts>
+ struct ConvertFromOpaque<R(*&)(Ts...)> {
+ using Type = R(*)(Ts...);
+
+ static Type &apply(void *p) {
+ return *static_cast<Type *>(p);
+ }
+ };
+
+ template<class Caller, class F>
+ class BindFirstOpaqueN;
+
+ template<class Caller, class R, class FirstBound, class... Ts>
+ class BindFirstOpaqueN<Caller, R(FirstBound, Ts...)> {
+ FirstBound firstBound;
+ public:
+ explicit BindFirstOpaqueN(FirstBound firstBound) : firstBound(firstBound) {
+ }
+
+ R operator()(Ts... args) const {
+ return Caller::call(firstBound, args...);
+ }
+
+ FirstBound getBound() const {
+ return firstBound;
+ }
+
+ static R thunk(void *environment, Ts... args) {
+ return thunk_(detail::ConvertFromOpaque<FirstBound>::apply(environment), args...);
+ }
+
+ static R thunk_(FirstBound environment, Ts... args) {
+ return Caller::call(environment, args...);
+ }
+
+ void *getEnvironment() const {
+ return const_cast<void *>(detail::convertToOpaque(firstBound));
+ }
+ };
+}
-typedef Callback1<bool> BoolImportCallback;
-typedef Callback1<const BoolImportCallback&> BoolExportCallback;
+template<class Caller>
+using BindFirstOpaque = detail::BindFirstOpaqueN<Caller, get_func<Caller>>;
-typedef Callback1<int> IntImportCallback;
-typedef Callback1<const IntImportCallback&> IntExportCallback;
+/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer.
+///
+/// Use with the callback constructors MemberCaller0, ConstMemberCaller0, ReferenceCaller0, ConstReferenceCaller0, PointerCaller0, ConstPointerCaller0 and FreeCaller0.
+template<class F>
+class Callback;
-typedef Callback1<float> FloatImportCallback;
-typedef Callback1<const FloatImportCallback&> FloatExportCallback;
+template<class R, class... Ts>
+class Callback<R(Ts...)> : public detail::CallbackBase<R(*)(void *, Ts...)> {
+ using Base = detail::CallbackBase<R (*)(void *, Ts...)>;
-typedef Callback1<const char*> StringImportCallback;
-typedef Callback1<const StringImportCallback&> StringExportCallback;
+ static R nullThunk(void *, Ts...) {
+ }
-typedef Callback1<std::size_t> SizeImportCallback;
-typedef Callback1<const SizeImportCallback&> SizeExportCallback;
+public:
+ using func = R(Ts...);
+ Callback() : Base(0, nullThunk) {
+ }
-/// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function.
-///
-/// \dontinclude generic/callback.cpp
-/// \skipline MemberCaller example
-/// \until end example
-template<typename Environment, void (Environment::*member)()>
-class MemberCaller
-{
- Environment& m_environment;
-public:
- MemberCaller(Environment& environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return &m_environment;
- }
- static void thunk(void* environment)
- {
- ((*reinterpret_cast<Environment*>(environment)).*member)();
- }
- operator Callback() const
- {
- return Callback(getEnvironment(), thunk);
- }
-};
+ template<typename Caller>
+ Callback(const BindFirstOpaque<Caller> &caller) : Base(caller.getEnvironment(), BindFirstOpaque<Caller>::thunk) {
+ }
-/// \brief Forms a Callback from a const Environment reference and a const Environment member-function.
-///
-/// \dontinclude generic/callback.cpp
-/// \skipline MemberCaller example
-/// \until end example
-template<typename Environment, void (Environment::*member)() const>
-class ConstMemberCaller
-{
- const Environment& m_environment;
-public:
- ConstMemberCaller(const Environment& environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return const_cast<Environment*>(&m_environment);
- }
- static void thunk(void* environment)
- {
- ((*reinterpret_cast<const Environment*>(environment)).*member)();
- }
- operator Callback() const
- {
- return Callback(getEnvironment(), thunk);
- }
-};
+ Callback(void *environment, typename Base::Thunk function) : Base(environment, function) {
+ }
-/// \brief Forms a Callback from a non-const Environment reference and a const Environment member-function which takes one argument.
-template<typename Environment, typename FirstArgument, void (Environment::*member)(FirstArgument)>
-class MemberCaller1
-{
- Environment& m_environment;
-public:
- MemberCaller1(Environment& environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return &m_environment;
- }
- static void thunk(void* environment, FirstArgument firstArgument)
- {
- ((*reinterpret_cast<Environment*>(environment)).*member)(firstArgument);
- }
- operator Callback1<FirstArgument>() const
- {
- return Callback1<FirstArgument>(getEnvironment(), thunk);
- }
+ R operator()(Ts... args) const {
+ return Base::getThunk()(Base::getEnvironment(), args...);
+ }
};
-/// \brief Forms a Callback from a const Environment reference and a const Environment member-function which takes one argument.
-template<typename Environment, typename FirstArgument, void (Environment::*member)(FirstArgument) const>
-class ConstMemberCaller1
-{
- const Environment& m_environment;
-public:
- ConstMemberCaller1(const Environment& environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return const_cast<Environment*>(&m_environment);
- }
- static void thunk(void* environment, FirstArgument firstArgument)
- {
- ((*reinterpret_cast<Environment*>(environment)).*member)(firstArgument);
- }
- operator Callback1<FirstArgument>() const
- {
- return Callback1<FirstArgument>(getEnvironment(), thunk);
- }
-};
+namespace detail {
+ template<class F>
+ struct Arglist;
-/// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference.
-///
-/// \dontinclude generic/callback.cpp
-/// \skipline ReferenceCaller example
-/// \until end example
-template<typename Environment, void (*func)(Environment&)>
-class ReferenceCaller
-{
- Environment& m_environment;
-public:
- ReferenceCaller(Environment& environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return &m_environment;
- }
- static void thunk(void* environment)
- {
- (func)(*reinterpret_cast<Environment*>(environment));
- }
- operator Callback() const
- {
- return Callback(getEnvironment(), thunk);
- }
-};
+ template<class R, class Head, class... Ts>
+ struct Arglist<R(Head, Ts...)> {
+ using type = R(Head, Ts...);
-/// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference.
-///
-/// \dontinclude generic/callback.cpp
-/// \skipline ReferenceCaller example
-/// \until end example
-template<typename Environment, void (*func)(const Environment&)>
-class ConstReferenceCaller
-{
- const Environment& m_environment;
-public:
- ConstReferenceCaller(const Environment& environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return const_cast<Environment*>(&m_environment);
- }
- static void thunk(void* environment)
- {
- (func)(*reinterpret_cast<const Environment*>(environment));
- }
- operator Callback() const
- {
- return Callback(getEnvironment(), thunk);
- }
-};
+ template <class Unshift>
+ using unshift = Arglist<R(Unshift, Head, Ts...)>;
-/// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference and one other argument.
-template<typename Environment, typename FirstArgument, void (*func)(Environment&, FirstArgument)>
-class ReferenceCaller1
-{
- Environment& m_environment;
-public:
- ReferenceCaller1(Environment& environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return &m_environment;
- }
- static void thunk(void* environment, FirstArgument firstArgument)
- {
- (func)(*reinterpret_cast<Environment*>(environment), firstArgument);
- }
- operator Callback1<FirstArgument>() const
- {
- return Callback1<FirstArgument>(getEnvironment(), thunk);
- }
-};
+ using shift = Arglist<R(Ts...)>;
+ };
-/// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference and one other argument.
-template<typename Environment, typename FirstArgument, void (*func)(const Environment&, FirstArgument)>
-class ConstReferenceCaller1
-{
- const Environment& m_environment;
-public:
- ConstReferenceCaller1(const Environment& environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return const_cast<Environment*>(&m_environment);
- }
- static void thunk(void* environment, FirstArgument firstArgument)
- {
- (func)(*reinterpret_cast<const Environment*>(environment), firstArgument);
- }
- operator Callback1<FirstArgument>() const
- {
- return Callback1<FirstArgument>(getEnvironment(), thunk);
- }
-};
+ template<class R, class... Ts>
+ struct Arglist<R(Ts...)> {
+ using type = R(Ts...);
-/// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer.
-template<typename Environment, void (*func)(Environment*)>
-class PointerCaller
-{
- Environment* m_environment;
-public:
- PointerCaller(Environment* environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return m_environment;
- }
- static void thunk(void* environment)
- {
- (func)(reinterpret_cast<Environment*>(environment));
- }
- operator Callback() const
- {
- return Callback(getEnvironment(), thunk);
- }
-};
+ template <class Unshift>
+ using unshift = Arglist<R(Unshift, Ts...)>;
+ };
-/// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer.
-template<typename Environment, void (*func)(const Environment*)>
-class ConstPointerCaller
-{
- const Environment* m_environment;
-public:
- ConstPointerCaller(const Environment* environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return const_cast<Environment*>(m_environment);
- }
- static void thunk(void* environment)
- {
- (func)(reinterpret_cast<const Environment*>(environment));
- }
- operator Callback() const
- {
- return Callback(getEnvironment(), thunk);
- }
-};
+ template<class F>
+ using ArgShift = typename detail::Arglist<F>::shift::type;
-/// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer and one other argument.
-template<typename Environment, typename FirstArgument, void (*func)(Environment*, FirstArgument)>
-class PointerCaller1
-{
- Environment* m_environment;
-public:
- PointerCaller1(Environment* environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return m_environment;
- }
- static void thunk(void* environment, FirstArgument firstArgument)
- {
- (func)(reinterpret_cast<Environment*>(environment), firstArgument);
- }
- operator Callback1<FirstArgument>() const
- {
- return Callback1<FirstArgument>(getEnvironment(), thunk);
- }
-};
+ template<class F, class T>
+ using ArgUnshift = typename detail::Arglist<F>::template unshift<T>::type;
+}
-/// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer and one other argument.
-template<typename Environment, typename FirstArgument, void (*func)(const Environment*, FirstArgument)>
-class ConstPointerCaller1
-{
- const Environment* m_environment;
-public:
- ConstPointerCaller1(const Environment* environment) : m_environment(environment)
- {
- }
- void* getEnvironment() const
- {
- return const_cast<Environment*>(m_environment);
- }
- static void thunk(void* environment, FirstArgument firstArgument)
- {
- (func)(reinterpret_cast<const Environment*>(environment), firstArgument);
- }
- operator Callback1<FirstArgument>() const
- {
- return Callback1<FirstArgument>(getEnvironment(), thunk);
- }
-};
+template<typename Caller>
+inline Callback<detail::ArgShift<get_func<Caller>>> makeCallback(const Caller &caller, get_argument<Caller, 0> callee) {
+ return BindFirstOpaque<Caller>(callee);
+}
+template<class Caller, class F>
+class CallerShiftFirst;
-/// \brief Forms a Callback from a free function which takes no arguments.
-template<void (*func)()>
-class FreeCaller
-{
+template<class Caller, class R, class FirstArgument, class... Ts>
+class CallerShiftFirst<Caller, R(FirstArgument, Ts...)> {
public:
- void* getEnvironment() const
- {
- return 0;
- }
- static void thunk(void*)
- {
- (func)();
- }
- operator Callback() const
- {
- return Callback(getEnvironment(), thunk);
- }
-};
+ using func = R(FirstArgument, Ts...);
-/// \brief Forms a Callback from a free function which takes a single argument.
-template<typename FirstArgument, void (*func)(FirstArgument)>
-class FreeCaller1
-{
-public:
- void* getEnvironment() const
- {
- return 0;
- }
- static void thunk(void*, FirstArgument firstArgument)
- {
- (func)(firstArgument);
- }
- operator Callback1<FirstArgument>() const
- {
- return Callback1<FirstArgument>(getEnvironment(), thunk);
- }
+ static R call(FirstArgument, Ts... args) {
+ return Caller::call(args...);
+ }
};
-
-/// \brief Constructs a Callback from a non-const \p functor with zero arguments.
-///
-/// \param Functor Must define \c operator()().
-template<typename Functor>
-inline Callback makeCallback(Functor& functor)
-{
- return Callback(MemberCaller<Functor, &Functor::operator()>(functor));
+template<typename Caller>
+inline Callback<get_func<Caller>> makeStatelessCallback(const Caller &caller) {
+ return makeCallback(CallerShiftFirst<Caller, detail::ArgUnshift<get_func<Caller>, void *>>(), nullptr);
}
-/// \brief Constructs a Callback from a const \p functor with zero arguments.
-///
-/// \param Functor Must define const \c operator()().
-template<typename Functor>
-inline Callback makeCallback(const Functor& functor)
-{
- return Callback(ConstMemberCaller<Functor, &Functor::operator()>(functor));
-}
+/// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function.
+template<class Environment, class F, MemberFunction<Environment, F> member>
+using MemberCaller = BindFirstOpaque<Member<Environment, F, member>>;
-/// \brief Constructs a Callback1 from a non-const \p functor with one argument.
-///
+/// \brief Constructs a Callback1 from a non-const \p functor
+///
/// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type).
template<typename Functor>
-inline Callback1<typename Functor::first_argument_type> makeCallback1(Functor& functor)
-{
- typedef typename Functor::first_argument_type FirstArgument;
- return Callback1<FirstArgument>(MemberCaller1<Functor, FirstArgument, &Functor::operator()>(functor));
+inline Callback<get_func<Functor>> makeCallback(Functor &functor) {
+ return MemberCaller<Functor, get_func<Functor>, &Functor::operator()>(functor);
}
-/// \brief Constructs a Callback1 from a const \p functor with one argument.
-///
+/// \brief Forms a Callback from a const Environment reference and a const Environment member-function.
+template<class Environment, class F, ConstMemberFunction<Environment, F> member>
+using ConstMemberCaller = BindFirstOpaque<ConstMember<Environment, F, member>>;
+
+/// \brief Constructs a Callback1 from a const \p functor
+///
/// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type).
template<typename Functor>
-inline Callback1<typename Functor::first_argument_type> makeCallback1(const Functor& functor)
-{
- typedef typename Functor::first_argument_type FirstArgument;
- return Callback1<FirstArgument>(ConstMemberCaller1<Functor, FirstArgument, &Functor::operator()>(functor));
+inline Callback<get_func<Functor>> makeCallback(const Functor &functor) {
+ return ConstMemberCaller<Functor, get_func<Functor>, &Functor::operator()>(functor);
+}
+
+/// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference.
+template<class Environment, class F, detail::ArgUnshift<F, Environment &> *func>
+using ReferenceCaller = BindFirstOpaque<Function<detail::ArgUnshift<F, Environment &>, func>>;
+
+/// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference.
+template<class Environment, class F, detail::ArgUnshift<F, const Environment &> *func>
+using ConstReferenceCaller = BindFirstOpaque<Function<detail::ArgUnshift<F, const Environment &>, func>>;
+
+/// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer.
+template<class Environment, class F, detail::ArgUnshift<F, Environment *> *func>
+using PointerCaller = BindFirstOpaque<Function<detail::ArgUnshift<F, Environment *>, func>>;
+
+/// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer.
+template<class Environment, class F, detail::ArgUnshift<F, const Environment *> *func>
+using ConstPointerCaller = BindFirstOpaque<Function<detail::ArgUnshift<F, const Environment *>, func>>;
+
+namespace detail {
+ template<class Caller, class F>
+ class FreeCaller : public BindFirstOpaque<CallerShiftFirst<Caller, detail::ArgUnshift<F, void *>>> {
+ public:
+ FreeCaller() : BindFirstOpaque<CallerShiftFirst<Caller, detail::ArgUnshift<F, void *>>>(nullptr) {
+ }
+ };
+
+ template<class F>
+ struct FreeCallerWrapper;
+
+ template<class R, class... Ts>
+ struct FreeCallerWrapper<R(Ts...)> {
+ using func = R(void *, Ts...);
+
+ static R call(void *f, Ts... args) {
+ // ideally, we'd get the implementation of the function type directly. Instead, it's passed in
+ return reinterpret_cast<R(*)(Ts...)>(f)(args...);
+ }
+ };
+}
+
+/// \brief Forms a Callback from a free function
+template<class F, F *func>
+using FreeCaller = detail::FreeCaller<Function<F, func>, F>;
+
+template<class R, class... Ts>
+inline Callback<R(Ts...)> makeCallbackF(R(*func)(Ts...)) {
+ void *pVoid = reinterpret_cast<void *>(func);
+ return BindFirstOpaque<detail::FreeCallerWrapper<R(Ts...)>>(pVoid);
}
#endif