/*
 * 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 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 * Callback.h
 * @brief Function objects.
 * Copyright (C) 2005 Simon Newton
 *
 * THIS FILE IS AUTOGENERATED!
 * Please edit and run gen_callbacks.py if you need to add more types.
 */

/**
 * @defgroup callbacks Callbacks
 * @brief Function objects.
 *
 * Callbacks are powerful objects that behave like function pointers. They
 * can be constructed with a pointer to a either plain function or member
 * function. Arguments can be provided at either creation time or execution
 * time.
 *
 * The SingleUse variant of a Callback automatically delete itself after it
 * has been executed.
 *
 * Callbacks are used throughout OLA to reduce the coupling between classes
 * and make for more modular code.
 *
 * Avoid creating Callbacks by directly calling the constructor. Instead use
 * the NewSingleCallback() and NewCallback() helper methods.
 *
 * @examplepara Simple function pointer replacement.
 *   @code
 *   // wrap a function that takes no args and returns a bool
 *   SingleUseCallback<bool> *callback1 = NewSingleCallback(&Function0);
 *
 *   // some time later
 *   bool result = callback1->Run();
 *   // callback1 has deleted itself at this point
 *   @endcode
 *
 * @examplepara Method pointer with a single bound argument
 *   @code
 *   // Create a Callback for Method1 of the Object class and bind TEST_VALUE
 *   // as the first argument.
 *   Callback<void> *callback2 = NewCallback(object, &Object::Method1,
 *                                           TEST_VALUE);
 *
 *   // This will call object->Method1(TEST_VALUE)
 *   callback2->Run();
 *   // this wasn't a SingleUse Callback, so callback is still around and
 *   // needs to be deleted manually.
 *   delete callback2;
 *   @endcode
 *
 * @examplepara Method pointer that takes a single argument at execution time.
 *   @code
 *   // Create a Callback for a method that takes 1 argument and returns void.
 *   BaseCallback1<void, unsigned int> *callback3 = NewCallback(
 *       object, &Object::Method1);
 *
 *   // Call object->Method1(TEST_VALUE)
 *   callback3->Run(TEST_VALUE);
 *   // callback3 is still around at this stage
 *   delete callback3;
 *   @endcode
 *
 * @examplepara Method pointer with one bound argument and one execution time
 * argument.
 *   @code
 *   // Create a callback for a method that takes 2 args and returns void
 *   BaseCallback2<void, int, int> *callback4 = NewSingleCallback(
 *       object,
 *       &Object::Method2,
 *       TEST_VALUE);
 *
 *   // This calls object->Method2(TEST_VALUE, TEST_VALUE2);
 *   callback4->Run(TEST_VALUE2);
 *   // callback4 is still around
 *   delete callback4;
 *   @endcode
 *
 * @note The code in Callback.h is autogenerated by gen_callbacks.py. Please
 * edit and run gen_callbacks.py if you need to add more types.
 *
 */

/**
 * @addtogroup callbacks
 * @{
 * @file Callback.h
 * @}
 */

#ifndef INCLUDE_OLA_CALLBACK_H_
#define INCLUDE_OLA_CALLBACK_H_

namespace ola {

/**
 * @addtogroup callbacks
 * @{
 */

/**
 * @brief The base class for all 0 argument callbacks.
 */
template <typename ReturnType>
class BaseCallback0 {
 public:
  virtual ~BaseCallback0() {}
  virtual ReturnType Run() = 0;
};

/**
 * @brief A 0 argument callback which can be called multiple times.
 */
template <typename ReturnType>
class Callback0: public BaseCallback0<ReturnType> {
 public:
  virtual ~Callback0() {}
  ReturnType Run() { return this->DoRun(); }
 private:
  virtual ReturnType DoRun() = 0;
};

/**
 * @brief A 0 argument callback which deletes itself after it's run.
 */
template <typename ReturnType>
class SingleUseCallback0: public BaseCallback0<ReturnType> {
 public:
  virtual ~SingleUseCallback0() {}
  ReturnType Run() {
    ReturnType ret = this->DoRun();
    delete this;
    return ret;
  }
 private:
  virtual ReturnType DoRun() = 0;
};

/**
 * @brief A 0 arg, single use callback that returns void.
 */
template <>
class SingleUseCallback0<void>: public BaseCallback0<void> {
 public:
  virtual ~SingleUseCallback0() {}
  void Run() {
    this->DoRun();
    delete this;
  }
 private:
  virtual void DoRun() = 0;
};

/**
 * @brief A Function callback with 0 create-time args and 0 exec time args
 */
template <typename Parent, typename ReturnType>
class FunctionCallback0_0: public Parent {
 public:
  typedef ReturnType (*Function)();
  explicit FunctionCallback0_0(Function callback):
    Parent(),
    m_callback(callback) {}
  ReturnType DoRun() {
    return m_callback();
  }
 private:
  Function m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType>
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  ReturnType (*callback)()) {
  return new FunctionCallback0_0<
                                 SingleUseCallback0<ReturnType>,
                                 ReturnType>(
      callback);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType>
inline Callback0<ReturnType>* NewCallback(
  ReturnType (*callback)()) {
  return new FunctionCallback0_0<
                                 Callback0<ReturnType>,
                                 ReturnType>(
      callback);
}


/**
 * @brief A Method callback with 0 create-time args and 0 exec time args
 */
template <typename Class, typename Parent, typename ReturnType>
class MethodCallback0_0: public Parent {
 public:
  typedef ReturnType (Class::*Method)();
  MethodCallback0_0(Class *object, Method callback):
    Parent(),
    m_object(object),
    m_callback(callback) {}
  ReturnType DoRun() {
    return (m_object->*m_callback)();
  }
 private:
  Class *m_object;
  Method m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType>
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)()) {
  return new MethodCallback0_0<Class,
                               SingleUseCallback0<ReturnType>,
                               ReturnType>(
      object,
      method);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType>
inline Callback0<ReturnType>* NewCallback(
  Class* object,
  ReturnType (Class::*method)()) {
  return new MethodCallback0_0<Class,
                               Callback0<ReturnType>,
                               ReturnType>(
      object,
      method);
}


/**
 * @brief A Function callback with 1 create-time args and 0 exec time args
 */
template <typename Parent, typename ReturnType, typename A0>
class FunctionCallback1_0: public Parent {
 public:
  typedef ReturnType (*Function)(A0);
  FunctionCallback1_0(Function callback, A0 a0):
    Parent(),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun() {
    return m_callback(m_a0);
  }
 private:
  Function m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0>
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  ReturnType (*callback)(A0),
  A0 a0) {
  return new FunctionCallback1_0<
                                 SingleUseCallback0<ReturnType>,
                                 ReturnType,
                                 A0>(
      callback,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0>
inline Callback0<ReturnType>* NewCallback(
  ReturnType (*callback)(A0),
  A0 a0) {
  return new FunctionCallback1_0<
                                 Callback0<ReturnType>,
                                 ReturnType,
                                 A0>(
      callback,
      a0);
}


/**
 * @brief A Method callback with 1 create-time args and 0 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0>
class MethodCallback1_0: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0);
  MethodCallback1_0(Class *object, Method callback, A0 a0):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun() {
    return (m_object->*m_callback)(m_a0);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0>
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0),
  A0 a0) {
  return new MethodCallback1_0<Class,
                               SingleUseCallback0<ReturnType>,
                               ReturnType,
                               A0>(
      object,
      method,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0>
inline Callback0<ReturnType>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0),
  A0 a0) {
  return new MethodCallback1_0<Class,
                               Callback0<ReturnType>,
                               ReturnType,
                               A0>(
      object,
      method,
      a0);
}


/**
 * @brief A Function callback with 2 create-time args and 0 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1>
class FunctionCallback2_0: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1);
  FunctionCallback2_0(Function callback, A0 a0, A1 a1):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun() {
    return m_callback(m_a0, m_a1);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1>
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  ReturnType (*callback)(A0, A1),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_0<
                                 SingleUseCallback0<ReturnType>,
                                 ReturnType,
                                 A0,
                                 A1>(
      callback,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1>
inline Callback0<ReturnType>* NewCallback(
  ReturnType (*callback)(A0, A1),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_0<
                                 Callback0<ReturnType>,
                                 ReturnType,
                                 A0,
                                 A1>(
      callback,
      a0,
      a1);
}


/**
 * @brief A Method callback with 2 create-time args and 0 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1>  // NOLINT(whitespace/line_length)
class MethodCallback2_0: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1);
  MethodCallback2_0(Class *object, Method callback, A0 a0, A1 a1):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun() {
    return (m_object->*m_callback)(m_a0, m_a1);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1>
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_0<Class,
                               SingleUseCallback0<ReturnType>,
                               ReturnType,
                               A0,
                               A1>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1>
inline Callback0<ReturnType>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_0<Class,
                               Callback0<ReturnType>,
                               ReturnType,
                               A0,
                               A1>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A Function callback with 3 create-time args and 0 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2>  // NOLINT(whitespace/line_length)
class FunctionCallback3_0: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2);
  FunctionCallback3_0(Function callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun() {
    return m_callback(m_a0, m_a1, m_a2);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2>
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, A2),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_0<
                                 SingleUseCallback0<ReturnType>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2>
inline Callback0<ReturnType>* NewCallback(
  ReturnType (*callback)(A0, A1, A2),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_0<
                                 Callback0<ReturnType>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A Method callback with 3 create-time args and 0 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2>  // NOLINT(whitespace/line_length)
class MethodCallback3_0: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2);
  MethodCallback3_0(Class *object, Method callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun() {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_0<Class,
                               SingleUseCallback0<ReturnType>,
                               ReturnType,
                               A0,
                               A1,
                               A2>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2>  // NOLINT(whitespace/line_length)
inline Callback0<ReturnType>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_0<Class,
                               Callback0<ReturnType>,
                               ReturnType,
                               A0,
                               A1,
                               A2>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A Function callback with 4 create-time args and 0 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3>  // NOLINT(whitespace/line_length)
class FunctionCallback4_0: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, A3);
  FunctionCallback4_0(Function callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun() {
    return m_callback(m_a0, m_a1, m_a2, m_a3);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, A2, A3),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_0<
                                 SingleUseCallback0<ReturnType>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 0 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3>  // NOLINT(whitespace/line_length)
inline Callback0<ReturnType>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, A3),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_0<
                                 Callback0<ReturnType>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A Method callback with 4 create-time args and 0 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3>  // NOLINT(whitespace/line_length)
class MethodCallback4_0: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, A3);
  MethodCallback4_0(Class *object, Method callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun() {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, m_a3);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback0<ReturnType>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_0<Class,
                               SingleUseCallback0<ReturnType>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 0 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3>  // NOLINT(whitespace/line_length)
inline Callback0<ReturnType>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_0<Class,
                               Callback0<ReturnType>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief The base class for all 1 argument callbacks.
 */
template <typename ReturnType, typename Arg0>
class BaseCallback1 {
 public:
  virtual ~BaseCallback1() {}
  virtual ReturnType Run(Arg0 arg0) = 0;
};

/**
 * @brief A 1 argument callback which can be called multiple times.
 */
template <typename ReturnType, typename Arg0>
class Callback1: public BaseCallback1<ReturnType, Arg0> {
 public:
  virtual ~Callback1() {}
  ReturnType Run(Arg0 arg0) { return this->DoRun(arg0); }
 private:
  virtual ReturnType DoRun(Arg0 arg0) = 0;
};

/**
 * @brief A 1 argument callback which deletes itself after it's run.
 */
template <typename ReturnType, typename Arg0>
class SingleUseCallback1: public BaseCallback1<ReturnType, Arg0> {
 public:
  virtual ~SingleUseCallback1() {}
  ReturnType Run(Arg0 arg0) {
    ReturnType ret = this->DoRun(arg0);
    delete this;
    return ret;
  }
 private:
  virtual ReturnType DoRun(Arg0 arg0) = 0;
};

/**
 * @brief A 1 arg, single use callback that returns void.
 */
template <typename Arg0>
class SingleUseCallback1<void, Arg0>: public BaseCallback1<void, Arg0> {
 public:
  virtual ~SingleUseCallback1() {}
  void Run(Arg0 arg0) {
    this->DoRun(arg0);
    delete this;
  }
 private:
  virtual void DoRun(Arg0 arg0) = 0;
};

/**
 * @brief A Function callback with 0 create-time args and 1 exec time args
 */
template <typename Parent, typename ReturnType, typename Arg0>
class FunctionCallback0_1: public Parent {
 public:
  typedef ReturnType (*Function)(Arg0);
  explicit FunctionCallback0_1(Function callback):
    Parent(),
    m_callback(callback) {}
  ReturnType DoRun(Arg0 arg0) {
    return m_callback(arg0);
  }
 private:
  Function m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename Arg0>
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  ReturnType (*callback)(Arg0)) {
  return new FunctionCallback0_1<
                                 SingleUseCallback1<ReturnType, Arg0>,
                                 ReturnType,
                                 Arg0>(
      callback);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename Arg0>
inline Callback1<ReturnType, Arg0>* NewCallback(
  ReturnType (*callback)(Arg0)) {
  return new FunctionCallback0_1<
                                 Callback1<ReturnType, Arg0>,
                                 ReturnType,
                                 Arg0>(
      callback);
}


/**
 * @brief A Method callback with 0 create-time args and 1 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename Arg0>
class MethodCallback0_1: public Parent {
 public:
  typedef ReturnType (Class::*Method)(Arg0);
  MethodCallback0_1(Class *object, Method callback):
    Parent(),
    m_object(object),
    m_callback(callback) {}
  ReturnType DoRun(Arg0 arg0) {
    return (m_object->*m_callback)(arg0);
  }
 private:
  Class *m_object;
  Method m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename Arg0>
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(Arg0)) {
  return new MethodCallback0_1<Class,
                               SingleUseCallback1<ReturnType, Arg0>,
                               ReturnType,
                               Arg0>(
      object,
      method);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename Arg0>
inline Callback1<ReturnType, Arg0>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(Arg0)) {
  return new MethodCallback0_1<Class,
                               Callback1<ReturnType, Arg0>,
                               ReturnType,
                               Arg0>(
      object,
      method);
}


/**
 * @brief A Function callback with 1 create-time args and 1 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename Arg0>
class FunctionCallback1_1: public Parent {
 public:
  typedef ReturnType (*Function)(A0, Arg0);
  FunctionCallback1_1(Function callback, A0 a0):
    Parent(),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun(Arg0 arg0) {
    return m_callback(m_a0, arg0);
  }
 private:
  Function m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename Arg0>
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  ReturnType (*callback)(A0, Arg0),
  A0 a0) {
  return new FunctionCallback1_1<
                                 SingleUseCallback1<ReturnType, Arg0>,
                                 ReturnType,
                                 A0,
                                 Arg0>(
      callback,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename Arg0>
inline Callback1<ReturnType, Arg0>* NewCallback(
  ReturnType (*callback)(A0, Arg0),
  A0 a0) {
  return new FunctionCallback1_1<
                                 Callback1<ReturnType, Arg0>,
                                 ReturnType,
                                 A0,
                                 Arg0>(
      callback,
      a0);
}


/**
 * @brief A Method callback with 1 create-time args and 1 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename Arg0>  // NOLINT(whitespace/line_length)
class MethodCallback1_1: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, Arg0);
  MethodCallback1_1(Class *object, Method callback, A0 a0):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun(Arg0 arg0) {
    return (m_object->*m_callback)(m_a0, arg0);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename Arg0>
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, Arg0),
  A0 a0) {
  return new MethodCallback1_1<Class,
                               SingleUseCallback1<ReturnType, Arg0>,
                               ReturnType,
                               A0,
                               Arg0>(
      object,
      method,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename Arg0>
inline Callback1<ReturnType, Arg0>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, Arg0),
  A0 a0) {
  return new MethodCallback1_1<Class,
                               Callback1<ReturnType, Arg0>,
                               ReturnType,
                               A0,
                               Arg0>(
      object,
      method,
      a0);
}


/**
 * @brief A Function callback with 2 create-time args and 1 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename Arg0>  // NOLINT(whitespace/line_length)
class FunctionCallback2_1: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, Arg0);
  FunctionCallback2_1(Function callback, A0 a0, A1 a1):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun(Arg0 arg0) {
    return m_callback(m_a0, m_a1, arg0);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename Arg0>
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, Arg0),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_1<
                                 SingleUseCallback1<ReturnType, Arg0>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 Arg0>(
      callback,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename Arg0>
inline Callback1<ReturnType, Arg0>* NewCallback(
  ReturnType (*callback)(A0, A1, Arg0),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_1<
                                 Callback1<ReturnType, Arg0>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 Arg0>(
      callback,
      a0,
      a1);
}


/**
 * @brief A Method callback with 2 create-time args and 1 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename Arg0>  // NOLINT(whitespace/line_length)
class MethodCallback2_1: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, Arg0);
  MethodCallback2_1(Class *object, Method callback, A0 a0, A1 a1):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun(Arg0 arg0) {
    return (m_object->*m_callback)(m_a0, m_a1, arg0);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename Arg0>  // NOLINT(whitespace/line_length)
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, Arg0),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_1<Class,
                               SingleUseCallback1<ReturnType, Arg0>,
                               ReturnType,
                               A0,
                               A1,
                               Arg0>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename Arg0>  // NOLINT(whitespace/line_length)
inline Callback1<ReturnType, Arg0>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, Arg0),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_1<Class,
                               Callback1<ReturnType, Arg0>,
                               ReturnType,
                               A0,
                               A1,
                               Arg0>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A Function callback with 3 create-time args and 1 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0>  // NOLINT(whitespace/line_length)
class FunctionCallback3_1: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, Arg0);
  FunctionCallback3_1(Function callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun(Arg0 arg0) {
    return m_callback(m_a0, m_a1, m_a2, arg0);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename Arg0>  // NOLINT(whitespace/line_length)
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, A2, Arg0),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_1<
                                 SingleUseCallback1<ReturnType, Arg0>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 Arg0>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename Arg0>  // NOLINT(whitespace/line_length)
inline Callback1<ReturnType, Arg0>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, Arg0),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_1<
                                 Callback1<ReturnType, Arg0>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 Arg0>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A Method callback with 3 create-time args and 1 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0>  // NOLINT(whitespace/line_length)
class MethodCallback3_1: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, Arg0);
  MethodCallback3_1(Class *object, Method callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun(Arg0 arg0) {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, arg0);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0>  // NOLINT(whitespace/line_length)
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, Arg0),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_1<Class,
                               SingleUseCallback1<ReturnType, Arg0>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               Arg0>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0>  // NOLINT(whitespace/line_length)
inline Callback1<ReturnType, Arg0>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, Arg0),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_1<Class,
                               Callback1<ReturnType, Arg0>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               Arg0>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A Function callback with 4 create-time args and 1 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0>  // NOLINT(whitespace/line_length)
class FunctionCallback4_1: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, A3, Arg0);
  FunctionCallback4_1(Function callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun(Arg0 arg0) {
    return m_callback(m_a0, m_a1, m_a2, m_a3, arg0);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0>  // NOLINT(whitespace/line_length)
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, A2, A3, Arg0),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_1<
                                 SingleUseCallback1<ReturnType, Arg0>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3,
                                 Arg0>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 1 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0>  // NOLINT(whitespace/line_length)
inline Callback1<ReturnType, Arg0>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, A3, Arg0),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_1<
                                 Callback1<ReturnType, Arg0>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3,
                                 Arg0>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A Method callback with 4 create-time args and 1 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0>  // NOLINT(whitespace/line_length)
class MethodCallback4_1: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, A3, Arg0);
  MethodCallback4_1(Class *object, Method callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun(Arg0 arg0) {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, m_a3, arg0);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0>  // NOLINT(whitespace/line_length)
inline SingleUseCallback1<ReturnType, Arg0>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3, Arg0),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_1<Class,
                               SingleUseCallback1<ReturnType, Arg0>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3,
                               Arg0>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 1 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0>  // NOLINT(whitespace/line_length)
inline Callback1<ReturnType, Arg0>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3, Arg0),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_1<Class,
                               Callback1<ReturnType, Arg0>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3,
                               Arg0>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief The base class for all 2 argument callbacks.
 */
template <typename ReturnType, typename Arg0, typename Arg1>
class BaseCallback2 {
 public:
  virtual ~BaseCallback2() {}
  virtual ReturnType Run(Arg0 arg0, Arg1 arg1) = 0;
};

/**
 * @brief A 2 argument callback which can be called multiple times.
 */
template <typename ReturnType, typename Arg0, typename Arg1>
class Callback2: public BaseCallback2<ReturnType, Arg0, Arg1> {
 public:
  virtual ~Callback2() {}
  ReturnType Run(Arg0 arg0, Arg1 arg1) { return this->DoRun(arg0, arg1); }
 private:
  virtual ReturnType DoRun(Arg0 arg0, Arg1 arg1) = 0;
};

/**
 * @brief A 2 argument callback which deletes itself after it's run.
 */
template <typename ReturnType, typename Arg0, typename Arg1>
class SingleUseCallback2: public BaseCallback2<ReturnType, Arg0, Arg1> {
 public:
  virtual ~SingleUseCallback2() {}
  ReturnType Run(Arg0 arg0, Arg1 arg1) {
    ReturnType ret = this->DoRun(arg0, arg1);
    delete this;
    return ret;
  }
 private:
  virtual ReturnType DoRun(Arg0 arg0, Arg1 arg1) = 0;
};

/**
 * @brief A 2 arg, single use callback that returns void.
 */
template <typename Arg0, typename Arg1>
class SingleUseCallback2<void, Arg0, Arg1>: public BaseCallback2<void, Arg0, Arg1> {  // NOLINT(whitespace/line_length)
 public:
  virtual ~SingleUseCallback2() {}
  void Run(Arg0 arg0, Arg1 arg1) {
    this->DoRun(arg0, arg1);
    delete this;
  }
 private:
  virtual void DoRun(Arg0 arg0, Arg1 arg1) = 0;
};

/**
 * @brief A Function callback with 0 create-time args and 2 exec time args
 */
template <typename Parent, typename ReturnType, typename Arg0, typename Arg1>
class FunctionCallback0_2: public Parent {
 public:
  typedef ReturnType (*Function)(Arg0, Arg1);
  explicit FunctionCallback0_2(Function callback):
    Parent(),
    m_callback(callback) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return m_callback(arg0, arg1);
  }
 private:
  Function m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename Arg0, typename Arg1>
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  ReturnType (*callback)(Arg0, Arg1)) {
  return new FunctionCallback0_2<
                                 SingleUseCallback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 Arg0,
                                 Arg1>(
      callback);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename Arg0, typename Arg1>
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  ReturnType (*callback)(Arg0, Arg1)) {
  return new FunctionCallback0_2<
                                 Callback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 Arg0,
                                 Arg1>(
      callback);
}


/**
 * @brief A Method callback with 0 create-time args and 2 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class MethodCallback0_2: public Parent {
 public:
  typedef ReturnType (Class::*Method)(Arg0, Arg1);
  MethodCallback0_2(Class *object, Method callback):
    Parent(),
    m_object(object),
    m_callback(callback) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return (m_object->*m_callback)(arg0, arg1);
  }
 private:
  Class *m_object;
  Method m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename Arg0, typename Arg1>
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(Arg0, Arg1)) {
  return new MethodCallback0_2<Class,
                               SingleUseCallback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               Arg0,
                               Arg1>(
      object,
      method);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename Arg0, typename Arg1>
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(Arg0, Arg1)) {
  return new MethodCallback0_2<Class,
                               Callback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               Arg0,
                               Arg1>(
      object,
      method);
}


/**
 * @brief A Function callback with 1 create-time args and 2 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class FunctionCallback1_2: public Parent {
 public:
  typedef ReturnType (*Function)(A0, Arg0, Arg1);
  FunctionCallback1_2(Function callback, A0 a0):
    Parent(),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return m_callback(m_a0, arg0, arg1);
  }
 private:
  Function m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename Arg0, typename Arg1>
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  ReturnType (*callback)(A0, Arg0, Arg1),
  A0 a0) {
  return new FunctionCallback1_2<
                                 SingleUseCallback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 A0,
                                 Arg0,
                                 Arg1>(
      callback,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename Arg0, typename Arg1>
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  ReturnType (*callback)(A0, Arg0, Arg1),
  A0 a0) {
  return new FunctionCallback1_2<
                                 Callback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 A0,
                                 Arg0,
                                 Arg1>(
      callback,
      a0);
}


/**
 * @brief A Method callback with 1 create-time args and 2 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class MethodCallback1_2: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, Arg0, Arg1);
  MethodCallback1_2(Class *object, Method callback, A0 a0):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return (m_object->*m_callback)(m_a0, arg0, arg1);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, Arg0, Arg1),
  A0 a0) {
  return new MethodCallback1_2<Class,
                               SingleUseCallback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               A0,
                               Arg0,
                               Arg1>(
      object,
      method,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, Arg0, Arg1),
  A0 a0) {
  return new MethodCallback1_2<Class,
                               Callback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               A0,
                               Arg0,
                               Arg1>(
      object,
      method,
      a0);
}


/**
 * @brief A Function callback with 2 create-time args and 2 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class FunctionCallback2_2: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, Arg0, Arg1);
  FunctionCallback2_2(Function callback, A0 a0, A1 a1):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return m_callback(m_a0, m_a1, arg0, arg1);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, Arg0, Arg1),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_2<
                                 SingleUseCallback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 Arg0,
                                 Arg1>(
      callback,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  ReturnType (*callback)(A0, A1, Arg0, Arg1),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_2<
                                 Callback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 Arg0,
                                 Arg1>(
      callback,
      a0,
      a1);
}


/**
 * @brief A Method callback with 2 create-time args and 2 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class MethodCallback2_2: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, Arg0, Arg1);
  MethodCallback2_2(Class *object, Method callback, A0 a0, A1 a1):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return (m_object->*m_callback)(m_a0, m_a1, arg0, arg1);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, Arg0, Arg1),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_2<Class,
                               SingleUseCallback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               A0,
                               A1,
                               Arg0,
                               Arg1>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, Arg0, Arg1),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_2<Class,
                               Callback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               A0,
                               A1,
                               Arg0,
                               Arg1>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A Function callback with 3 create-time args and 2 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class FunctionCallback3_2: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, Arg0, Arg1);
  FunctionCallback3_2(Function callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return m_callback(m_a0, m_a1, m_a2, arg0, arg1);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, A2, Arg0, Arg1),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_2<
                                 SingleUseCallback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 Arg0,
                                 Arg1>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, Arg0, Arg1),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_2<
                                 Callback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 Arg0,
                                 Arg1>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A Method callback with 3 create-time args and 2 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class MethodCallback3_2: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, Arg0, Arg1);
  MethodCallback3_2(Class *object, Method callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, arg0, arg1);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, Arg0, Arg1),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_2<Class,
                               SingleUseCallback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               Arg0,
                               Arg1>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, Arg0, Arg1),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_2<Class,
                               Callback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               Arg0,
                               Arg1>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A Function callback with 4 create-time args and 2 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class FunctionCallback4_2: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, A3, Arg0, Arg1);
  FunctionCallback4_2(Function callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return m_callback(m_a0, m_a1, m_a2, m_a3, arg0, arg1);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, A2, A3, Arg0, Arg1),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_2<
                                 SingleUseCallback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3,
                                 Arg0,
                                 Arg1>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 2 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, A3, Arg0, Arg1),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_2<
                                 Callback2<ReturnType, Arg0, Arg1>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3,
                                 Arg0,
                                 Arg1>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A Method callback with 4 create-time args and 2 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
class MethodCallback4_2: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, A3, Arg0, Arg1);
  MethodCallback4_2(Class *object, Method callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1) {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, m_a3, arg0, arg1);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline SingleUseCallback2<ReturnType, Arg0, Arg1>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3, Arg0, Arg1),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_2<Class,
                               SingleUseCallback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3,
                               Arg0,
                               Arg1>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 2 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1>  // NOLINT(whitespace/line_length)
inline Callback2<ReturnType, Arg0, Arg1>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3, Arg0, Arg1),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_2<Class,
                               Callback2<ReturnType, Arg0, Arg1>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3,
                               Arg0,
                               Arg1>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief The base class for all 3 argument callbacks.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
class BaseCallback3 {
 public:
  virtual ~BaseCallback3() {}
  virtual ReturnType Run(Arg0 arg0, Arg1 arg1, Arg2 arg2) = 0;
};

/**
 * @brief A 3 argument callback which can be called multiple times.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
class Callback3: public BaseCallback3<ReturnType, Arg0, Arg1, Arg2> {
 public:
  virtual ~Callback3() {}
  ReturnType Run(Arg0 arg0, Arg1 arg1, Arg2 arg2) { return this->DoRun(arg0, arg1, arg2); }  // NOLINT(whitespace/line_length)
 private:
  virtual ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) = 0;
};

/**
 * @brief A 3 argument callback which deletes itself after it's run.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
class SingleUseCallback3: public BaseCallback3<ReturnType, Arg0, Arg1, Arg2> {
 public:
  virtual ~SingleUseCallback3() {}
  ReturnType Run(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    ReturnType ret = this->DoRun(arg0, arg1, arg2);
    delete this;
    return ret;
  }
 private:
  virtual ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) = 0;
};

/**
 * @brief A 3 arg, single use callback that returns void.
 */
template <typename Arg0, typename Arg1, typename Arg2>
class SingleUseCallback3<void, Arg0, Arg1, Arg2>: public BaseCallback3<void, Arg0, Arg1, Arg2> {  // NOLINT(whitespace/line_length)
 public:
  virtual ~SingleUseCallback3() {}
  void Run(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    this->DoRun(arg0, arg1, arg2);
    delete this;
  }
 private:
  virtual void DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) = 0;
};

/**
 * @brief A Function callback with 0 create-time args and 3 exec time args
 */
template <typename Parent, typename ReturnType, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class FunctionCallback0_3: public Parent {
 public:
  typedef ReturnType (*Function)(Arg0, Arg1, Arg2);
  explicit FunctionCallback0_3(Function callback):
    Parent(),
    m_callback(callback) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return m_callback(arg0, arg1, arg2);
  }
 private:
  Function m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  ReturnType (*callback)(Arg0, Arg1, Arg2)) {
  return new FunctionCallback0_3<
                                 SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2>
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  ReturnType (*callback)(Arg0, Arg1, Arg2)) {
  return new FunctionCallback0_3<
                                 Callback3<ReturnType, Arg0, Arg1, Arg2>,
                                 ReturnType,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback);
}


/**
 * @brief A Method callback with 0 create-time args and 3 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class MethodCallback0_3: public Parent {
 public:
  typedef ReturnType (Class::*Method)(Arg0, Arg1, Arg2);
  MethodCallback0_3(Class *object, Method callback):
    Parent(),
    m_object(object),
    m_callback(callback) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return (m_object->*m_callback)(arg0, arg1, arg2);
  }
 private:
  Class *m_object;
  Method m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(Arg0, Arg1, Arg2)) {
  return new MethodCallback0_3<Class,
                               SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(Arg0, Arg1, Arg2)) {
  return new MethodCallback0_3<Class,
                               Callback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method);
}


/**
 * @brief A Function callback with 1 create-time args and 3 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class FunctionCallback1_3: public Parent {
 public:
  typedef ReturnType (*Function)(A0, Arg0, Arg1, Arg2);
  FunctionCallback1_3(Function callback, A0 a0):
    Parent(),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return m_callback(m_a0, arg0, arg1, arg2);
  }
 private:
  Function m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  ReturnType (*callback)(A0, Arg0, Arg1, Arg2),
  A0 a0) {
  return new FunctionCallback1_3<
                                 SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 A0,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  ReturnType (*callback)(A0, Arg0, Arg1, Arg2),
  A0 a0) {
  return new FunctionCallback1_3<
                                 Callback3<ReturnType, Arg0, Arg1, Arg2>,
                                 ReturnType,
                                 A0,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback,
      a0);
}


/**
 * @brief A Method callback with 1 create-time args and 3 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class MethodCallback1_3: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, Arg0, Arg1, Arg2);
  MethodCallback1_3(Class *object, Method callback, A0 a0):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return (m_object->*m_callback)(m_a0, arg0, arg1, arg2);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, Arg0, Arg1, Arg2),
  A0 a0) {
  return new MethodCallback1_3<Class,
                               SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               A0,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, Arg0, Arg1, Arg2),
  A0 a0) {
  return new MethodCallback1_3<Class,
                               Callback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               A0,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method,
      a0);
}


/**
 * @brief A Function callback with 2 create-time args and 3 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class FunctionCallback2_3: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, Arg0, Arg1, Arg2);
  FunctionCallback2_3(Function callback, A0 a0, A1 a1):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return m_callback(m_a0, m_a1, arg0, arg1, arg2);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_3<
                                 SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 A0,
                                 A1,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  ReturnType (*callback)(A0, A1, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_3<
                                 Callback3<ReturnType, Arg0, Arg1, Arg2>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback,
      a0,
      a1);
}


/**
 * @brief A Method callback with 2 create-time args and 3 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class MethodCallback2_3: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, Arg0, Arg1, Arg2);
  MethodCallback2_3(Class *object, Method callback, A0 a0, A1 a1):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return (m_object->*m_callback)(m_a0, m_a1, arg0, arg1, arg2);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_3<Class,
                               SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               A0,
                               A1,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_3<Class,
                               Callback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               A0,
                               A1,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A Function callback with 3 create-time args and 3 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class FunctionCallback3_3: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, Arg0, Arg1, Arg2);
  FunctionCallback3_3(Function callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return m_callback(m_a0, m_a1, m_a2, arg0, arg1, arg2);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, A2, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_3<
                                 SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_3<
                                 Callback3<ReturnType, Arg0, Arg1, Arg2>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A Method callback with 3 create-time args and 3 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class MethodCallback3_3: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, Arg0, Arg1, Arg2);
  MethodCallback3_3(Class *object, Method callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, arg0, arg1, arg2);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_3<Class,
                               SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_3<Class,
                               Callback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A Function callback with 4 create-time args and 3 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class FunctionCallback4_3: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, A3, Arg0, Arg1, Arg2);
  FunctionCallback4_3(Function callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return m_callback(m_a0, m_a1, m_a2, m_a3, arg0, arg1, arg2);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  ReturnType (*callback)(A0, A1, A2, A3, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_3<
                                 SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 3 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, A3, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_3<
                                 Callback3<ReturnType, Arg0, Arg1, Arg2>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3,
                                 Arg0,
                                 Arg1,
                                 Arg2>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A Method callback with 4 create-time args and 3 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
class MethodCallback4_3: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, A3, Arg0, Arg1, Arg2);
  MethodCallback4_3(Class *object, Method callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2) {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, m_a3, arg0, arg1, arg2);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>* NewSingleCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_3<Class,
                               SingleUseCallback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 3 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2>  // NOLINT(whitespace/line_length)
inline Callback3<ReturnType, Arg0, Arg1, Arg2>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3, Arg0, Arg1, Arg2),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_3<Class,
                               Callback3<ReturnType, Arg0, Arg1, Arg2>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3,
                               Arg0,
                               Arg1,
                               Arg2>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief The base class for all 4 argument callbacks.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class BaseCallback4 {
 public:
  virtual ~BaseCallback4() {}
  virtual ReturnType Run(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
};

/**
 * @brief A 4 argument callback which can be called multiple times.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class Callback4: public BaseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3> {
 public:
  virtual ~Callback4() {}
  ReturnType Run(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) { return this->DoRun(arg0, arg1, arg2, arg3); }  // NOLINT(whitespace/line_length)
 private:
  virtual ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
};

/**
 * @brief A 4 argument callback which deletes itself after it's run.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class SingleUseCallback4: public BaseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3> {  // NOLINT(whitespace/line_length)
 public:
  virtual ~SingleUseCallback4() {}
  ReturnType Run(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    ReturnType ret = this->DoRun(arg0, arg1, arg2, arg3);
    delete this;
    return ret;
  }
 private:
  virtual ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
};

/**
 * @brief A 4 arg, single use callback that returns void.
 */
template <typename Arg0, typename Arg1, typename Arg2, typename Arg3>
class SingleUseCallback4<void, Arg0, Arg1, Arg2, Arg3>: public BaseCallback4<void, Arg0, Arg1, Arg2, Arg3> {  // NOLINT(whitespace/line_length)
 public:
  virtual ~SingleUseCallback4() {}
  void Run(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    this->DoRun(arg0, arg1, arg2, arg3);
    delete this;
  }
 private:
  virtual void DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
};

/**
 * @brief A Function callback with 0 create-time args and 4 exec time args
 */
template <typename Parent, typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class FunctionCallback0_4: public Parent {
 public:
  typedef ReturnType (*Function)(Arg0, Arg1, Arg2, Arg3);
  explicit FunctionCallback0_4(Function callback):
    Parent(),
    m_callback(callback) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return m_callback(arg0, arg1, arg2, arg3);
  }
 private:
  Function m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  ReturnType (*callback)(Arg0, Arg1, Arg2, Arg3)) {
  return new FunctionCallback0_4<
                                 SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  ReturnType (*callback)(Arg0, Arg1, Arg2, Arg3)) {
  return new FunctionCallback0_4<
                                 Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                                 ReturnType,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback);
}


/**
 * @brief A Method callback with 0 create-time args and 4 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class MethodCallback0_4: public Parent {
 public:
  typedef ReturnType (Class::*Method)(Arg0, Arg1, Arg2, Arg3);
  MethodCallback0_4(Class *object, Method callback):
    Parent(),
    m_object(object),
    m_callback(callback) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return (m_object->*m_callback)(arg0, arg1, arg2, arg3);
  }
 private:
  Class *m_object;
  Method m_callback;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 0
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  Class* object,
  ReturnType (Class::*method)(Arg0, Arg1, Arg2, Arg3)) {
  return new MethodCallback0_4<Class,
                               SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                               ReturnType,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method);
}


/**
 * @brief A helper function to create a new Callback with 0
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(Arg0, Arg1, Arg2, Arg3)) {
  return new MethodCallback0_4<Class,
                               Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                               ReturnType,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method);
}


/**
 * @brief A Function callback with 1 create-time args and 4 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class FunctionCallback1_4: public Parent {
 public:
  typedef ReturnType (*Function)(A0, Arg0, Arg1, Arg2, Arg3);
  FunctionCallback1_4(Function callback, A0 a0):
    Parent(),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return m_callback(m_a0, arg0, arg1, arg2, arg3);
  }
 private:
  Function m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  ReturnType (*callback)(A0, Arg0, Arg1, Arg2, Arg3),
  A0 a0) {
  return new FunctionCallback1_4<
                                 SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 A0,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  ReturnType (*callback)(A0, Arg0, Arg1, Arg2, Arg3),
  A0 a0) {
  return new FunctionCallback1_4<
                                 Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                                 ReturnType,
                                 A0,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback,
      a0);
}


/**
 * @brief A Method callback with 1 create-time args and 4 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class MethodCallback1_4: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, Arg0, Arg1, Arg2, Arg3);
  MethodCallback1_4(Class *object, Method callback, A0 a0):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return (m_object->*m_callback)(m_a0, arg0, arg1, arg2, arg3);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 1
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  Class* object,
  ReturnType (Class::*method)(A0, Arg0, Arg1, Arg2, Arg3),
  A0 a0) {
  return new MethodCallback1_4<Class,
                               SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                               ReturnType,
                               A0,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method,
      a0);
}


/**
 * @brief A helper function to create a new Callback with 1
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, Arg0, Arg1, Arg2, Arg3),
  A0 a0) {
  return new MethodCallback1_4<Class,
                               Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                               ReturnType,
                               A0,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method,
      a0);
}


/**
 * @brief A Function callback with 2 create-time args and 4 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class FunctionCallback2_4: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, Arg0, Arg1, Arg2, Arg3);
  FunctionCallback2_4(Function callback, A0 a0, A1 a1):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return m_callback(m_a0, m_a1, arg0, arg1, arg2, arg3);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  ReturnType (*callback)(A0, A1, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_4<
                                 SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 A0,
                                 A1,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  ReturnType (*callback)(A0, A1, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1) {
  return new FunctionCallback2_4<
                                 Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback,
      a0,
      a1);
}


/**
 * @brief A Method callback with 2 create-time args and 4 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class MethodCallback2_4: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, Arg0, Arg1, Arg2, Arg3);
  MethodCallback2_4(Class *object, Method callback, A0 a0, A1 a1):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return (m_object->*m_callback)(m_a0, m_a1, arg0, arg1, arg2, arg3);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 2
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  Class* object,
  ReturnType (Class::*method)(A0, A1, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_4<Class,
                               SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                               ReturnType,
                               A0,
                               A1,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A helper function to create a new Callback with 2
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1) {
  return new MethodCallback2_4<Class,
                               Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                               ReturnType,
                               A0,
                               A1,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method,
      a0,
      a1);
}


/**
 * @brief A Function callback with 3 create-time args and 4 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class FunctionCallback3_4: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, Arg0, Arg1, Arg2, Arg3);
  FunctionCallback3_4(Function callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return m_callback(m_a0, m_a1, m_a2, arg0, arg1, arg2, arg3);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  ReturnType (*callback)(A0, A1, A2, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_4<
                                 SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new FunctionCallback3_4<
                                 Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback,
      a0,
      a1,
      a2);
}


/**
 * @brief A Method callback with 3 create-time args and 4 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class MethodCallback3_4: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, Arg0, Arg1, Arg2, Arg3);
  MethodCallback3_4(Class *object, Method callback, A0 a0, A1 a1, A2 a2):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, arg0, arg1, arg2, arg3);
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 3
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_4<Class,
                               SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A helper function to create a new Callback with 3
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1,
  A2 a2) {
  return new MethodCallback3_4<Class,
                               Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method,
      a0,
      a1,
      a2);
}


/**
 * @brief A Function callback with 4 create-time args and 4 exec time args
 */
template <typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class FunctionCallback4_4: public Parent {
 public:
  typedef ReturnType (*Function)(A0, A1, A2, A3, Arg0, Arg1, Arg2, Arg3);
  FunctionCallback4_4(Function callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return m_callback(m_a0, m_a1, m_a2, m_a3, arg0, arg1, arg2, arg3);
  }
 private:
  Function m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  ReturnType (*callback)(A0, A1, A2, A3, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_4<
                                 SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 4 execution time arguments.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param callback the function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the function.
 */
template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  ReturnType (*callback)(A0, A1, A2, A3, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new FunctionCallback4_4<
                                 Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                                 ReturnType,
                                 A0,
                                 A1,
                                 A2,
                                 A3,
                                 Arg0,
                                 Arg1,
                                 Arg2,
                                 Arg3>(
      callback,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A Method callback with 4 create-time args and 4 exec time args
 */
template <typename Class, typename Parent, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
class MethodCallback4_4: public Parent {
 public:
  typedef ReturnType (Class::*Method)(A0, A1, A2, A3, Arg0, Arg1, Arg2, Arg3);
  MethodCallback4_4(Class *object, Method callback, A0 a0, A1 a1, A2 a2, A3 a3):
    Parent(),
    m_object(object),
    m_callback(callback),
    m_a0(a0),
    m_a1(a1),
    m_a2(a2),
    m_a3(a3) {}
  ReturnType DoRun(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
    return (m_object->*m_callback)(m_a0, m_a1, m_a2, m_a3, arg0, arg1, arg2, arg3);  // NOLINT(whitespace/line_length)
  }
 private:
  Class *m_object;
  Method m_callback;
  A0 m_a0;
  A1 m_a1;
  A2 m_a2;
  A3 m_a3;
};


/**
 * @brief A helper function to create a new SingleUseCallback with 4
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewSingleCallback(  // NOLINT(whitespace/line_length)
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_4<Class,
                               SingleUseCallback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,  // NOLINT(whitespace/line_length)
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @brief A helper function to create a new Callback with 4
 * create-time arguments and 4 execution time arguments.
 * @tparam Class the class with the member function.
 * @tparam ReturnType the return type of the callback.
 * @tparam A0 a create-time argument type.
 * @tparam A1 a create-time argument type.
 * @tparam A2 a create-time argument type.
 * @tparam A3 a create-time argument type.
 * @tparam Arg0 an exec-time argument type.
 * @tparam Arg1 an exec-time argument type.
 * @tparam Arg2 an exec-time argument type.
 * @tparam Arg3 an exec-time argument type.
 * @param object the object to call the member function on.
 * @param method the member function pointer to use when executing the callback.
 * @param a0 a create-time argument.
 * @param a1 a create-time argument.
 * @param a2 a create-time argument.
 * @param a3 a create-time argument.
 * @returns The same return value as the member function.
 */
template <typename Class, typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename Arg0, typename Arg1, typename Arg2, typename Arg3>  // NOLINT(whitespace/line_length)
inline Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>* NewCallback(
  Class* object,
  ReturnType (Class::*method)(A0, A1, A2, A3, Arg0, Arg1, Arg2, Arg3),
  A0 a0,
  A1 a1,
  A2 a2,
  A3 a3) {
  return new MethodCallback4_4<Class,
                               Callback4<ReturnType, Arg0, Arg1, Arg2, Arg3>,
                               ReturnType,
                               A0,
                               A1,
                               A2,
                               A3,
                               Arg0,
                               Arg1,
                               Arg2,
                               Arg3>(
      object,
      method,
      a0,
      a1,
      a2,
      a3);
}


/**
 * @}
 */
}  // namespace ola
#endif  // INCLUDE_OLA_CALLBACK_H_
