// This file was GENERATED by command:
//     pump.py bind_internal_functor.h.pump
// DO NOT EDIT BY HAND!!!


// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_BIND_INTERNAL_FUNCTOR_H_
#define BASE_BIND_INTERNAL_FUNCTOR_H_

namespace base {
namespace internal {

// The RunnableAdapterFunctor<> template is used in a template specialization
// for RunnableAdapter<> which enables support for functor objects, including
// C++11 lambdas. The functor signature is deduced from the type of the
// operator() method using decltype().
//
// All supported functors are assumed to have a const qualifier in their
// operator() method.

template <typename Functor>
class RunnableAdapter;

template <typename Functor, typename Sig>
class RunnableAdapterFunctor;

template <typename Functor>
class RunnableAdapter
    : public RunnableAdapterFunctor<Functor, decltype(&Functor::operator())> {
 public:
  typedef RunnableAdapterFunctor<Functor,
      decltype(&Functor::operator())> BaseType;

  explicit RunnableAdapter(Functor functor)
      : BaseType(functor) {}
};

// Functor: Arity 0.
template <typename F, typename T, typename R>
class RunnableAdapterFunctor<F, R(T::*)() const> {
 public:
  typedef R (RunType)();

  explicit RunnableAdapterFunctor(F functor)
      : functor_(functor) {
  }

  R Run() {
    return functor_();
  }

 private:
  F functor_;
};

// Functor: Arity 1.
template <typename F, typename T, typename R, typename A1>
class RunnableAdapterFunctor<F, R(T::*)(A1) const> {
 public:
  typedef R (RunType)(A1);

  explicit RunnableAdapterFunctor(F functor)
      : functor_(functor) {
  }

  R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
    return functor_(CallbackForward(a1));
  }

 private:
  F functor_;
};

// Functor: Arity 2.
template <typename F, typename T, typename R, typename A1, typename A2>
class RunnableAdapterFunctor<F, R(T::*)(A1, A2) const> {
 public:
  typedef R (RunType)(A1, A2);

  explicit RunnableAdapterFunctor(F functor)
      : functor_(functor) {
  }

  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
      typename CallbackParamTraits<A2>::ForwardType a2) {
    return functor_(CallbackForward(a1), CallbackForward(a2));
  }

 private:
  F functor_;
};

// Functor: Arity 3.
template <typename F, typename T, typename R, typename A1, typename A2,
    typename A3>
class RunnableAdapterFunctor<F, R(T::*)(A1, A2, A3) const> {
 public:
  typedef R (RunType)(A1, A2, A3);

  explicit RunnableAdapterFunctor(F functor)
      : functor_(functor) {
  }

  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
      typename CallbackParamTraits<A2>::ForwardType a2,
      typename CallbackParamTraits<A3>::ForwardType a3) {
    return functor_(CallbackForward(a1), CallbackForward(a2),
        CallbackForward(a3));
  }

 private:
  F functor_;
};

// Functor: Arity 4.
template <typename F, typename T, typename R, typename A1, typename A2,
    typename A3, typename A4>
class RunnableAdapterFunctor<F, R(T::*)(A1, A2, A3, A4) const> {
 public:
  typedef R (RunType)(A1, A2, A3, A4);

  explicit RunnableAdapterFunctor(F functor)
      : functor_(functor) {
  }

  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
      typename CallbackParamTraits<A2>::ForwardType a2,
      typename CallbackParamTraits<A3>::ForwardType a3,
      typename CallbackParamTraits<A4>::ForwardType a4) {
    return functor_(CallbackForward(a1), CallbackForward(a2),
        CallbackForward(a3), CallbackForward(a4));
  }

 private:
  F functor_;
};

// Functor: Arity 5.
template <typename F, typename T, typename R, typename A1, typename A2,
    typename A3, typename A4, typename A5>
class RunnableAdapterFunctor<F, R(T::*)(A1, A2, A3, A4, A5) const> {
 public:
  typedef R (RunType)(A1, A2, A3, A4, A5);

  explicit RunnableAdapterFunctor(F functor)
      : functor_(functor) {
  }

  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
      typename CallbackParamTraits<A2>::ForwardType a2,
      typename CallbackParamTraits<A3>::ForwardType a3,
      typename CallbackParamTraits<A4>::ForwardType a4,
      typename CallbackParamTraits<A5>::ForwardType a5) {
    return functor_(CallbackForward(a1), CallbackForward(a2),
        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5));
  }

 private:
  F functor_;
};

// Functor: Arity 6.
template <typename F, typename T, typename R, typename A1, typename A2,
    typename A3, typename A4, typename A5, typename A6>
class RunnableAdapterFunctor<F, R(T::*)(A1, A2, A3, A4, A5, A6) const> {
 public:
  typedef R (RunType)(A1, A2, A3, A4, A5, A6);

  explicit RunnableAdapterFunctor(F functor)
      : functor_(functor) {
  }

  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
      typename CallbackParamTraits<A2>::ForwardType a2,
      typename CallbackParamTraits<A3>::ForwardType a3,
      typename CallbackParamTraits<A4>::ForwardType a4,
      typename CallbackParamTraits<A5>::ForwardType a5,
      typename CallbackParamTraits<A6>::ForwardType a6) {
    return functor_(CallbackForward(a1), CallbackForward(a2),
        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
        CallbackForward(a6));
  }

 private:
  F functor_;
};

// Functor: Arity 7.
template <typename F, typename T, typename R, typename A1, typename A2,
    typename A3, typename A4, typename A5, typename A6, typename A7>
class RunnableAdapterFunctor<F, R(T::*)(A1, A2, A3, A4, A5, A6, A7) const> {
 public:
  typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7);

  explicit RunnableAdapterFunctor(F functor)
      : functor_(functor) {
  }

  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
      typename CallbackParamTraits<A2>::ForwardType a2,
      typename CallbackParamTraits<A3>::ForwardType a3,
      typename CallbackParamTraits<A4>::ForwardType a4,
      typename CallbackParamTraits<A5>::ForwardType a5,
      typename CallbackParamTraits<A6>::ForwardType a6,
      typename CallbackParamTraits<A7>::ForwardType a7) {
    return functor_(CallbackForward(a1), CallbackForward(a2),
        CallbackForward(a3), CallbackForward(a4), CallbackForward(a5),
        CallbackForward(a6), CallbackForward(a7));
  }

 private:
  F functor_;
};

}  // namespace internal
}  // namespace base

#endif  // BASE_BIND_INTERNAL_FUNCTOR_H_
