/* Copyright (C) 2008 to 2013 Chris Vine

The library comprised in this file or of which this file is part is
distributed by Chris Vine under the GNU Lesser General Public
License as follows:

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1 of
   the License, or (at your option) any later version.

   This library 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
   Lesser General Public License, version 2.1, for more details.

   You should have received a copy of the GNU Lesser General Public
   License, version 2.1, along with this library (see the file LGPL.TXT
   which came with this source code package in the c++-gtk-utils
   sub-directory); if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

However, it is not intended that the object code of a program whose
source code instantiates a template from this file or uses macros or
inline functions (of any length) should by reason only of that
instantiation or use be subject to the restrictions of use in the GNU
Lesser General Public License.  With that in mind, the words "and
macros, inline functions and instantiations of templates (of any
length)" shall be treated as substituted for the words "and small
macros and small inline functions (ten lines or less in length)" in
the fourth paragraph of section 5 of that licence.  This does not
affect any other reason why object code may be subject to the
restrictions in that licence (nor for the avoidance of doubt does it
affect the application of section 2 of that licence to modifications
of the source code in this file).

*/

#ifndef CGU_CALLBACK_H
#define CGU_CALLBACK_H

/**
 * @file callback.h
 * @brief This file provides classes for type erasure.
 *
 * \#include <c++-gtk-utils/callback.h>
 *
 * These classes provide type erasure on callable objects.  They
 * comprise a generic callback creation and execution interface for
 * closures.  There is a basic Callback::Callback type, which is an
 * entire closure or 'thunk', where all values are bound into the
 * object, and is completely opaque.  Callback::CallbackArg<T...> is a
 * class which takes unbound arguments of the template types when the
 * object is dispatched.  (The opaque Callback::Callback type is a
 * typedef for Callback::CallbackArg<>: the two types are
 * interchangeable.)
 *
 * The classes are normally constructed using the Callback::lambda()
 * factory function, which takes any callable object such as a lambda
 * expression or the return value of std::bind and returns a pointer
 * to a Callback or CallbackArg object.  When using
 * Callback::lambda(), the unbound arguments (if any) must be passed
 * as explicit template parameters.
 *
 * Callback/CallbackArg objects can also be constructed using the
 * Callback::make() and Callback::make_ref() factory functions, which
 * can be useful where invoking standalone functions or object
 * methods.
 *
 * The Callback::make() and Callback::make_ref() functions
 * -------------------------------------------------------
 *
 * The Callback::make() and Callback::make_ref() functions construct a
 * Callback/CallbackArg object from a function pointer (or an object
 * reference and member function pointer) together with bound
 * arguments.  They provide for a maximum of five bound arguments, and
 * the unbound arguments (if any) must be the last (trailing)
 * arguments of the relevant function or method to be called.
 *
 * Callback::make() does a direct type mapping from the bound
 * arguments of the function or method represented by the callback
 * object to the arguments stored by it and is for use when all bound
 * arguments are simple fundamental types such as pointers (including
 * C strings), integers or floating points.
 *
 * Callback::make_ref() is for use where bound arguments include class
 * types or one or more of the types of the bound arguments include a
 * const reference.  It will accomplish perfect forwarding (by lvalue
 * reference or rvalue reference) when constructing the callback and
 * will also ensure that a copy of any object to be passed by const
 * reference (as well as any taken by value) is kept in order to avoid
 * dangling references.  Note however that where a member function is
 * called, the object of which the target function is a member must
 * still be in existence when the Callback/CallbackArg object is
 * dispatched and, unlike Callback::make(), Callback::make_ref()
 * cannot be used with overloaded functions except with explicit
 * disambiguation.
 *
 * Callback::make() can also construct a Callback/CallbackArg object
 * from a std::function object.
 *
 * Callback::FunctorArg and Callback::SafeFunctorArg classes
 * ---------------------------------------------------------
 *
 * Functor/FunctorArg objects hold a Callback/CallbackArg object by
 * SharedPtr to enable them to be shared by reference counting, and
 * SafeFunctor/SafeFunctorArg objects hold them by SharedLockPtr,
 * which have a thread safe reference count so that they may be shared
 * between different threads.  These classes also have an operator()()
 * method so as to be callable with function syntax.
 *
 * Memory allocation
 * -----------------
 *
 * If the library is installed using the
 * \--with-glib-memory-slices-no-compat configuration option, any
 * Callback/CallbackArg object will be constructed in glib memory
 * slices rather than in the generic C++ free store.
 *
 * Usage
 * -----
 *
 * Using Callback::lambda():
 *
 * @code 
 *   using namespace Cgu;
 *
 *   // here cb1 is of type Callback::Callback*
 *   auto cb1 = Callback::lambda<>([] () {std::cout << "Hello world\n";});
 *   cb1->dispatch();
 *   delete cb1;
 *
 *   // the same using Callback::Functor
 *   Callback::Functor f1{Callback::lambda<>([] () {std::cout << "Hello world\n";})};
 *   f1();
 *
 *   // here cb2 is of type Callback::CallbackArg<int, int&>*
 *   auto cb2 = Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;});
 *   int res;
 *   cb2->dispatch(2, res);
 *   std::cout << "10 times 2 is " << res << '\n';
 *   delete cb2;
 *
 *   // the same using Callback::FunctorArg
 *   Callback::FunctorArg<int, int&> f2{Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;})};
 *   f2(2, res);
 *   std::cout << "10 times 2 is " << res << '\n';
 * @endcode
 *
 * Using Callback::make(), with a class object my_obj of type MyClass,
 * with a method void MyClass::my_method(int, int, const char*):
 *
 * @code 
 *   using namespace Cgu;
 *
 *   int arg1 = 1, arg2 = 5;
 *   // here cb1 is of type Callback::Callback*
 *   auto cb1 = Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n");
 *   cb1->dispatch();
 *   delete cb1;
 *
 *   // the same using Callback::Functor
 *   Callback::Functor f{Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n")};
 *   f();
 *
 *   int arg1 = 1, arg2 = 5;
 *   // cb2 is of type Callback::CallbackArg<int, const char*>*
 *   auto cb = Callback::make(my_obj, &MyClass::my_method, arg1);
 *   cb->dispatch(arg2, "Hello\n");
 *   delete cb;
 *
 *   // the same using Callback::FunctorArg
 *   Callback::FunctorArg<int, const char*> f{Callback::make(my_obj, &MyClass::my_method, arg1)};
 *   f(arg2, "Hello\n");
 * @endcode
 *
 * Using Callback::make_ref(), with a class object my_obj of type
 * MyClass, with a method void MyClass::my_method(int, const
 * Something&):
 *
 * @code
 *   int arg1 = 1;
 *   Something arg2;
 *   // here cb is of type Callback::Callback*
 *   auto cb = Callback::make_ref(my_obj, &MyClass::my_method, arg1, arg2);
 * @endcode
 *
 * Posting of callbacks
 * --------------------
 *
 * This file also provides a Callback::post() function which will
 * execute a callback in a glib main loop and can be used (amongst
 * other things) to pass an event from a worker thread to the main
 * program thread.  In that respect, it provides an alternative to the
 * Notifier class.  It is passed either a pointer to a
 * Callback::Callback object created with a call to Callback::lambda()
 * (or Callback::make() or Callback::make_ref()), or it can be passed
 * a callable object and the implementation will call
 * Callback::lambda() for you.
 *
 * To provide for thread-safe automatic disconnection of the callback
 * if the callback represents or calls into a non-static method of an
 * object which may be destroyed before the callback executes in the
 * main loop, include a Releaser as a public member of that object and
 * pass the Releaser object as the second argument of
 * Callback::post().  Note that for this to be race free, the lifetime
 * of the remote object whose method is to be invoked must be
 * determined by the thread to whose main loop the callback has been
 * attached.  When the main loop begins invoking the execution of the
 * callback, the remote object must either wholly exist (in which case
 * the callback will be invoked) or have been destroyed (in which case
 * the callback will be ignored), and not be in some transient
 * half-state governed by another thread.
 *
 * Advantages as against Notifier:
 * 
 * 1. If there are a lot of different events requiring callbacks to be
 *    dispatched in the program from worker threads to the main
 *    thread, this avoids having separate Notifier objects for each
 *    event.
 * 2. It is easier to pass arguments with varying values - they can be
 *    passed as bound arguments of the callback and no special
 *    synchronisation is normally required (the call to
 *    g_source_attach() invokes locking of the main loop which will
 *    have the effect of ensuring memory visibility).  With a Notifier
 *    object it may be necessary to use an asynchronous queue to pass
 *    variable values (or to bind a reference to the data, thus
 *    normally requiring separate synchronisation).
 * 3. Although the callback would normally be sent for execution by
 *    the main program loop, and that is the default, it can be sent
 *    for execution by any thread which has its own
 *    GMainContext/GMainLoop objects.  Thus callbacks can be passed
 *    for execution between worker threads, or from the main program
 *    thread to worker threads, as well as from worker threads to the
 *    main program thread.
 *
 * Disadvantages as against Notifier:
 *
 * 1. Less efficient, as a new callback object has to be created on
 *    freestore every time the callback is invoked, together with a
 *    new SafeEmitter object if a Releaser is used to track the
 *    callback.
 * 2. Multiple callbacks relevant to a single event cannot be invoked
 *    from a single call for the event - each callback has to be
 *    separately dispatched.
 */

/**
 * @namespace Cgu::Callback
 * @brief This namespace provides classes for type erasure.
 *
 * \#include <c++-gtk-utils/callback.h>
 *
 * These classes provide type erasure on callable objects.  They
 * comprise a generic callback creation and execution interface for
 * closures.  There is a basic Callback::Callback type, which is an
 * entire closure or 'thunk', where all values are bound into the
 * object, and is completely opaque.  Callback::CallbackArg<T...> is a
 * class which takes unbound arguments of the template types when the
 * object is dispatched.  (The opaque Callback::Callback type is a
 * typedef for Callback::CallbackArg<>: the two types are
 * interchangeable.)
 *
 * The classes are normally constructed using the Callback::lambda()
 * factory function, which takes any callable object such as a lambda
 * expression or the return value of std::bind and returns a pointer
 * to a Callback or CallbackArg object.  When using
 * Callback::lambda(), the unbound arguments (if any) must be passed
 * as explicit template parameters.
 *
 * Callback/CallbackArg objects can also be constructed using the
 * Callback::make() and Callback::make_ref() factory functions, which
 * can be useful where invoking standalone functions or object
 * methods.
 *
 * The Callback::make() and Callback::make_ref() functions
 * -------------------------------------------------------
 *
 * The Callback::make() and Callback::make_ref() functions construct a
 * Callback/CallbackArg object from a function pointer (or an object
 * reference and member function pointer) together with bound
 * arguments.  They provide for a maximum of five bound arguments, and
 * the unbound arguments (if any) must be the last (trailing)
 * arguments of the relevant function or method to be called.
 *
 * Callback::make() does a direct type mapping from the bound
 * arguments of the function or method represented by the callback
 * object to the arguments stored by it and is for use when all bound
 * arguments are simple fundamental types such as pointers (including
 * C strings), integers or floating points.
 *
 * Callback::make_ref() is for use where bound arguments include class
 * types or one or more of the types of the bound arguments include a
 * const reference.  It will accomplish perfect forwarding (by lvalue
 * reference or rvalue reference) when constructing the callback and
 * will also ensure that a copy of any object to be passed by const
 * reference (as well as any taken by value) is kept in order to avoid
 * dangling references.  Note however that where a member function is
 * called, the object of which the target function is a member must
 * still be in existence when the Callback/CallbackArg object is
 * dispatched and, unlike Callback::make(), Callback::make_ref()
 * cannot be used with overloaded functions except with explicit
 * disambiguation.
 *
 * Callback::make() can also construct a Callback/CallbackArg object
 * from a std::function object.
 *
 * Callback::FunctorArg and Callback::SafeFunctorArg classes
 * ---------------------------------------------------------
 *
 * Functor/FunctorArg objects hold a Callback/CallbackArg object by
 * SharedPtr to enable them to be shared by reference counting, and
 * SafeFunctor/SafeFunctorArg objects hold them by SharedLockPtr,
 * which have a thread safe reference count so that they may be shared
 * between different threads.  These classes also have an operator()()
 * method so as to be callable with function syntax.
 *
 * Memory allocation
 * -----------------
 *
 * If the library is installed using the
 * \--with-glib-memory-slices-no-compat configuration option, any
 * Callback/CallbackArg object will be constructed in glib memory
 * slices rather than in the generic C++ free store.
 *
 * Usage
 * -----
 *
 * Using Callback::lambda():
 *
 * @code 
 *   using namespace Cgu;
 *
 *   // here cb1 is of type Callback::Callback*
 *   auto cb1 = Callback::lambda<>([] () {std::cout << "Hello world\n";});
 *   cb1->dispatch();
 *   delete cb1;
 *
 *   // the same using Callback::Functor
 *   Callback::Functor f1{Callback::lambda<>([] () {std::cout << "Hello world\n";})};
 *   f1();
 *
 *   // here cb2 is of type Callback::CallbackArg<int, int&>*
 *   auto cb2 = Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;});
 *   int res;
 *   cb2->dispatch(2, res);
 *   std::cout << "10 times 2 is " << res << '\n';
 *   delete cb2;
 *
 *   // the same using Callback::FunctorArg
 *   Callback::FunctorArg<int, int&> f2{Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;})};
 *   f2(2, res);
 *   std::cout << "10 times 2 is " << res << '\n';
 * @endcode
 *
 * Using Callback::make(), with a class object my_obj of type MyClass,
 * with a method void MyClass::my_method(int, int, const char*):
 *
 * @code 
 *   using namespace Cgu;
 *
 *   int arg1 = 1, arg2 = 5;
 *   // here cb1 is of type Callback::Callback*
 *   auto cb1 = Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n");
 *   cb1->dispatch();
 *   delete cb1;
 *
 *   // the same using Callback::Functor
 *   Callback::Functor f{Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n")};
 *   f();
 *
 *   int arg1 = 1, arg2 = 5;
 *   // cb2 is of type Callback::CallbackArg<int, const char*>*
 *   auto cb = Callback::make(my_obj, &MyClass::my_method, arg1);
 *   cb->dispatch(arg2, "Hello\n");
 *   delete cb;
 *
 *   // the same using Callback::FunctorArg
 *   Callback::FunctorArg<int, const char*> f{Callback::make(my_obj, &MyClass::my_method, arg1)};
 *   f(arg2, "Hello\n");
 * @endcode
 *
 * Using Callback::make_ref(), with a class object my_obj of type
 * MyClass, with a method void MyClass::my_method(int, const
 * Something&):
 *
 * @code
 *   int arg1 = 1;
 *   Something arg2;
 *   // here cb is of type Callback::Callback*
 *   auto cb = Callback::make_ref(my_obj, &MyClass::my_method, arg1, arg2);
 * @endcode
 *
 * Posting of callbacks
 * --------------------
 *
 * This namespace also provides a Callback::post() function which will
 * execute a callback in a glib main loop and can be used (amongst
 * other things) to pass an event from a worker thread to the main
 * program thread.  In that respect, it provides an alternative to the
 * Notifier class.  It is passed either a pointer to a
 * Callback::Callback object created with a call to Callback::lambda()
 * (or Callback::make() or Callback::make_ref()), or it can be passed
 * a callable object and the implementation will call
 * Callback::lambda() for you.
 *
 * To provide for thread-safe automatic disconnection of the callback
 * if the callback represents or calls into a non-static method of an
 * object which may be destroyed before the callback executes in the
 * main loop, include a Releaser as a public member of that object and
 * pass the Releaser object as the second argument of
 * Callback::post().  Note that for this to be race free, the lifetime
 * of the remote object whose method is to be invoked must be
 * determined by the thread to whose main loop the callback has been
 * attached.  When the main loop begins invoking the execution of the
 * callback, the remote object must either wholly exist (in which case
 * the callback will be invoked) or have been destroyed (in which case
 * the callback will be ignored), and not be in some transient
 * half-state governed by another thread.
 *
 * Advantages as against Notifier:
 * 
 * 1. If there are a lot of different events requiring callbacks to be
 *    dispatched in the program from worker threads to the main
 *    thread, this avoids having separate Notifier objects for each
 *    event.
 * 2. It is easier to pass arguments with varying values - they can be
 *    passed as bound arguments of the callback and no special
 *    synchronisation is normally required (the call to
 *    g_source_attach() invokes locking of the main loop which will
 *    have the effect of ensuring memory visibility).  With a Notifier
 *    object it may be necessary to use an asynchronous queue to pass
 *    variable values (or to bind a reference to the data, thus
 *    normally requiring separate synchronisation).
 * 3. Although the callback would normally be sent for execution by
 *    the main program loop, and that is the default, it can be sent
 *    for execution by any thread which has its own
 *    GMainContext/GMainLoop objects.  Thus callbacks can be passed
 *    for execution between worker threads, or from the main program
 *    thread to worker threads, as well as from worker threads to the
 *    main program thread.
 *
 * Disadvantages as against Notifier:
 *
 * 1. Less efficient, as a new callback object has to be created on
 *    freestore every time the callback is invoked, together with a
 *    new SafeEmitter object if a Releaser is used to track the
 *    callback.
 * 2. Multiple callbacks relevant to a single event cannot be invoked
 *    from a single call for the event - each callback has to be
 *    separately dispatched.
 */

#include <functional>  // for std::less, std::function and std::hash<T*>
#include <utility>     // for std::move and std::forward
#include <cstddef>     // for std::size_t
#include <type_traits> // for std::remove_reference, std::remove_const and std::enable_if

#include <glib.h>

#include <c++-gtk-utils/shared_ptr.h>
#include <c++-gtk-utils/param.h>
#include <c++-gtk-utils/cgu_config.h>

namespace Cgu {

namespace Callback {

/*
   The CallbackArg class could be additionally templated to provide a
   return value, but that would affect the simplicity of the
   interface, and if a case were to arise where a result is needed, an
   alternative is for users to pass an argument by reference or
   pointer (or pointer to pointer) rather than have a return value.
*/

/* Declare the two basic interface types */

template <class... FreeArgs> class CallbackArg;
typedef CallbackArg<> Callback;

/* now the class definitions */

/**
 * @class CallbackArg callback.h c++-gtk-utils/callback.h
 * @brief The callback interface class
 * @sa Callback namespace
 * @sa FunctorArg SafeFunctorArg
 *
 * This class provides type erasure for callable objects.  The
 * CallbackArg type is constructed on free store and can wrap any
 * callable object, such as a lambda expression or the return value of
 * std::bind.
 *
 * The class is particularly relevant where a callable object with
 * bound values needs to be handed safely between threads, or in other
 * cases where a callback object has to be passed by pointer (which
 * will happen at some stage with glib or pthreads).  They are
 * therefore useful for general event passing when used together with
 * the Callback::post() functions or as the continuation for GIO async
 * operations, and are more efficient than constructing std::function
 * objects on free store and passing them by pointer (they avoid one
 * level of indirection and only require one rather than two
 * allocations).
 *
 * The classes are also used in the Emitter/EmitterArg and
 * SafeEmitter/SafeEmitterArg classes in emitter.h, which enable
 * callable objects to be connected to an emitter and provide for
 * automatic disconnection where a class object whose member a
 * callback represents or calls into ceases to exist.  They are also
 * used internally to implement the Thread::Future and
 * Thread::TaskManager classes.
 * 
 * The template types are the types of the unbound arguments, if any.
 * Callback::CallbackArg<> is typedef'ed to Callback::Callback.  The
 * main method of constructing a Callback/CallbackArg object is with
 * the Callback::lambda() factory function.  When using
 * Callback::lambda(), the unbound arguments (if any) must be passed
 * as explicit template parameters.
 *
 * Callback/CallbackArg classes do not provide for a return value.  If
 * a result is wanted, users should pass an unbound argument by
 * reference or pointer (or pointer to pointer).
 *
 * The 2.2 series of the library generally dispenses with the need to
 * create objects explicitly using Callback::lambda() when calling
 * into the library itself: all the library interfaces which take a
 * Callback/CallbackArg object also now provide an overload which
 * takes any callable object as a template type, and the
 * implementation calls Callback::lambda() internally for you.
 *
 * @b Usage
 *
 * These are examples:
 *
 * @code 
 *   using namespace Cgu;
 *
 *   // here cb1 is of type Callback::Callback*
 *   auto cb1 = Callback::lambda<>([] () {std::cout << "Hello world\n";});
 *   cb1->dispatch();
 *   delete cb1;
 *
 *   // here cb2 is of type Callback::CallbackArg<int, int&>*
 *   auto cb2 = Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;});
 *   int res;
 *   cb2->dispatch(2, res);
 *   std::cout << "10 times 2 is " << res << '\n';
 *   delete cb2;
 * @endcode
 *
 * For further background, including about the Callback::make(),
 * Callback::make_ref() functions, read this: Callback
 */

template <class... FreeArgs>
class CallbackArg {
public:
/* Because dispatch() is a virtual function, we cannot templatise it
 * with a view to preserving r-value forwarding of temporary objects
 * passed as a free argument.  But this would rarely be relevant
 * anyway - it would only be relevant if the target function were to
 * take an argument by r-value reference and a temporary were to be
 * passed to it.  In such a case virtual dispatch is at the cost of a
 * copy of the temporary.
 */
/**
 * This will execute the referenced function, callable object or class
 * method encapsulated by this class.  It will only throw if the
 * dispatched function, callable object or class method throws, or if
 * the copy constructor of a free or bound argument throws and it is
 * not a reference argument.  It is thread safe if the referenced
 * function or class method is thread safe.
 * @param args The unbound arguments to be passed to the referenced
 * function, callable object or class method, if any.
 * @note We use dispatch() to execute the callback, because the
 * callback would normally be invoked through a base class pointer.
 * To invoke it through operator()(), use the FunctorArg or
 * SafeFunctorArg wrapper class.
 */
  virtual void dispatch(typename Cgu::Param<FreeArgs>::ParamType... args) const = 0;

/**
 *  The constructor will not throw unless the copy constructor of an
 *  argument bound to the derived implementation class throws.
 */
  CallbackArg() {}

/**
 *  The destructor will not throw unless the destructor of an argument
 *  bound to the derived implementation class throws.
 */
  virtual ~CallbackArg() {}

/* these functions will be inherited by the derived callback classes */
#ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
  CGU_GLIB_MEMORY_SLICES_FUNCS
#endif
};

/* The four basic functor types */

template <class... FreeArgs> class FunctorArg;
template <class... FreeArgs> class SafeFunctorArg;
typedef FunctorArg<> Functor;
typedef SafeFunctorArg<> SafeFunctor;

/* Functor friend functions */

// we can use built-in operator == when comparing pointers referencing
// different objects of the same type
/**
 * Two FunctorArg objects compare equal if the addresses of the
 * CallbackArg objects they contain are the same.  This comparison
 * operator does not throw.
 */
template <class... T>
bool operator==(const FunctorArg<T...>& f1, const FunctorArg<T...>& f2) {
  return (f1.cb_s.get() == f2.cb_s.get());
}

/**
 * Two FunctorArg objects compare unequal if the addresses of the
 * CallbackArg objects they contain are not the same.  This comparison
 * operator does not throw.
 */
template <class... T>
bool operator!=(const FunctorArg<T...>& f1, const FunctorArg<T...>& f2) {
  return !(f1 == f2);
}

// we must use std::less rather than the < built-in operator for
// pointers to objects not within the same array or object: "For
// templates greater, less, greater_equal, and less_equal, the
// specializations for any pointer type yield a total order, even if
// the built-in operators <, >, <=, >= do not." (para 20.3.3/8).
/**
 * One FunctorArg object is less than another if the address of the
 * CallbackArg object contained by the first is regarded by std::less
 * as less than the address of the CallbackArg object contained by the
 * other.  This comparison operator does not throw.
 */
template <class... T>
bool operator<(const FunctorArg<T...>& f1, const FunctorArg<T...>& f2) {
  return std::less<const CallbackArg<T...>*>()(f1.cb_s.get(), f2.cb_s.get());
}

/**
 * Two SafeFunctorArg objects compare equal if the addresses of the
 * CallbackArg objects they contain are the same.  This comparison
 * operator does not throw.
 */
template <class... T>
bool operator==(const SafeFunctorArg<T...>& f1, const SafeFunctorArg<T...>& f2) {
  return (f1.cb_s.get() == f2.cb_s.get());
}

/**
 * Two SafeFunctorArg objects compare unequal if the addresses of the
 * CallbackArg objects they contain are not the same.  This comparison
 * operator does not throw.
 */
template <class... T>
bool operator!=(const SafeFunctorArg<T...>& f1, const SafeFunctorArg<T...>& f2) {
  return !(f1 == f2);
}

/**
 * One SafeFunctorArg object is less than another if the address of
 * the CallbackArg object contained by the first is regarded by
 * std::less as less than the address of the CallbackArg object
 * contained by the other.  This comparison operator does not throw.
 */
template <class... T>
bool operator<(const SafeFunctorArg<T...>& f1, const SafeFunctorArg<T...>& f2) {
  return std::less<const CallbackArg<T...>*>()(f1.cb_s.get(), f2.cb_s.get());
}

} // namespace Callback
} // namespace Cgu

// doxygen produces long filenames that tar can't handle:
// we have generic documentation for std::hash specialisations
// in doxygen.main.in
#ifndef DOXYGEN_PARSING

/* These structs allow FunctorArg and SafeFunctorArg objects to be
   keys in unordered associative containers */
namespace std {
template <class... T>
struct hash<Cgu::Callback::FunctorArg<T...>> {
  typedef std::size_t result_type;
  typedef Cgu::Callback::FunctorArg<T...> argument_type;
  result_type operator()(const argument_type& f) const {
    // this is fine: std::hash structs do not normally contain data and
    // std::hash<T*> certainly won't, so we don't have overhead constructing
    // std::hash<T*> on the fly
    return std::hash<const Cgu::Callback::CallbackArg<T...>*>()(f.cb_s.get());
  }
};
template <class... T>
struct hash<Cgu::Callback::SafeFunctorArg<T...>> {
  typedef std::size_t result_type;
  typedef Cgu::Callback::SafeFunctorArg<T...> argument_type;
  result_type operator()(const argument_type& f) const {
    // this is fine: std::hash structs do not normally contain data and
    // std::hash<T*> certainly won't, so we don't have overhead constructing
    // std::hash<T*> on the fly
    return std::hash<const Cgu::Callback::CallbackArg<T...>*>()(f.cb_s.get());
  }
};
} // namespace std

#endif // DOXYGEN_PARSING

namespace Cgu {
namespace Callback {

/* the functor classes */

/**
 * @class FunctorArg callback.h c++-gtk-utils/callback.h
 * @brief Functor class holding a Callback::CallbackArg object.
 * @sa SafeFunctorArg
 * @sa Callback namespace
 *
 * This class wraps a CallbackArg object.  The callback object is kept
 * by SharedPtr so the functor can be copied and offers automatic
 * lifetime management of the wrapped callback object, as well as
 * providing an operator()() function.  Ownership is taken of the
 * CallbackArg object passed to the constructor taking a CallbackArg
 * pointer, so that constructor should be treated like a shared
 * pointer constructor - only pass a newly allocated object to it (or
 * copy construct it or assign to it from another existing FunctorArg
 * object).  The template types are the types of the unbound
 * arguments, if any.  Callback::FunctorArg<> is typedef'ed to
 * Callback::Functor.
 *
 * The constructor taking a Callback::CallbackArg pointer is not
 * marked explicit, so the results of Callback::lambda(),
 * Callback::make() or Callback::make_ref() can be passed directly to
 * a function taking a Callback::FunctorArg argument, and implicit
 * conversion will take place.
 *
 * Functor/FunctorArg classes do not provide for a return value.  If
 * a result is wanted, users should pass an unbound argument by
 * reference or pointer (or pointer to pointer).
 *
 * @b Usage
 *
 * These are examples:
 *
 * @code 
 *   using namespace Cgu;
 *
 *   Callback::Functor f1{Callback::lambda<>([] () {std::cout << "Hello world\n";})};
 *   f1();
 *
 *   int res;
 *   Callback::FunctorArg<int, int&> f2{Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;})};
 *   f2(2, res);
 *   std::cout << "10 times 2 is " << res << '\n';
 * @endcode
 *
 * For further background, including about the Callback::make(),
 * Callback::make_ref() functions, read this: Callback
 */

template <class... FreeArgs>
class FunctorArg {
  SharedPtr<const CallbackArg<FreeArgs...>> cb_s;
public:
/* Because CallbackArg::dispatch() is a virtual function, it is
 * pointless templatising this function with a view to preserving
 * r-value forwarding of temporary objects passed as a free argument,
 * because the r-value typeness will be discarded in dispatch().  But
 * this would rarely be relevant anyway - it would only be relevant if
 * the target function were to take an argument by r-value reference
 * and a temporary were to be passed to it.  In such a case virtual
 * dispatch is at the cost of a copy of the temporary.
 */
/**
 * This will execute the function, callable object or class method
 * represented by the callback encapsulated by this object, or do
 * nothing if this object has not been initialized with a callback.
 * It will only throw if the executed function, callable object or
 * class method throws, or if the copy constructor of a free or bound
 * argument throws and it is not a reference argument.  It is thread
 * safe if the referenced function or class method is thread safe.
 * @param args The unbound arguments to be passed to the referenced
 * function, callable object or class method, if any.
 */
  void operator()(typename Cgu::Param<FreeArgs>::ParamType... args) const {
    if (cb_s.get()) cb_s->dispatch(args...);
  }

/** 
 * This function does not throw.
 * @param f The assignor.
 * @return The functor object after assignment.
 */ 
  FunctorArg& operator=(const FunctorArg& f) {cb_s = f.cb_s; return *this;}

/** 
 * This function does not throw.
 * @param f The functor to be moved.
 * @return The functor object after the move operation.
 */ 
  FunctorArg& operator=(FunctorArg&& f) {cb_s = std::move(f.cb_s); return *this;}

/**
 * Two FunctorArg objects compare equal if the addresses of the
 * CallbackArg objects they contain are the same.  This comparison
 * operator does not throw.
 */
  friend bool operator== <>(const FunctorArg&, const FunctorArg&);

/**
 * One FunctorArg object is less than another if the address of the
 * CallbackArg object contained by the first is regarded by std::less
 * as less than the address of the CallbackArg object contained by the
 * other.  This comparison operator does not throw.
 */
  friend bool operator< <>(const FunctorArg&, const FunctorArg&);

  friend struct std::hash<FunctorArg>;

/**
 * Constructor of first FunctorArg holding the referenced callback.
 * As it is not marked explicit, it is also a type conversion
 * constructor.
 * @param cb The CallbackArg object which the functor is to manage.
 * @exception std::bad_alloc This might throw std::bad_alloc if
 * memory is exhausted and the system throws in that case.  Note that
 * if such an exception is thrown, then this constructor will clean
 * itself up and also delete the callback object passed to it.
 * @note std::bad_alloc will not be thrown if the library has been
 * installed using the \--with-glib-memory-slices-no-compat
 * configuration option: instead glib will terminate the program if it
 * is unable to obtain memory from the operating system.
 */
  FunctorArg(const CallbackArg<FreeArgs...>* cb): cb_s(cb) {}

/** 
 * The copy constructor does not throw.
 * @param f The assignor
 */ 
  FunctorArg(const FunctorArg& f): cb_s(f.cb_s) {}

/** 
 * The move constructor does not throw.
 * @param f The functor to be moved.
 */ 
  FunctorArg(FunctorArg&& f): cb_s(std::move(f.cb_s)) {}

 /**
  * Default constructor, where a Callback::CallbackArg object is to be
  * assigned later (via the type conversion constructor and/or the
  * assignment operator).  This constructor does not throw.
  */
  FunctorArg() {}

/* Only has effect if --with-glib-memory-slices-compat or
   --with-glib-memory-slices-no-compat option picked */
  CGU_GLIB_MEMORY_SLICES_FUNCS
};

/**
 * @class SafeFunctorArg callback.h c++-gtk-utils/callback.h
 * @brief Functor class holding a Callback::CallbackArg object, with
 * thread-safe reference count.
 * @sa FunctorArg
 * @sa Callback namespace
 *
 * This class is the same as Callback::FunctorArg except that it will
 * provide synchronisation of the reference count between threads.
 * Use it where a functor wrapper object is to be passed between
 * threads.  The FunctorArg documentation gives details on usage.
 *
 * Callback::SafeFunctorArg<> is typedef'ed to Callback::SafeFunctor.
 *
 * For further background, read this: Callback
 */

template <class... FreeArgs>
class SafeFunctorArg {
  SharedLockPtr<const CallbackArg<FreeArgs...>> cb_s;
public:
/**
 * This will execute the function, callable object or class method
 * represented by the callback encapsulated by this object, or do
 * nothing if this object has not been initialized with a callback.
 * It will only throw if the executed function, callable object or
 * class method throws, or if the copy constructor of a free or bound
 * argument throws and it is not a reference argument.  It is thread
 * safe if the referenced function or class method is thread safe.
 * @param args The unbound arguments to be passed to the referenced
 * function, callable object or class method, if any.
 */
  void operator()(typename Cgu::Param<FreeArgs>::ParamType... args) const {
    if (cb_s.get()) cb_s->dispatch(args...);
  }

/** 
 * This function does not throw.
 * @param f The assignor.
 * @return The functor object after assignment.
 */ 
  SafeFunctorArg& operator=(const SafeFunctorArg& f) {cb_s = f.cb_s; return *this;}

/** 
 * This function does not throw.
 * @param f The functor to be moved.
 * @return The functor object after the move operation.
 */ 
  SafeFunctorArg& operator=(SafeFunctorArg&& f) {cb_s = std::move(f.cb_s); return *this;}

/**
 * Two SafeFunctorArg objects compare equal if the addresses of the
 * CallbackArg objects they contain are the same.  This comparison
 * operator does not throw.
 */
  friend bool operator== <>(const SafeFunctorArg&, const SafeFunctorArg&);

/**
 * One SafeFunctorArg object is less than another if the address of
 * the CallbackArg object contained by the first is regarded by
 * std::less as less than the address of the CallbackArg object
 * contained by the other.  This comparison operator does not throw.
 */
  friend bool operator< <>(const SafeFunctorArg&, const SafeFunctorArg&);

  friend struct std::hash<SafeFunctorArg>;

 /**
 * Constructor of first SafeFunctorArg holding the referenced
 * callback.  As it is not marked explicit, it is also a type
 * conversion constructor.
 * @param cb The CallbackArg object which the functor is to manage.
 * @exception std::bad_alloc This might throw std::bad_alloc if
 * memory is exhausted and the system throws in that case.  Note that
 * if such an exception is thrown, then this constructor will clean
 * itself up and also delete the callback object passed to it.
 * @note std::bad_alloc will not be thrown if the library has been
 * installed using the \--with-glib-memory-slices-no-compat
 * configuration option: instead glib will terminate the program if it
 * is unable to obtain memory from the operating system.
 */
  SafeFunctorArg(const CallbackArg<FreeArgs...>* cb): cb_s(cb) {}

/** 
 * The copy constructor does not throw.
 * @param f The assignor.
 */ 
  SafeFunctorArg(const SafeFunctorArg& f): cb_s(f.cb_s) {}

/** 
 * The move constructor does not throw.
 * @param f The functor to be moved.
 */ 
  SafeFunctorArg(SafeFunctorArg&& f): cb_s(std::move(f.cb_s)) {}

 /**
  * Default constructor, where a Callback::CallbackArg object is to be
  * assigned later (via the type conversion constructor and/or the
  * assignment operator).  This constructor does not throw.
  * @note The reference count maintained with respect to the contained
  * callback object is thread-safe, so SafeFunctorArg objects may be
  * copied between threads by the implicit assignment operator and put
  * in different containers in different threads.  They use a
  * SharedLockPtr object to hold the referenced callback object.
  */
  SafeFunctorArg() {}

/* Only has effect if --with-glib-memory-slices-compat or
   --with-glib-memory-slices-no-compat option picked */
  CGU_GLIB_MEMORY_SLICES_FUNCS
};

/* the callback implementation classes */

template <class T, class... FreeArgs>
class Callback0: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(FreeArgs...);
private:
  T* obj;
  MemFunc func;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(free_args...);
  }
  Callback0(T& obj_, MemFunc func_): obj(&obj_), func(func_) {}
};

template <bool unref, class T, class BoundArg, class... FreeArgs>
class Callback1: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg, FreeArgs...);
private:
  T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg, unref>::Type arg;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg, free_args...);
  }
  template <class Arg>
  Callback1(T& obj_, MemFunc func_,
	    Arg&& arg_): obj(&obj_), func(func_), arg(std::forward<Arg>(arg_)) {}
};

template <bool unref, class T, class BoundArg1, class BoundArg2, class... FreeArgs>
class Callback2: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg1, BoundArg2, FreeArgs...);
private:
  T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg1, arg2, free_args...);
  }
  template <class Arg1, class Arg2>
  Callback2(T& obj_, MemFunc func_,
	    Arg1&& arg1_,
	    Arg2&& arg2_): obj(&obj_), func(func_),
                           arg1(std::forward<Arg1>(arg1_)),
                           arg2(std::forward<Arg2>(arg2_)) {}
};

template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
class Callback3: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...);
private:
  T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg1, arg2, arg3, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3>
  Callback3(T& obj_, MemFunc func_,
	    Arg1&& arg1_,
	    Arg2&& arg2_,
	    Arg3&& arg3_):
              obj(&obj_), func(func_),
	      arg1(std::forward<Arg1>(arg1_)),
	      arg2(std::forward<Arg2>(arg2_)),
	      arg3(std::forward<Arg3>(arg3_)) {}
};

template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3, 
          class BoundArg4, class... FreeArgs>
class Callback4: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...);
private:
  T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
  typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg1, arg2, arg3, arg4, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3, class Arg4>
  Callback4(T& obj_, MemFunc func_,
	    Arg1&& arg1_,
	    Arg2&& arg2_,
	    Arg3&& arg3_,
	    Arg4&& arg4_):
              obj(&obj_), func(func_),
	      arg1(std::forward<Arg1>(arg1_)),
	      arg2(std::forward<Arg2>(arg2_)),
	      arg3(std::forward<Arg3>(arg3_)),
	      arg4(std::forward<Arg4>(arg4_)) {}
};

template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3, 
          class BoundArg4, class BoundArg5, class... FreeArgs>
class Callback5: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3,
			      BoundArg4, BoundArg5, FreeArgs...);
private:
  T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
  typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
  typename Cgu::RemoveRefCond<BoundArg5, unref>::Type arg5;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg1, arg2, arg3, arg4, arg5, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
  Callback5(T& obj_, MemFunc func_,
	    Arg1&& arg1_,
	    Arg2&& arg2_,
	    Arg3&& arg3_,
	    Arg4&& arg4_,
	    Arg5&& arg5_):
              obj(&obj_), func(func_),
	      arg1(std::forward<Arg1>(arg1_)),
	      arg2(std::forward<Arg2>(arg2_)),
	      arg3(std::forward<Arg3>(arg3_)),
	      arg4(std::forward<Arg4>(arg4_)),
	      arg5(std::forward<Arg5>(arg5_)) {}
};

/* const versions, for binding to const methods */

template <class T, class... FreeArgs>
class Callback0_const: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(FreeArgs...) const;
private:
  const T* obj;
  MemFunc func;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(free_args...);
  }
  Callback0_const(const T& obj_, MemFunc func_): obj(&obj_), func(func_) {}
};

template <bool unref, class T, class BoundArg, class... FreeArgs>
class Callback1_const: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg, FreeArgs...) const;
private:
  const T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg, unref>::Type arg;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg, free_args...);
  }
  template <class Arg>
  Callback1_const(const T& obj_, MemFunc func_,
		  Arg&& arg_): obj(&obj_), func(func_), arg(std::forward<Arg>(arg_)) {}
};

template <bool unref, class T, class BoundArg1, class BoundArg2, class... FreeArgs>
class Callback2_const: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg1, BoundArg2, FreeArgs...) const;
private:
  const T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg1, arg2, free_args...);
  }
  template <class Arg1, class Arg2>
  Callback2_const(const T& obj_, MemFunc func_,
		  Arg1&& arg1_,
		  Arg2&& arg2_): obj(&obj_), func(func_),
                                 arg1(std::forward<Arg1>(arg1_)),
                                 arg2(std::forward<Arg2>(arg2_)) {}
};

template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
class Callback3_const: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const;
private:
  const T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg1, arg2, arg3, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3>
  Callback3_const(const T& obj_, MemFunc func_,
		  Arg1&& arg1_,
		  Arg2&& arg2_,
		  Arg3&& arg3_):
                    obj(&obj_), func(func_),
		    arg1(std::forward<Arg1>(arg1_)),
		    arg2(std::forward<Arg2>(arg2_)),
		    arg3(std::forward<Arg3>(arg3_)) {}
};

template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3, 
          class BoundArg4, class... FreeArgs>
class Callback4_const: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...) const;
private:
  const T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
  typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg1, arg2, arg3, arg4, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3, class Arg4>
  Callback4_const(const T& obj_, MemFunc func_,
		  Arg1&& arg1_,
		  Arg2&& arg2_,
		  Arg3&& arg3_,
		  Arg4&& arg4_):
                    obj(&obj_), func(func_),
		    arg1(std::forward<Arg1>(arg1_)),
		    arg2(std::forward<Arg2>(arg2_)),
		    arg3(std::forward<Arg3>(arg3_)),
		    arg4(std::forward<Arg4>(arg4_)) {}
};

template <bool unref, class T, class BoundArg1, class BoundArg2, class BoundArg3, 
          class BoundArg4, class BoundArg5, class... FreeArgs>
class Callback5_const: public CallbackArg<FreeArgs...> {
public:
  typedef void (T::* MemFunc)(BoundArg1, BoundArg2, BoundArg3,
			      BoundArg4, BoundArg5, FreeArgs...) const;
private:
  const T* obj;
  MemFunc func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
  typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
  typename Cgu::RemoveRefCond<BoundArg5, unref>::Type arg5;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    (obj->*func)(arg1, arg2, arg3, arg4, arg5, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
  Callback5_const(const T& obj_, MemFunc func_,
		  Arg1&& arg1_,
		  Arg2&& arg2_,
		  Arg3&& arg3_,
		  Arg4&& arg4_,
		  Arg5&& arg5_):
                    obj(&obj_), func(func_),
		    arg1(std::forward<Arg1>(arg1_)),
		    arg2(std::forward<Arg2>(arg2_)),
		    arg3(std::forward<Arg3>(arg3_)),
		    arg4(std::forward<Arg4>(arg4_)),
		    arg5(std::forward<Arg5>(arg5_)) {}
};

/* for static class methods and non-class functions */

template <class... FreeArgs>
class Callback0_static: public CallbackArg<FreeArgs...> {
public:
  typedef void (*Func)(FreeArgs...);
private:
  Func func;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    func(free_args...);
  }
  Callback0_static(Func func_): func(func_) {}
};

template <bool unref, class BoundArg, class... FreeArgs>
class Callback1_static: public CallbackArg<FreeArgs...> {
public:
  typedef void (*Func)(BoundArg, FreeArgs...);
private:
  Func func;
  typename Cgu::RemoveRefCond<BoundArg, unref>::Type arg;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    func(arg, free_args...);
  }
  template <class Arg>
  Callback1_static(Func func_, Arg&& arg_): func(func_), arg(std::forward<Arg>(arg_)) {}
};

template <bool unref, class BoundArg1, class BoundArg2, class... FreeArgs>
class Callback2_static: public CallbackArg<FreeArgs...> {
public:
  typedef void (*Func)(BoundArg1, BoundArg2, FreeArgs...);
private:
  Func func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    func(arg1, arg2, free_args...);
  }
  template <class Arg1, class Arg2>
  Callback2_static(Func func_, Arg1&& arg1_,
		   Arg2&& arg2_): func(func_),
                                  arg1(std::forward<Arg1>(arg1_)),
                                  arg2(std::forward<Arg2>(arg2_)) {}
};

template <bool unref, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
class Callback3_static: public CallbackArg<FreeArgs...> {
public:
  typedef void (*Func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...);
private:
  Func func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    func(arg1, arg2, arg3, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3>
  Callback3_static(Func func_,
		   Arg1&& arg1_,
		   Arg2&& arg2_,
		   Arg3&& arg3_):
                     func(func_),
		     arg1(std::forward<Arg1>(arg1_)),
		     arg2(std::forward<Arg2>(arg2_)),
		     arg3(std::forward<Arg3>(arg3_)) {}
};

template <bool unref, class BoundArg1, class BoundArg2, class BoundArg3, 
          class BoundArg4, class... FreeArgs>
class Callback4_static: public CallbackArg<FreeArgs...> {
public:
  typedef void (*Func)(BoundArg1, BoundArg2, BoundArg3, BoundArg4, FreeArgs...);
private:
  Func func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
  typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    func(arg1, arg2, arg3, arg4, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3, class Arg4>
  Callback4_static(Func func_,
		   Arg1&& arg1_,
		   Arg2&& arg2_,
		   Arg3&& arg3_,
		   Arg4&& arg4_):
                     func(func_),
		     arg1(std::forward<Arg1>(arg1_)),
		     arg2(std::forward<Arg2>(arg2_)),
		     arg3(std::forward<Arg3>(arg3_)),
		     arg4(std::forward<Arg4>(arg4_)) {}
};

template <bool unref, class BoundArg1, class BoundArg2, class BoundArg3, 
          class BoundArg4, class BoundArg5, class... FreeArgs>
class Callback5_static: public CallbackArg<FreeArgs...> {
public:
  typedef void (*Func)(BoundArg1, BoundArg2, BoundArg3,
		       BoundArg4, BoundArg5, FreeArgs...);
private:
  Func func;
  typename Cgu::RemoveRefCond<BoundArg1, unref>::Type arg1;
  typename Cgu::RemoveRefCond<BoundArg2, unref>::Type arg2;
  typename Cgu::RemoveRefCond<BoundArg3, unref>::Type arg3;
  typename Cgu::RemoveRefCond<BoundArg4, unref>::Type arg4;
  typename Cgu::RemoveRefCond<BoundArg5, unref>::Type arg5;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {
    func(arg1, arg2, arg3, arg4, arg5, free_args...);
  }
  template <class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
  Callback5_static(Func func_,
		   Arg1&& arg1_,
		   Arg2&& arg2_,
		   Arg3&& arg3_,
		   Arg4&& arg4_,
		   Arg5&& arg5_):
                     func(func_),
		     arg1(std::forward<Arg1>(arg1_)),
		     arg2(std::forward<Arg2>(arg2_)),
		     arg3(std::forward<Arg3>(arg3_)),
		     arg4(std::forward<Arg4>(arg4_)),
		     arg5(std::forward<Arg5>(arg5_)) {}
};

// generic class for callable objects such as lambdas
template <class Lambda, class... FreeArgs>
class Callback_lambda: public CallbackArg<FreeArgs...> {
  // making 'l' mutable means that Callback_lamdba objects can contain
  // mutable lambda expressions
  mutable Lambda l;
public:
  void dispatch(typename Cgu::Param<FreeArgs>::ParamType... free_args) const {l(free_args...);}
  template <class L> Callback_lambda(L&& l_): l(std::forward<L>(l_)) {}
};

/* Convenience functions making callback objects on freestore.  These
 * can for example be passed as the first argument of the
 * Thread::start() method in thread.h. They are also used by the
 * Callback::post() function.
*/

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case.  This exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option (instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).
 */
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
			       void (T::*func)(FreeArgs...)) {
  return new Callback0<T, FreeArgs...>{t, func};
}

/**
 * Since this function constructs a callback which does not take a
 * bound argument, it is a synonym for make() (the two are identical).
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case.  This exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option (instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).
 *
 * Since 2.0.0-rc3
 */
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
				   void (T::*func)(FreeArgs...)) {
  return new Callback0<T, FreeArgs...>{t, func};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
			       void (T::*func)(BoundArg, FreeArgs...),
			       BoundArg arg) {
  return new Callback1<false, T, BoundArg, FreeArgs...>{t, func, arg};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg, class Arg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
				   void (T::*func)(BoundArg, FreeArgs...),
				   Arg&& arg) {
  return new Callback1<true, T, BoundArg, FreeArgs...>{t, func, std::forward<Arg>(arg)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
			       void (T::*func)(BoundArg1, BoundArg2, FreeArgs...),
			       BoundArg1 arg1,
			       BoundArg2 arg2) {
  return new Callback2<false, T, BoundArg1, BoundArg2, FreeArgs...>{t, func, arg1, arg2};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg1, class BoundArg2,
          class Arg1, class Arg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
				   void (T::*func)(BoundArg1, BoundArg2, FreeArgs...),
				   Arg1&& arg1,
				   Arg2&& arg2) {
  return new Callback2<true, T, BoundArg1, BoundArg2, FreeArgs...>{t, func,
                                                                   std::forward<Arg1>(arg1),
                                                                   std::forward<Arg2>(arg2)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
			       void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3) {
  return new Callback3<false, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func, arg1, arg2, arg3};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class Arg1, class Arg2, class Arg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3) {
  return new Callback3<true, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func,
                                                                              std::forward<Arg1>(arg1),
                                                                              std::forward<Arg2>(arg2),
                                                                              std::forward<Arg3>(arg3)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
			       void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
					       BoundArg4, FreeArgs...),
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3,
			       BoundArg4 arg4) {
  return new Callback4<false, T, BoundArg1, BoundArg2, BoundArg3,
                       BoundArg4, FreeArgs...>{t, func, arg1, arg2, arg3, arg4};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4,
          class Arg1, class Arg2, class Arg3, class Arg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
						   BoundArg4, FreeArgs...),
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3,
				   Arg4&& arg4) {
  return new Callback4<true, T, BoundArg1, BoundArg2, BoundArg3,
                       BoundArg4, FreeArgs...>{t, func,
                                               std::forward<Arg1>(arg1),
                                               std::forward<Arg2>(arg2),
                                               std::forward<Arg3>(arg3),
                                               std::forward<Arg4>(arg4)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make(T& t,
			       void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
					       BoundArg4, BoundArg5, FreeArgs...),
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3,
			       BoundArg4 arg4,
			       BoundArg5 arg5) {
  return new Callback5<false, T, BoundArg1, BoundArg2, BoundArg3,
                       BoundArg4, BoundArg5, FreeArgs...>{t, func, arg1, arg2, arg3, arg4, arg5};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4, class BoundArg5,
          class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
						   BoundArg4, BoundArg5, FreeArgs...),
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3,
				   Arg4&& arg4,
				   Arg5&& arg5) {
  return new Callback5<true, T, BoundArg1, BoundArg2, BoundArg3,
                       BoundArg4, BoundArg5, FreeArgs...>{t, func,
                                                          std::forward<Arg1>(arg1),
                                                          std::forward<Arg2>(arg2),
                                                          std::forward<Arg3>(arg3),
                                                          std::forward<Arg4>(arg4),
                                                          std::forward<Arg5>(arg5)};
}

/* const versions, for binding to const methods */

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case.  This exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option (instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).
 */
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
			       void (T::*func)(FreeArgs...) const) {
  return new Callback0_const<T, FreeArgs...>{t, func};
}

/**
 * Since this function constructs a callback which does not take a
 * bound argument, it is a synonym for make() (the two are identical).
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case.  This exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option (instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).
 *
 * Since 2.0.0-rc3
 */
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
				   void (T::*func)(FreeArgs...) const) {
  return new Callback0_const<T, FreeArgs...>{t, func};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
			       void (T::*func)(BoundArg, FreeArgs...) const,
			       BoundArg arg) {
  return new Callback1_const<false, T, BoundArg, FreeArgs...>{t, func, arg};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg, class Arg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
				   void (T::*func)(BoundArg, FreeArgs...) const,
				   Arg&& arg) {
  return new Callback1_const<true, T, BoundArg, FreeArgs...>{t, func, std::forward<Arg>(arg)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
			       void (T::*func)(BoundArg1, BoundArg2, FreeArgs...) const,
			       BoundArg1 arg1,
			       BoundArg2 arg2) {
  return new Callback2_const<false, T, BoundArg1, BoundArg2, FreeArgs...>{t, func, arg1, arg2};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg1, class BoundArg2,
          class Arg1, class Arg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
				   void (T::*func)(BoundArg1, BoundArg2, FreeArgs...) const,
				   Arg1&& arg1,
				   Arg2&& arg2) {
  return new Callback2_const<true, T, BoundArg1, BoundArg2, FreeArgs...>{t, func,
                                                                         std::forward<Arg1>(arg1),
                                                                         std::forward<Arg2>(arg2)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
			       void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const,
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3) {
  return new Callback3_const<false, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func, arg1, arg2, arg3};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class Arg1, class Arg2, class Arg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const,
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3) {
  return new Callback3_const<true, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func,
                                                                                    std::forward<Arg1>(arg1),
                                                                                    std::forward<Arg2>(arg2),
                                                                                    std::forward<Arg3>(arg3)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
			       void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
					       BoundArg4, FreeArgs...) const,
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3,
			       BoundArg4 arg4) {
  return new Callback4_const<false, T, BoundArg1, BoundArg2, BoundArg3,
                             BoundArg4, FreeArgs...>{t, func, arg1, arg2, arg3, arg4};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4,
          class Arg1, class Arg2, class Arg3, class Arg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
						   BoundArg4, FreeArgs...) const,
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3,
				   Arg4&& arg4) {
  return new Callback4_const<true, T, BoundArg1, BoundArg2, BoundArg3,
                             BoundArg4, FreeArgs...>{t, func,
                                                     std::forward<Arg1>(arg1),
                                                     std::forward<Arg2>(arg2),
                                                     std::forward<Arg3>(arg3),
                                                     std::forward<Arg4>(arg4)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make(const T& t,
			       void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
					       BoundArg4, BoundArg5, FreeArgs...) const,
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3,
			       BoundArg4 arg4,
			       BoundArg5 arg5) {
  return new Callback5_const<false, T, BoundArg1, BoundArg2, BoundArg3,
                             BoundArg4, BoundArg5, FreeArgs...>{t, func, arg1, arg2, arg3, arg4, arg5};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4, class BoundArg5,
          class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
						   BoundArg4, BoundArg5, FreeArgs...) const,
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3,
				   Arg4&& arg4,
				   Arg5&& arg5) {
  return new Callback5_const<true, T, BoundArg1, BoundArg2, BoundArg3,
                             BoundArg4, BoundArg5, FreeArgs...>{t, func,
                                                                std::forward<Arg1>(arg1),
                                                                std::forward<Arg2>(arg2),
                                                                std::forward<Arg3>(arg3),
                                                                std::forward<Arg4>(arg4),
                                                                std::forward<Arg5>(arg5)};
}

/* for static class methods and non-class functions */

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case.  This exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option (instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).
 */
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(FreeArgs...)) {
  return new Callback0_static<FreeArgs...>{func};
}

/**
 * Since this function constructs a callback which does not take a
 * bound argument, it is a synonym for make() (the two are identical).
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case.  This exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option (instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).
 *
 * Since 2.0.0-rc3
 */
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(FreeArgs...)) {
  return new Callback0_static<FreeArgs...>{func};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg, FreeArgs...),
			       BoundArg arg) {
  return new Callback1_static<false, BoundArg, FreeArgs...>{func, arg};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class BoundArg, class Arg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg, FreeArgs...),
				   Arg&& arg) {
  return new Callback1_static<true, BoundArg, FreeArgs...>{func, std::forward<Arg>(arg)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg1, BoundArg2, FreeArgs...),
			       BoundArg1 arg1,
			       BoundArg2 arg2) {
  return new Callback2_static<false, BoundArg1, BoundArg2, FreeArgs...>{func, arg1, arg2};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class BoundArg1, class BoundArg2, class Arg1, class Arg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg1, BoundArg2, FreeArgs...),
				   Arg1&& arg1,
				   Arg2&& arg2) {
  return new Callback2_static<true, BoundArg1, BoundArg2, FreeArgs...>{func,
                                                                       std::forward<Arg1>(arg1),
                                                                       std::forward<Arg2>(arg2)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3) {
  return new Callback3_static<false, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{func, arg1, arg2, arg3};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class BoundArg1, class BoundArg2, class BoundArg3,
          class Arg1, class Arg2, class Arg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3) {
  return new Callback3_static<true, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{func,
                                                                                  std::forward<Arg1>(arg1),
                                                                                  std::forward<Arg2>(arg2),
                                                                                  std::forward<Arg3>(arg3)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg1, BoundArg2, BoundArg3,
					    BoundArg4, FreeArgs...),
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3,
			       BoundArg4 arg4) {
  return new Callback4_static<false, BoundArg1, BoundArg2, BoundArg3,
                              BoundArg4, FreeArgs...>{func, arg1, arg2, arg3, arg4};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4,
          class Arg1, class Arg2, class Arg3, class Arg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg1, BoundArg2, BoundArg3,
						BoundArg4, FreeArgs...),
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3,
				   Arg4&& arg4) {
  return new Callback4_static<true, BoundArg1, BoundArg2, BoundArg3,
                              BoundArg4, FreeArgs...>{func,
                                                      std::forward<Arg1>(arg1),
                                                      std::forward<Arg2>(arg2),
                                                      std::forward<Arg3>(arg3),
                                                      std::forward<Arg4>(arg4)};
}

/**
 * A convenience function to make Callback::CallbackArg objects
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make(void (*func)(BoundArg1, BoundArg2, BoundArg3,
					    BoundArg4, BoundArg5, FreeArgs...),
			       BoundArg1 arg1,
			       BoundArg2 arg2,
			       BoundArg3 arg3,
			       BoundArg4 arg4,
			       BoundArg5 arg5) {
  return new Callback5_static<false, BoundArg1, BoundArg2, BoundArg3,
                              BoundArg4, BoundArg5, FreeArgs...>{func, arg1, arg2, arg3, arg4, arg5};
}

/**
 * An alternative function to make Callback::CallbackArg objects,
 * which is for use where a target function either receives a class
 * type bound argument by value, or receives a bound argument by
 * reference to const in a case where the generated CallbackArg object
 * is to store a copy of that argument instead of just keeping a
 * reference.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws.
 *
 * Since 2.0.0-rc3
 */
template <class BoundArg1, class BoundArg2, class BoundArg3, class BoundArg4, class BoundArg5,
          class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(void (*func)(BoundArg1, BoundArg2, BoundArg3,
						BoundArg4, BoundArg5, FreeArgs...),
				   Arg1&& arg1,
				   Arg2&& arg2,
				   Arg3&& arg3,
				   Arg4&& arg4,
				   Arg5&& arg5) {
  return new Callback5_static<true, BoundArg1, BoundArg2, BoundArg3,
                              BoundArg4, BoundArg5, FreeArgs...>{func,
                                                                 std::forward<Arg1>(arg1),
                                                                 std::forward<Arg2>(arg2),
                                                                 std::forward<Arg3>(arg3),
                                                                 std::forward<Arg4>(arg4),
                                                                 std::forward<Arg5>(arg5)};
}

/* for std::function objects */

/**
 * A convenience function to make Callback::CallbackArg objects from
 * std::function objects.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make(const std::function<void(FreeArgs...)>& f) {
  typedef std::function<void(FreeArgs...)> LType;
  return new Callback_lambda<LType, FreeArgs...>{f};
}

/**
 * A convenience function to make Callback::Callback objects from
 * std::function objects.  Since this function takes no bound argument
 * (and bound arguments are bound into the std::function object), it
 * is a synonym for make() (the two are identical).
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(const std::function<void(FreeArgs...)>& f) {
  typedef std::function<void(FreeArgs...)> LType;
  return new Callback_lambda<LType, FreeArgs...>{f};
}

/**
 * A convenience function to make Callback::CallbackArg objects from
 * std::function objects.
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make(std::function<void(FreeArgs...)>&& f) {
  typedef std::function<void(FreeArgs...)> LType;
  return new Callback_lambda<LType, FreeArgs...>{std::move(f)};
}

/**
 * A convenience function to make Callback::Callback objects from
 * std::function objects.  Since this function takes no bound argument
 * (and bound arguments are bound into the std::function object), it
 * is a synonym for make() (the two are identical).
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of a bound argument throws and it is not a reference
 * argument.
 */
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_ref(std::function<void(FreeArgs...)>&& f) {
  typedef std::function<void(FreeArgs...)> LType;
  return new Callback_lambda<LType, FreeArgs...>{std::move(f)};
}

// This helper function to construct Callback_lambda objects could be
// implemented as a further overload of Callback::make().  No best
// match ambiguities would arise, because even when Callback::make()
// is passed a function pointer without bound arguments, the overload
// of Callback::make taking a function pointer (as opposed to a
// generic callable object) would still comprise the best match.
// However, to construct Callback_lambda objects, the unbound
// arguments need to be specified by hand, which doesn't happen with
// Callback::make() (it would only be necessary to specify an explicit
// type where a mutable reference argument is to be bound to the
// callback object).  It seems to me to be less confusing to the user
// therefore to have a separate Callback::lambda() helper function.
// However, if you disagree please let me know.

// template parameter packs do not need to be placed last in the case
// of function templates, as type deduction is available for the last
// parameter: there is in fact no function parameter pack in
// Callback::lambda() (function parameter packs must come last).
/**
 * A convenience function to make Callback::CallbackArg objects from
 * C++11 lambda expressions, or from any other arbitrary callable
 * object.  The types of the unbound arguments (if any) must be
 * explicitly specified as template parameters, as they cannot be
 * deduced.  From version 2.0.10, this function can be called for
 * lambda expressions which are declared mutable (in version 2.0.9,
 * this function could only be called for non-mutable lambda
 * expressions).  From version 2.0.16, this function can be passed
 * callable objects which are lvalues as well as rvalues (prior to
 * version 2.0.16, it could only be passed callable objects which are
 * rvalues).
 * @exception std::bad_alloc It might throw std::bad_alloc if memory
 * is exhausted and the system throws in that case (this exception
 * will not be thrown if the library has been installed using the
 * \--with-glib-memory-slices-no-compat configuration option: instead
 * glib will terminate the program if it is unable to obtain memory
 * from the operating system).  It will also throw if the copy or move
 * constructor of an object captured by the lambda expression throws.
 *
 * Since 2.0.9
 */
template <class... FreeArgs, class Lambda>
CallbackArg<FreeArgs...>* lambda(Lambda&& l) {
  typedef typename std::remove_const<typename std::remove_reference<Lambda>::type>::type LType;
  return new Callback_lambda<LType, FreeArgs...>{std::forward<Lambda>(l)};
}

#ifndef DOXYGEN_PARSING
/*
 * DEPRECATED.  These make_val() functions are retained for API
 * compatibility only, but should not be used in new code and are not
 * documented.  Use make_ref() instead.
 */
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
				   void (T::*func)(FreeArgs...)) {
  return new Callback0<T, FreeArgs...>{t, func};
}
template <class T, class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
				   void (T::*func)(BoundArg, FreeArgs...),
				   const BoundArg& arg) {
  return new Callback1<false, T, BoundArg, FreeArgs...>{t, func, arg};
}
template <class T, class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
				   void (T::*func)(BoundArg1, BoundArg2, FreeArgs...),
				   const BoundArg1& arg1,
				   const BoundArg2& arg2) {
  return new Callback2<false, T, BoundArg1, BoundArg2, FreeArgs...>{t, func, arg1, arg2};
}
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3) {
  return new Callback3<false, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func, arg1, arg2, arg3};
}
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
						   BoundArg4, FreeArgs...),
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3,
				   const BoundArg4& arg4) {
  return new Callback4<false, T, BoundArg1, BoundArg2, BoundArg3,
                       BoundArg4, FreeArgs...>{t, func, arg1, arg2, arg3, arg4};
}
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
						   BoundArg4, BoundArg5, FreeArgs...),
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3,
				   const BoundArg4& arg4,
				   const BoundArg5& arg5) {
  return new Callback5<false, T, BoundArg1, BoundArg2, BoundArg3,
                       BoundArg4, BoundArg5, FreeArgs...>{t, func, arg1, arg2, arg3, arg4, arg5};
}
template <class T, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
				   void (T::*func)(FreeArgs...) const) {
  return new Callback0_const<T, FreeArgs...>{t, func};
}
template <class T, class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
				   void (T::*func)(BoundArg, FreeArgs...) const,
				   const BoundArg& arg) {
  return new Callback1_const<false, T, BoundArg, FreeArgs...>{t, func, arg};
}
template <class T, class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
				   void (T::*func)(BoundArg1, BoundArg2, FreeArgs...) const,
				   const BoundArg1& arg1,
				   const BoundArg2& arg2) {
  return new Callback2_const<false, T, BoundArg1, BoundArg2, FreeArgs...>{t, func, arg1, arg2};
}
template <class T, class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...) const,
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3) {
  return new Callback3_const<false, T, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{t, func, arg1, arg2, arg3};
}
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
						   BoundArg4, FreeArgs...) const,
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3,
				   const BoundArg4& arg4) {
  return new Callback4_const<false, T, BoundArg1, BoundArg2, BoundArg3,
                             BoundArg4, FreeArgs...>{t, func, arg1, arg2, arg3, arg4};
}
template <class T, class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const T& t,
				   void (T::*func)(BoundArg1, BoundArg2, BoundArg3,
						   BoundArg4, BoundArg5, FreeArgs...) const,
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3,
				   const BoundArg4& arg4,
				   const BoundArg5& arg5) {
  return new Callback5_const<false, T, BoundArg1, BoundArg2, BoundArg3,
                             BoundArg4, BoundArg5, FreeArgs...>{t, func, arg1, arg2, arg3, arg4, arg5};
}
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(FreeArgs...)) {
  return new Callback0_static<FreeArgs...>{func};
}
template <class BoundArg, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg, FreeArgs...),
				   const BoundArg& arg) {
  return new Callback1_static<false, BoundArg, FreeArgs...>{func, arg};
}
template <class BoundArg1, class BoundArg2, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg1, BoundArg2, FreeArgs...),
				   const BoundArg1& arg1,
				   const BoundArg2& arg2) {
  return new Callback2_static<false, BoundArg1, BoundArg2, FreeArgs...>{func, arg1, arg2};
}
template <class BoundArg1, class BoundArg2, class BoundArg3, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg1, BoundArg2, BoundArg3, FreeArgs...),
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3) {
  return new Callback3_static<false, BoundArg1, BoundArg2, BoundArg3, FreeArgs...>{func, arg1, arg2, arg3};
}
template <class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg1, BoundArg2, BoundArg3,
						BoundArg4, FreeArgs...),
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3,
				   const BoundArg4& arg4) {
  return new Callback4_static<false, BoundArg1, BoundArg2, BoundArg3,
                              BoundArg4, FreeArgs...>{func, arg1, arg2, arg3, arg4};
}
template <class BoundArg1, class BoundArg2, class BoundArg3,
          class BoundArg4, class BoundArg5, class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(void (*func)(BoundArg1, BoundArg2, BoundArg3,
						BoundArg4, BoundArg5, FreeArgs...),
				   const BoundArg1& arg1,
				   const BoundArg2& arg2,
				   const BoundArg3& arg3,
				   const BoundArg4& arg4,
				   const BoundArg5& arg5) {
  return new Callback5_static<false, BoundArg1, BoundArg2, BoundArg3,
                              BoundArg4, BoundArg5, FreeArgs...>{func, arg1, arg2, arg3, arg4, arg5};
}
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(const std::function<void(FreeArgs...)>& f) {
  typedef std::function<void(FreeArgs...)> LType;
  return new Callback_lambda<LType, FreeArgs...>{f};
}
template <class... FreeArgs>
CallbackArg<FreeArgs...>* make_val(std::function<void(FreeArgs...)>&& f) {
  typedef std::function<void(FreeArgs...)> LType;
  return new Callback_lambda<LType, FreeArgs...>{std::move(f)};
}
#endif // DOXYGEN_PARSING

} // namespace Callback

class Releaser;

namespace Callback {

/**
 * Posts a callback for execution by a glib main loop.  It is
 * thread-safe provided that (if glib < 2.32 is used) g_thread_init()
 * has been called.  glib >= 2.32 does not require g_thread_init() to
 * be called.  This function will not throw.
 * @param cb The callback object.  Ownership is taken of this object,
 * and it will be deleted when it has been finished with.
 * @param priority The priority to be given to the callback in the
 * main loop.  In ascending order of priorities, priorities are
 * G_PRIORITY_LOW, G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE,
 * G_PRIORITY_DEFAULT and G_PRIORITY_HIGH. The default is
 * G_PRIORITY_DEFAULT_IDLE.  This determines the order in which the
 * callback will appear in the event list in the main loop, not the
 * priority which the OS will adopt
 * @param context The glib main loop context in which the callback is
 * to be executed (the default of NULL will cause the callback to be
 * executed in the main program loop, and this is usually what is
 * wanted).
 * @note Cancellation of the receiving thread is blocked when the
 * callback executes.
 */
void post(const Callback* cb, gint priority = G_PRIORITY_DEFAULT_IDLE,
	  GMainContext* context = 0);

/**
 * Posts a callback for execution by a glib main loop.  It is
 * thread-safe provided that (if glib < 2.32 is used) g_thread_init()
 * has been called.  glib >= 2.32 does not require g_thread_init() to
 * be called.  This function will not throw.
 * @param cb The callback object.  Ownership is taken of this object,
 * and it will be deleted when it has been finished with.
 * @param r A Releaser object for automatic disconnection of the
 * callback before it executes in the main loop (mainly relevant if
 * the callback represents a non-static member function of an object
 * which may be destroyed before the callback executes).
 * @param priority The priority to be given to the callback in the
 * main loop.  In ascending order of priorities, priorities are
 * G_PRIORITY_LOW, G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE,
 * G_PRIORITY_DEFAULT and G_PRIORITY_HIGH. The default is
 * G_PRIORITY_DEFAULT_IDLE.  This determines the order in which the
 * callback will appear in the event list in the main loop, not the
 * priority which the OS will adopt.
 * @param context The glib main loop context in which the callback is
 * to be executed (the default of NULL will cause the callback to be
 * executed in the main program loop, and this is usually what is
 * wanted).
 * @exception std::bad_alloc This function might throw std::bad_alloc
 * if memory is exhausted and the system throws in that case.  If it
 * does so, the Callback object will be disposed of.
 * @exception Cgu::Thread::MutexError This method might throw
 * Cgu:Thread::MutexError if initialisation of the mutex in a
 * SafeEmitterArg object constructed by this method fails.  If it does
 * so, the Callback object will be disposed of.  (It is often not
 * worth checking for this exception, as it means either memory is
 * exhausted or pthread has run out of other resources to create new
 * mutexes.)
 * @note 1. Cancellation of the receiving thread is blocked when the
 * callback executes.
 * @note 2. By virtue of the Releaser object, it is in theory possible
 * (if memory is exhausted and the system throws in that case) that an
 * internal SafeEmitterArg object will throw std::bad_alloc when
 * emitting/executing the callback in the glib main loop, with the
 * result that the relevant callback will not execute (instead the
 * exception will be consumed and a g_critical() warning will be
 * issued).  This is rarely of any relevance because glib will abort
 * the program if it is itself unable to obtain memory from the
 * operating system.  However, where it is relevant, design the
 * program so that it is not necessary to provide a releaser object.
 */
void post(const Callback* cb, Releaser& r,
	  gint priority = G_PRIORITY_DEFAULT_IDLE, GMainContext* context = 0);


/**
 * Posts a callable object for execution by a glib main loop.  It is
 * thread-safe provided that (if glib < 2.32 is used) g_thread_init()
 * has been called.  glib >= 2.32 does not require g_thread_init() to
 * be called.  This function will not throw unless the copy or move
 * constructor of the callable object throws.
 * @param func A callable object, such as formed by a lambda
 * expression or the result of std::bind.  It must be fully bound
 * (that is, its must take no arguments when called).
 * @param priority The priority to be given to the callable object in
 * the main loop.  In ascending order of priorities, priorities are
 * G_PRIORITY_LOW, G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE,
 * G_PRIORITY_DEFAULT and G_PRIORITY_HIGH. The default is
 * G_PRIORITY_DEFAULT_IDLE.  This determines the order in which the
 * callback will appear in the event list in the main loop, not the
 * priority which the OS will adopt
 * @param context The glib main loop context in which the callable
 * object is to be executed (the default of NULL will cause the
 * callback to be executed in the main program loop, and this is
 * usually what is wanted).
 * @note Cancellation of the receiving thread is blocked when the
 * callback executes.
 *
 * Since 2.1.0
 */
// we need to use enable_if so that where this function is passed a
// pointer to non-const Callback, or some other convertible pointer,
// this templated overload is dropped from the overload set, in order
// to support the Callback pointer overloads of this function.  This
// overload calls into the version of this function taking a pointer
// to const Callback in order to perform type erasure.
template <class F,
	  class = typename std::enable_if<!std::is_convertible<typename std::remove_reference<F>::type,
							       const Callback*>::value>::type>
void post(F&& func, gint priority = G_PRIORITY_DEFAULT_IDLE,
	  GMainContext* context = 0) {
  post(lambda<>(std::forward<F>(func)), priority, context);
}

/**
 * Posts a callable object for execution by a glib main loop.  It is
 * thread-safe provided that (if glib < 2.32 is used) g_thread_init()
 * has been called.  glib >= 2.32 does not require g_thread_init() to
 * be called.
 * @param func A callable object, such as formed by a lambda
 * expression or the result of std::bind.  It must be fully bound
 * (that is, its must take no arguments when called).
 * @param r A Releaser object for automatic disconnection of the
 * callback before it executes in the main loop (mainly relevant if
 * the callback represents or calls into a non-static member function
 * of an object which may be destroyed before the callback executes).
 * @param priority The priority to be given to the callback in the
 * main loop.  In ascending order of priorities, priorities are
 * G_PRIORITY_LOW, G_PRIORITY_DEFAULT_IDLE, G_PRIORITY_HIGH_IDLE,
 * G_PRIORITY_DEFAULT and G_PRIORITY_HIGH. The default is
 * G_PRIORITY_DEFAULT_IDLE.  This determines the order in which the
 * callback will appear in the event list in the main loop, not the
 * priority which the OS will adopt.
 * @param context The glib main loop context in which the callable
 * object is to be executed (the default of NULL will cause the
 * callback to be executed in the main program loop, and this is
 * usually what is wanted).
 * @exception std::bad_alloc This function might throw std::bad_alloc
 * if memory is exhausted and the system throws in that case.
 * @exception Cgu::Thread::MutexError This method might throw
 * Cgu:Thread::MutexError if initialisation of the mutex in a
 * SafeEmitterArg object constructed by this method fails.  (It is
 * often not worth checking for this exception, as it means either
 * memory is exhausted or pthread has run out of other resources to
 * create new mutexes.)
 * @note 1.  This function may also throw if the copy or move
 * constructor of the callable object throws.
 * @note 2. Cancellation of the receiving thread is blocked when the
 * callback executes.
 * @note 3. By virtue of the Releaser object, it is in theory possible
 * (if memory is exhausted and the system throws in that case) that an
 * internal SafeEmitterArg object will throw std::bad_alloc when
 * emitting/executing the callback in the glib main loop, with the
 * result that the relevant callback will not execute (instead the
 * exception will be consumed and a g_critical() warning will be
 * issued).  This is rarely of any relevance because glib will abort
 * the program if it is itself unable to obtain memory from the
 * operating system.  However, where it is relevant, design the
 * program so that it is not necessary to provide a releaser object.
 *
 * Since 2.1.0
 */
// we need to use enable_if so that where this function is passed a
// pointer to non-const Callback, or some other convertible pointer,
// this templated overload is dropped from the overload set, in order
// to support the Callback pointer overloads of this function.  This
// overload calls into the version of this function taking a pointer
// to const Callback in order to perform type erasure.
template <class F,
	  class = typename std::enable_if<!std::is_convertible<typename std::remove_reference<F>::type,
							       const Callback*>::value>::type>
void post(F&& func, Releaser& r,
	  gint priority = G_PRIORITY_DEFAULT_IDLE, GMainContext* context = 0) {
  post(lambda<>(std::forward<F>(func)), r, priority, context);
}

} // namespace Callback

} // namespace Cgu

#endif
