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



// Copyright (c) 2011 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_H_
#define BASE_BIND_INTERNAL_H_
#pragma once

#include "base/bind_helpers.h"
#include "base/callback_internal.h"
#include "base/template_util.h"
#include "build/build_config.h"

#if defined(OS_WIN)
#include "base/bind_internal_win.h"
#endif

namespace base {
namespace internal {

// The method by which a function is invoked is determined by 3 different
// dimensions:
//
//   1) The type of function (normal or method).
//   2) The arity of the function.
//   3) The number of bound parameters.
//
// The templates below handle the determination of each of these dimensions.
// In brief:
//
//   FunctionTraits<> -- Provides a normalied signature, and other traits.
//   InvokerN<> -- Provides a DoInvoke() function that actually executes
//                 a calback.
//   InvokerStorageN<> -- Provides storage for the bound parameters, and
//                        typedefs to the above.
//
// More details about the design of each class is included in a comment closer
// to their defition.

// FunctionTraits<>
//
// The FunctionTraits<> template determines the type of function, and also
// creates a NormalizedType used to select the InvokerN classes.  It turns out
// that syntactically, you only really have 2 variations when invoking a
// funciton pointer: normal, and method.  One is invoked func_ptr(arg1). The
// other is invoked (*obj_->method_ptr(arg1)).
//
// However, in the type system, there are many more distinctions. In standard
// C++, there's all variations of const, and volatile on the function pointer.
// In Windows, there are additional calling conventions (eg., __stdcall,
// __fastcall, etc.). FunctionTraits<> handles categorizing each of these into
// a normalized signature.
//
// Having a NormalizedSignature signature, reduces the combinatoric
// complexity of defintions for the InvokerN<> later.  Even though there are
// only 2 syntactic variations on invoking a function, without normalizing the
// signature, there would need to be one specialization of InvokerN for each
// unique (function_type, bound_arg, unbound_args) tuple in order to match all
// function signatures.
//
// By normalizing the function signature, we reduce function_type to exactly 2.

template <typename Sig>
struct FunctionTraits;

// Function: Arity 0.
template <typename R>
struct FunctionTraits<R(*)()> {
  typedef R (*NormalizedSig)();
  typedef false_type IsMethod;

};

// Method: Arity 0.
template <typename R, typename T>
struct FunctionTraits<R(T::*)()> {
  typedef R (T::*NormalizedSig)();
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;

};

// Const Method: Arity 0.
template <typename R, typename T>
struct FunctionTraits<R(T::*)() const> {
  typedef R (T::*NormalizedSig)();
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;

};

// Function: Arity 1.
template <typename R, typename X1>
struct FunctionTraits<R(*)(X1)> {
  typedef R (*NormalizedSig)(X1);
  typedef false_type IsMethod;
  // Target type for each bound parameter.
  typedef X1 B1;

};

// Method: Arity 1.
template <typename R, typename T, typename X1>
struct FunctionTraits<R(T::*)(X1)> {
  typedef R (T::*NormalizedSig)(X1);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;

};

// Const Method: Arity 1.
template <typename R, typename T, typename X1>
struct FunctionTraits<R(T::*)(X1) const> {
  typedef R (T::*NormalizedSig)(X1);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;

};

// Function: Arity 2.
template <typename R, typename X1, typename X2>
struct FunctionTraits<R(*)(X1, X2)> {
  typedef R (*NormalizedSig)(X1, X2);
  typedef false_type IsMethod;
  // Target type for each bound parameter.
  typedef X1 B1;
  typedef X2 B2;

};

// Method: Arity 2.
template <typename R, typename T, typename X1, typename X2>
struct FunctionTraits<R(T::*)(X1, X2)> {
  typedef R (T::*NormalizedSig)(X1, X2);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;

};

// Const Method: Arity 2.
template <typename R, typename T, typename X1, typename X2>
struct FunctionTraits<R(T::*)(X1, X2) const> {
  typedef R (T::*NormalizedSig)(X1, X2);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;

};

// Function: Arity 3.
template <typename R, typename X1, typename X2, typename X3>
struct FunctionTraits<R(*)(X1, X2, X3)> {
  typedef R (*NormalizedSig)(X1, X2, X3);
  typedef false_type IsMethod;
  // Target type for each bound parameter.
  typedef X1 B1;
  typedef X2 B2;
  typedef X3 B3;

};

// Method: Arity 3.
template <typename R, typename T, typename X1, typename X2, typename X3>
struct FunctionTraits<R(T::*)(X1, X2, X3)> {
  typedef R (T::*NormalizedSig)(X1, X2, X3);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;
  typedef X3 B4;

};

// Const Method: Arity 3.
template <typename R, typename T, typename X1, typename X2, typename X3>
struct FunctionTraits<R(T::*)(X1, X2, X3) const> {
  typedef R (T::*NormalizedSig)(X1, X2, X3);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;
  typedef X3 B4;

};

// Function: Arity 4.
template <typename R, typename X1, typename X2, typename X3, typename X4>
struct FunctionTraits<R(*)(X1, X2, X3, X4)> {
  typedef R (*NormalizedSig)(X1, X2, X3, X4);
  typedef false_type IsMethod;
  // Target type for each bound parameter.
  typedef X1 B1;
  typedef X2 B2;
  typedef X3 B3;
  typedef X4 B4;

};

// Method: Arity 4.
template <typename R, typename T, typename X1, typename X2, typename X3,
    typename X4>
struct FunctionTraits<R(T::*)(X1, X2, X3, X4)> {
  typedef R (T::*NormalizedSig)(X1, X2, X3, X4);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;
  typedef X3 B4;
  typedef X4 B5;

};

// Const Method: Arity 4.
template <typename R, typename T, typename X1, typename X2, typename X3,
    typename X4>
struct FunctionTraits<R(T::*)(X1, X2, X3, X4) const> {
  typedef R (T::*NormalizedSig)(X1, X2, X3, X4);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;
  typedef X3 B4;
  typedef X4 B5;

};

// Function: Arity 5.
template <typename R, typename X1, typename X2, typename X3, typename X4,
    typename X5>
struct FunctionTraits<R(*)(X1, X2, X3, X4, X5)> {
  typedef R (*NormalizedSig)(X1, X2, X3, X4, X5);
  typedef false_type IsMethod;
  // Target type for each bound parameter.
  typedef X1 B1;
  typedef X2 B2;
  typedef X3 B3;
  typedef X4 B4;
  typedef X5 B5;

};

// Method: Arity 5.
template <typename R, typename T, typename X1, typename X2, typename X3,
    typename X4, typename X5>
struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5)> {
  typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;
  typedef X3 B4;
  typedef X4 B5;
  typedef X5 B6;

};

// Const Method: Arity 5.
template <typename R, typename T, typename X1, typename X2, typename X3,
    typename X4, typename X5>
struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5) const> {
  typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;
  typedef X3 B4;
  typedef X4 B5;
  typedef X5 B6;

};

// Function: Arity 6.
template <typename R, typename X1, typename X2, typename X3, typename X4,
    typename X5, typename X6>
struct FunctionTraits<R(*)(X1, X2, X3, X4, X5, X6)> {
  typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6);
  typedef false_type IsMethod;
  // Target type for each bound parameter.
  typedef X1 B1;
  typedef X2 B2;
  typedef X3 B3;
  typedef X4 B4;
  typedef X5 B5;
  typedef X6 B6;

};

// Method: Arity 6.
template <typename R, typename T, typename X1, typename X2, typename X3,
    typename X4, typename X5, typename X6>
struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6)> {
  typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;
  typedef X3 B4;
  typedef X4 B5;
  typedef X5 B6;
  typedef X6 B7;

};

// Const Method: Arity 6.
template <typename R, typename T, typename X1, typename X2, typename X3,
    typename X4, typename X5, typename X6>
struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6) const> {
  typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;
  typedef X1 B2;
  typedef X2 B3;
  typedef X3 B4;
  typedef X4 B5;
  typedef X5 B6;
  typedef X6 B7;

};

// InvokerN<>
//
// The InvokerN templates contain a static DoInvoke() function that is the key
// to implementing type erasure in the Callback() classes.
//
// DoInvoke() is a static function with a fixed signature that is independent
// of StorageType; its first argument is a pointer to the non-templated common
// baseclass of StorageType. This lets us store pointer to DoInvoke() in a
// function pointer that has knowledge of the specific StorageType, and thus
// no knowledge of the bound function and bound parameter types.
//
// As long as we ensure that DoInvoke() is only used with pointers there were
// upcasted from the correct StorageType, we can be sure that execution is
// safe.
//
// The InvokerN templates are the only point that knows the number of bound
// and unbound arguments.  This is intentional because it allows the other
// templates classes in the system to only have as many specializations as
// the max arity of function we wish to support.

template <typename StorageType, typename NormalizedSig>
struct Invoker0;

// Function: Arity 0 -> 0.
template <typename StorageType, typename R>
struct Invoker0<StorageType, R(*)()> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_();
  }
};

// Function: Arity 1 -> 1.
template <typename StorageType, typename R,typename X1>
struct Invoker0<StorageType, R(*)(X1)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(x1);
  }
};

// Function: Arity 2 -> 2.
template <typename StorageType, typename R,typename X1, typename X2>
struct Invoker0<StorageType, R(*)(X1, X2)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(x1, x2);
  }
};

// Function: Arity 3 -> 3.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3>
struct Invoker0<StorageType, R(*)(X1, X2, X3)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(x1, x2, x3);
  }
};

// Function: Arity 4 -> 4.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4>
struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(x1, x2, x3, x4);
  }
};

// Function: Arity 5 -> 5.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5>
struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(x1, x2, x3, x4, x5);
  }
};

// Function: Arity 6 -> 6.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5, typename X6>
struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5,
      typename internal::ParamTraits<X6>::ForwardType x6) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(x1, x2, x3, x4, x5, x6);
  }
};

template <typename StorageType, typename NormalizedSig>
struct Invoker1;

// Function: Arity 1 -> 0.
template <typename StorageType, typename R,typename X1>
struct Invoker1<StorageType, R(*)(X1)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_));
  }
};

// Method: Arity 0 -> 0.
template <typename StorageType, typename R, typename T>
struct Invoker1<StorageType, R(T::*)()> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)();
  }
};

// Function: Arity 2 -> 1.
template <typename StorageType, typename R,typename X1, typename X2>
struct Invoker1<StorageType, R(*)(X1, X2)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), x2);
  }
};

// Method: Arity 1 -> 1.
template <typename StorageType, typename R, typename T, typename X1>
struct Invoker1<StorageType, R(T::*)(X1)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(x1);
  }
};

// Function: Arity 3 -> 2.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3>
struct Invoker1<StorageType, R(*)(X1, X2, X3)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), x2, x3);
  }
};

// Method: Arity 2 -> 2.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2>
struct Invoker1<StorageType, R(T::*)(X1, X2)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2);
  }
};

// Function: Arity 4 -> 3.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4>
struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4);
  }
};

// Method: Arity 3 -> 3.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3>
struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3);
  }
};

// Function: Arity 5 -> 4.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5>
struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4, x5);
  }
};

// Method: Arity 4 -> 4.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4>
struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4);
  }
};

// Function: Arity 6 -> 5.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5, typename X6>
struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5,
      typename internal::ParamTraits<X6>::ForwardType x6) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4, x5, x6);
  }
};

// Method: Arity 5 -> 5.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4, typename X5>
struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X1>::ForwardType x1,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4, x5);
  }
};

template <typename StorageType, typename NormalizedSig>
struct Invoker2;

// Function: Arity 2 -> 0.
template <typename StorageType, typename R,typename X1, typename X2>
struct Invoker2<StorageType, R(*)(X1, X2)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_));
  }
};

// Method: Arity 1 -> 0.
template <typename StorageType, typename R, typename T, typename X1>
struct Invoker2<StorageType, R(T::*)(X1)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_));
  }
};

// Function: Arity 3 -> 1.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3>
struct Invoker2<StorageType, R(*)(X1, X2, X3)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X3>::ForwardType x3) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3);
  }
};

// Method: Arity 2 -> 1.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2>
struct Invoker2<StorageType, R(T::*)(X1, X2)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2);
  }
};

// Function: Arity 4 -> 2.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4>
struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4);
  }
};

// Method: Arity 3 -> 2.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3>
struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3);
  }
};

// Function: Arity 5 -> 3.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5>
struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5);
  }
};

// Method: Arity 4 -> 3.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4>
struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3,
        x4);
  }
};

// Function: Arity 6 -> 4.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5, typename X6>
struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5,
      typename internal::ParamTraits<X6>::ForwardType x6) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5,
        x6);
  }
};

// Method: Arity 5 -> 4.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4, typename X5>
struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X2>::ForwardType x2,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3,
        x4, x5);
  }
};

template <typename StorageType, typename NormalizedSig>
struct Invoker3;

// Function: Arity 3 -> 0.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3>
struct Invoker3<StorageType, R(*)(X1, X2, X3)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_));
  }
};

// Method: Arity 2 -> 0.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2>
struct Invoker3<StorageType, R(T::*)(X1, X2)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_));
  }
};

// Function: Arity 4 -> 1.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4>
struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X4>::ForwardType x4) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), x4);
  }
};

// Method: Arity 3 -> 1.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3>
struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X3>::ForwardType x3) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), x3);
  }
};

// Function: Arity 5 -> 2.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5>
struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), x4, x5);
  }
};

// Method: Arity 4 -> 2.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4>
struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), x3, x4);
  }
};

// Function: Arity 6 -> 3.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5, typename X6>
struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5,
      typename internal::ParamTraits<X6>::ForwardType x6) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), x4, x5, x6);
  }
};

// Method: Arity 5 -> 3.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4, typename X5>
struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X3>::ForwardType x3,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), x3, x4, x5);
  }
};

template <typename StorageType, typename NormalizedSig>
struct Invoker4;

// Function: Arity 4 -> 0.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4>
struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_));
  }
};

// Method: Arity 3 -> 0.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3>
struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_));
  }
};

// Function: Arity 5 -> 1.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5>
struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5);
  }
};

// Method: Arity 4 -> 1.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4>
struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X4>::ForwardType x4) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4);
  }
};

// Function: Arity 6 -> 2.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5, typename X6>
struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X5>::ForwardType x5,
      typename internal::ParamTraits<X6>::ForwardType x6) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5, x6);
  }
};

// Method: Arity 5 -> 2.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4, typename X5>
struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X4>::ForwardType x4,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4, x5);
  }
};

template <typename StorageType, typename NormalizedSig>
struct Invoker5;

// Function: Arity 5 -> 0.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5>
struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_));
  }
};

// Method: Arity 4 -> 0.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4>
struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_));
  }
};

// Function: Arity 6 -> 1.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5, typename X6>
struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X6>::ForwardType x6) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x6);
  }
};

// Method: Arity 5 -> 1.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4, typename X5>
struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base,
      typename internal::ParamTraits<X5>::ForwardType x5) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5);
  }
};

template <typename StorageType, typename NormalizedSig>
struct Invoker6;

// Function: Arity 6 -> 0.
template <typename StorageType, typename R,typename X1, typename X2,
    typename X3, typename X4, typename X5, typename X6>
struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_),
        Unwrap(invoker->p6_));
  }
};

// Method: Arity 5 -> 0.
template <typename StorageType, typename R, typename T, typename X1,
    typename X2, typename X3, typename X4, typename X5>
struct Invoker6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> {
  static R DoInvoke(InvokerStorageBase* base) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_),
        Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_),
        Unwrap(invoker->p6_));
  }
};


// InvokerStorageN<>
//
// These are the actual storage classes for the Invokers.
//
// Though these types are "classes", they are being used as structs with
// all member variable public.  We cannot make it a struct because it inherits
// from a class which causes a compiler warning.  We cannot add a "Run()" method
// that forwards the unbound arguments because that would require we unwrap the
// Sig type like in InvokerN above to know the return type, and the arity
// of Run().
//
// An alternate solution would be to merge InvokerN and InvokerStorageN,
// but the generated code seemed harder to read.

template <typename Sig>
class InvokerStorage0 : public InvokerStorageBase {
 public:
  typedef InvokerStorage0 StorageType;
  typedef FunctionTraits<Sig> TargetTraits;
  typedef Invoker0<StorageType, typename TargetTraits::NormalizedSig> Invoker;
  typedef typename TargetTraits::IsMethod IsMethod;



  InvokerStorage0(Sig f)
      : f_(f) {
  }

  virtual ~InvokerStorage0() {  }

  Sig f_;
};

template <typename Sig, typename P1>
class InvokerStorage1 : public InvokerStorageBase {
 public:
  typedef InvokerStorage1 StorageType;
  typedef FunctionTraits<Sig> TargetTraits;
  typedef Invoker1<StorageType, typename TargetTraits::NormalizedSig> Invoker;
  typedef typename TargetTraits::IsMethod IsMethod;

  // For methods, we need to be careful for parameter 1.  We skip the
  // scoped_refptr check because the binder itself takes care of this. We also
  // disallow binding of an array as the method's target object.
  COMPILE_ASSERT(IsMethod::value ||
                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
                 p1_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
                 first_bound_argument_to_method_cannot_be_array);

  // Do not allow binding a non-const reference parameter. Non-const reference
  // parameters are disallowed by the Google style guide.  Also, binding a
  // non-const reference parameter can make for subtle bugs because the
  // invoked function will receive a reference to the stored copy of the
  // argument and not the original.
  COMPILE_ASSERT(
      !( is_non_const_reference<typename TargetTraits::B1>::value ),
      do_not_bind_functions_with_nonconst_ref);


  InvokerStorage1(Sig f, const P1& p1)
      : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)) {
    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
  }

  virtual ~InvokerStorage1() {
    MaybeRefcount<IsMethod, P1>::Release(p1_);
  }

  Sig f_;
  typename ParamTraits<P1>::StorageType p1_;
};

template <typename Sig, typename P1, typename P2>
class InvokerStorage2 : public InvokerStorageBase {
 public:
  typedef InvokerStorage2 StorageType;
  typedef FunctionTraits<Sig> TargetTraits;
  typedef Invoker2<StorageType, typename TargetTraits::NormalizedSig> Invoker;
  typedef typename TargetTraits::IsMethod IsMethod;

  // For methods, we need to be careful for parameter 1.  We skip the
  // scoped_refptr check because the binder itself takes care of this. We also
  // disallow binding of an array as the method's target object.
  COMPILE_ASSERT(IsMethod::value ||
                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
                 p1_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
                 first_bound_argument_to_method_cannot_be_array);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
                 p2_is_refcounted_type_and_needs_scoped_refptr);

  // Do not allow binding a non-const reference parameter. Non-const reference
  // parameters are disallowed by the Google style guide.  Also, binding a
  // non-const reference parameter can make for subtle bugs because the
  // invoked function will receive a reference to the stored copy of the
  // argument and not the original.
  COMPILE_ASSERT(
      !( is_non_const_reference<typename TargetTraits::B1>::value ||
          is_non_const_reference<typename TargetTraits::B2>::value ),
      do_not_bind_functions_with_nonconst_ref);


  InvokerStorage2(Sig f, const P1& p1, const P2& p2)
      : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)),
          p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)) {
    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
  }

  virtual ~InvokerStorage2() {
    MaybeRefcount<IsMethod, P1>::Release(p1_);
  }

  Sig f_;
  typename ParamTraits<P1>::StorageType p1_;
  typename ParamTraits<P2>::StorageType p2_;
};

template <typename Sig, typename P1, typename P2, typename P3>
class InvokerStorage3 : public InvokerStorageBase {
 public:
  typedef InvokerStorage3 StorageType;
  typedef FunctionTraits<Sig> TargetTraits;
  typedef Invoker3<StorageType, typename TargetTraits::NormalizedSig> Invoker;
  typedef typename TargetTraits::IsMethod IsMethod;

  // For methods, we need to be careful for parameter 1.  We skip the
  // scoped_refptr check because the binder itself takes care of this. We also
  // disallow binding of an array as the method's target object.
  COMPILE_ASSERT(IsMethod::value ||
                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
                 p1_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
                 first_bound_argument_to_method_cannot_be_array);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
                 p2_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
                 p3_is_refcounted_type_and_needs_scoped_refptr);

  // Do not allow binding a non-const reference parameter. Non-const reference
  // parameters are disallowed by the Google style guide.  Also, binding a
  // non-const reference parameter can make for subtle bugs because the
  // invoked function will receive a reference to the stored copy of the
  // argument and not the original.
  COMPILE_ASSERT(
      !( is_non_const_reference<typename TargetTraits::B1>::value ||
          is_non_const_reference<typename TargetTraits::B2>::value ||
          is_non_const_reference<typename TargetTraits::B3>::value ),
      do_not_bind_functions_with_nonconst_ref);


  InvokerStorage3(Sig f, const P1& p1, const P2& p2, const P3& p3)
      : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)),
          p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)),
          p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)) {
    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
  }

  virtual ~InvokerStorage3() {
    MaybeRefcount<IsMethod, P1>::Release(p1_);
  }

  Sig f_;
  typename ParamTraits<P1>::StorageType p1_;
  typename ParamTraits<P2>::StorageType p2_;
  typename ParamTraits<P3>::StorageType p3_;
};

template <typename Sig, typename P1, typename P2, typename P3, typename P4>
class InvokerStorage4 : public InvokerStorageBase {
 public:
  typedef InvokerStorage4 StorageType;
  typedef FunctionTraits<Sig> TargetTraits;
  typedef Invoker4<StorageType, typename TargetTraits::NormalizedSig> Invoker;
  typedef typename TargetTraits::IsMethod IsMethod;

  // For methods, we need to be careful for parameter 1.  We skip the
  // scoped_refptr check because the binder itself takes care of this. We also
  // disallow binding of an array as the method's target object.
  COMPILE_ASSERT(IsMethod::value ||
                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
                 p1_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
                 first_bound_argument_to_method_cannot_be_array);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
                 p2_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
                 p3_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
                 p4_is_refcounted_type_and_needs_scoped_refptr);

  // Do not allow binding a non-const reference parameter. Non-const reference
  // parameters are disallowed by the Google style guide.  Also, binding a
  // non-const reference parameter can make for subtle bugs because the
  // invoked function will receive a reference to the stored copy of the
  // argument and not the original.
  COMPILE_ASSERT(
      !( is_non_const_reference<typename TargetTraits::B1>::value ||
          is_non_const_reference<typename TargetTraits::B2>::value ||
          is_non_const_reference<typename TargetTraits::B3>::value ||
          is_non_const_reference<typename TargetTraits::B4>::value ),
      do_not_bind_functions_with_nonconst_ref);


  InvokerStorage4(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4)
      : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)),
          p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)),
          p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)),
          p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)) {
    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
  }

  virtual ~InvokerStorage4() {
    MaybeRefcount<IsMethod, P1>::Release(p1_);
  }

  Sig f_;
  typename ParamTraits<P1>::StorageType p1_;
  typename ParamTraits<P2>::StorageType p2_;
  typename ParamTraits<P3>::StorageType p3_;
  typename ParamTraits<P4>::StorageType p4_;
};

template <typename Sig, typename P1, typename P2, typename P3, typename P4,
    typename P5>
class InvokerStorage5 : public InvokerStorageBase {
 public:
  typedef InvokerStorage5 StorageType;
  typedef FunctionTraits<Sig> TargetTraits;
  typedef Invoker5<StorageType, typename TargetTraits::NormalizedSig> Invoker;
  typedef typename TargetTraits::IsMethod IsMethod;

  // For methods, we need to be careful for parameter 1.  We skip the
  // scoped_refptr check because the binder itself takes care of this. We also
  // disallow binding of an array as the method's target object.
  COMPILE_ASSERT(IsMethod::value ||
                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
                 p1_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
                 first_bound_argument_to_method_cannot_be_array);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
                 p2_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
                 p3_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
                 p4_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P5>::value,
                 p5_is_refcounted_type_and_needs_scoped_refptr);

  // Do not allow binding a non-const reference parameter. Non-const reference
  // parameters are disallowed by the Google style guide.  Also, binding a
  // non-const reference parameter can make for subtle bugs because the
  // invoked function will receive a reference to the stored copy of the
  // argument and not the original.
  COMPILE_ASSERT(
      !( is_non_const_reference<typename TargetTraits::B1>::value ||
          is_non_const_reference<typename TargetTraits::B2>::value ||
          is_non_const_reference<typename TargetTraits::B3>::value ||
          is_non_const_reference<typename TargetTraits::B4>::value ||
          is_non_const_reference<typename TargetTraits::B5>::value ),
      do_not_bind_functions_with_nonconst_ref);


  InvokerStorage5(Sig f, const P1& p1, const P2& p2, const P3& p3,
      const P4& p4, const P5& p5)
      : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)),
          p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)),
          p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)),
          p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)),
          p5_(static_cast<typename ParamTraits<P5>::StorageType>(p5)) {
    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
  }

  virtual ~InvokerStorage5() {
    MaybeRefcount<IsMethod, P1>::Release(p1_);
  }

  Sig f_;
  typename ParamTraits<P1>::StorageType p1_;
  typename ParamTraits<P2>::StorageType p2_;
  typename ParamTraits<P3>::StorageType p3_;
  typename ParamTraits<P4>::StorageType p4_;
  typename ParamTraits<P5>::StorageType p5_;
};

template <typename Sig, typename P1, typename P2, typename P3, typename P4,
    typename P5, typename P6>
class InvokerStorage6 : public InvokerStorageBase {
 public:
  typedef InvokerStorage6 StorageType;
  typedef FunctionTraits<Sig> TargetTraits;
  typedef Invoker6<StorageType, typename TargetTraits::NormalizedSig> Invoker;
  typedef typename TargetTraits::IsMethod IsMethod;

  // For methods, we need to be careful for parameter 1.  We skip the
  // scoped_refptr check because the binder itself takes care of this. We also
  // disallow binding of an array as the method's target object.
  COMPILE_ASSERT(IsMethod::value ||
                 !internal::UnsafeBindtoRefCountedArg<P1>::value,
                 p1_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
                 first_bound_argument_to_method_cannot_be_array);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
                 p2_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
                 p3_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
                 p4_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P5>::value,
                 p5_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P6>::value,
                 p6_is_refcounted_type_and_needs_scoped_refptr);

  // Do not allow binding a non-const reference parameter. Non-const reference
  // parameters are disallowed by the Google style guide.  Also, binding a
  // non-const reference parameter can make for subtle bugs because the
  // invoked function will receive a reference to the stored copy of the
  // argument and not the original.
  COMPILE_ASSERT(
      !( is_non_const_reference<typename TargetTraits::B1>::value ||
          is_non_const_reference<typename TargetTraits::B2>::value ||
          is_non_const_reference<typename TargetTraits::B3>::value ||
          is_non_const_reference<typename TargetTraits::B4>::value ||
          is_non_const_reference<typename TargetTraits::B5>::value ||
          is_non_const_reference<typename TargetTraits::B6>::value ),
      do_not_bind_functions_with_nonconst_ref);


  InvokerStorage6(Sig f, const P1& p1, const P2& p2, const P3& p3,
      const P4& p4, const P5& p5, const P6& p6)
      : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)),
          p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)),
          p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)),
          p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)),
          p5_(static_cast<typename ParamTraits<P5>::StorageType>(p5)),
          p6_(static_cast<typename ParamTraits<P6>::StorageType>(p6)) {
    MaybeRefcount<IsMethod, P1>::AddRef(p1_);
  }

  virtual ~InvokerStorage6() {
    MaybeRefcount<IsMethod, P1>::Release(p1_);
  }

  Sig f_;
  typename ParamTraits<P1>::StorageType p1_;
  typename ParamTraits<P2>::StorageType p2_;
  typename ParamTraits<P3>::StorageType p3_;
  typename ParamTraits<P4>::StorageType p4_;
  typename ParamTraits<P5>::StorageType p5_;
  typename ParamTraits<P6>::StorageType p6_;
};

}  // namespace internal
}  // namespace base

#endif  // BASE_BIND_INTERNAL_H_