Update Bind to match its comments and always capture by value. Also update the generated count to 9 args.

The existing comment is wrong, and the test even ensures it: Bind will capture reference values by reference. That makes it hard to use with AsyncInvoker, because you can't safely Bind to a function that takes (const) reference params.

The new version of this code strips references in the bound object, so it captures by value, but can bind against functions that take const references, they'll just be references to the copy.

As the class comment implies, actual by-reference args should be passed as pointers or things that safely share (e.g. scoped_refptr) and not references directly. A new test case ensures the pointer reference works. The new code will also give a compiler error if you try to bind
to a non-const reference.

BUG=

Review URL: https://codereview.webrtc.org/1291543006

Cr-Commit-Position: refs/heads/master@{#10397}
diff --git a/webrtc/base/bind.h b/webrtc/base/bind.h
index 923fda2..b50afc2 100644
--- a/webrtc/base/bind.h
+++ b/webrtc/base/bind.h
@@ -65,6 +65,7 @@
 #define WEBRTC_BASE_BIND_H_
 
 #include "webrtc/base/scoped_ref_ptr.h"
+#include "webrtc/base/template_util.h"
 
 #define NONAME
 
@@ -128,18 +129,6 @@
                                        T*>::type type;
 };
 
-// RemoveScopedPtrRef will capture scoped_refptr by-value instead of
-// by-reference.
-template <class T> struct RemoveScopedPtrRef { typedef T type; };
-template <class T>
-struct RemoveScopedPtrRef<const scoped_refptr<T>&> {
-  typedef scoped_refptr<T> type;
-};
-template <class T>
-struct RemoveScopedPtrRef<scoped_refptr<T>&> {
-  typedef scoped_refptr<T> type;
-};
-
 }  // namespace detail
 
 template <class ObjectT, class MethodT, class R>
@@ -220,7 +209,7 @@
  private:
   MethodT method_;
   typename detail::PointerType<ObjectT>::type object_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
+  typename rtc::remove_reference<P1>::type p1_;
 };
 
 template <class FunctorT, class R,
@@ -234,7 +223,7 @@
     return functor_(p1_); }
  private:
   FunctorT functor_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
+  typename rtc::remove_reference<P1>::type p1_;
 };
 
 
@@ -303,8 +292,8 @@
  private:
   MethodT method_;
   typename detail::PointerType<ObjectT>::type object_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
 };
 
 template <class FunctorT, class R,
@@ -320,8 +309,8 @@
     return functor_(p1_, p2_); }
  private:
   FunctorT functor_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
 };
 
 
@@ -401,9 +390,9 @@
  private:
   MethodT method_;
   typename detail::PointerType<ObjectT>::type object_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
-  typename detail::RemoveScopedPtrRef<P3>::type p3_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
 };
 
 template <class FunctorT, class R,
@@ -421,9 +410,9 @@
     return functor_(p1_, p2_, p3_); }
  private:
   FunctorT functor_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
-  typename detail::RemoveScopedPtrRef<P3>::type p3_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
 };
 
 
@@ -514,10 +503,10 @@
  private:
   MethodT method_;
   typename detail::PointerType<ObjectT>::type object_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
-  typename detail::RemoveScopedPtrRef<P3>::type p3_;
-  typename detail::RemoveScopedPtrRef<P4>::type p4_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
 };
 
 template <class FunctorT, class R,
@@ -537,10 +526,10 @@
     return functor_(p1_, p2_, p3_, p4_); }
  private:
   FunctorT functor_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
-  typename detail::RemoveScopedPtrRef<P3>::type p3_;
-  typename detail::RemoveScopedPtrRef<P4>::type p4_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
 };
 
 
@@ -642,11 +631,11 @@
  private:
   MethodT method_;
   typename detail::PointerType<ObjectT>::type object_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
-  typename detail::RemoveScopedPtrRef<P3>::type p3_;
-  typename detail::RemoveScopedPtrRef<P4>::type p4_;
-  typename detail::RemoveScopedPtrRef<P5>::type p5_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
 };
 
 template <class FunctorT, class R,
@@ -668,11 +657,11 @@
     return functor_(p1_, p2_, p3_, p4_, p5_); }
  private:
   FunctorT functor_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
-  typename detail::RemoveScopedPtrRef<P3>::type p3_;
-  typename detail::RemoveScopedPtrRef<P4>::type p4_;
-  typename detail::RemoveScopedPtrRef<P5>::type p5_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
 };
 
 
@@ -785,12 +774,12 @@
  private:
   MethodT method_;
   typename detail::PointerType<ObjectT>::type object_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
-  typename detail::RemoveScopedPtrRef<P3>::type p3_;
-  typename detail::RemoveScopedPtrRef<P4>::type p4_;
-  typename detail::RemoveScopedPtrRef<P5>::type p5_;
-  typename detail::RemoveScopedPtrRef<P6>::type p6_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
+  typename rtc::remove_reference<P6>::type p6_;
 };
 
 template <class FunctorT, class R,
@@ -814,12 +803,12 @@
     return functor_(p1_, p2_, p3_, p4_, p5_, p6_); }
  private:
   FunctorT functor_;
-  typename detail::RemoveScopedPtrRef<P1>::type p1_;
-  typename detail::RemoveScopedPtrRef<P2>::type p2_;
-  typename detail::RemoveScopedPtrRef<P3>::type p3_;
-  typename detail::RemoveScopedPtrRef<P4>::type p4_;
-  typename detail::RemoveScopedPtrRef<P5>::type p5_;
-  typename detail::RemoveScopedPtrRef<P6>::type p6_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
+  typename rtc::remove_reference<P6>::type p6_;
 };
 
 
@@ -912,6 +901,640 @@
 
 #undef FP_T
 
+template <class ObjectT,
+          class MethodT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7>
+class MethodFunctor7 {
+ public:
+  MethodFunctor7(MethodT method,
+                 ObjectT* object,
+                 P1 p1,
+                 P2 p2,
+                 P3 p3,
+                 P4 p4,
+                 P5 p5,
+                 P6 p6,
+                 P7 p7)
+      : method_(method),
+        object_(object),
+        p1_(p1),
+        p2_(p2),
+        p3_(p3),
+        p4_(p4),
+        p5_(p5),
+        p6_(p6),
+        p7_(p7) {}
+  R operator()() const {
+    return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_);
+  }
+
+ private:
+  MethodT method_;
+  typename detail::PointerType<ObjectT>::type object_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
+  typename rtc::remove_reference<P6>::type p6_;
+  typename rtc::remove_reference<P7>::type p7_;
+};
+
+template <class FunctorT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7>
+class Functor7 {
+ public:
+  Functor7(const FunctorT& functor,
+           P1 p1,
+           P2 p2,
+           P3 p3,
+           P4 p4,
+           P5 p5,
+           P6 p6,
+           P7 p7)
+      : functor_(functor),
+        p1_(p1),
+        p2_(p2),
+        p3_(p3),
+        p4_(p4),
+        p5_(p5),
+        p6_(p6),
+        p7_(p7) {}
+  R operator()() const { return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_); }
+
+ private:
+  FunctorT functor_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
+  typename rtc::remove_reference<P6>::type p6_;
+  typename rtc::remove_reference<P7>::type p7_;
+};
+
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7)
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7>
+MethodFunctor7<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7> Bind(
+    FP_T(method),
+    ObjectT* object,
+    typename detail::identity<P1>::type p1,
+    typename detail::identity<P2>::type p2,
+    typename detail::identity<P3>::type p3,
+    typename detail::identity<P4>::type p4,
+    typename detail::identity<P5>::type p5,
+    typename detail::identity<P6>::type p6,
+    typename detail::identity<P7>::type p7) {
+  return MethodFunctor7<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7>(
+      method, object, p1, p2, p3, p4, p5, p6, p7);
+}
+
+#undef FP_T
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7) const
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7>
+MethodFunctor7<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7> Bind(
+    FP_T(method),
+    const ObjectT* object,
+    typename detail::identity<P1>::type p1,
+    typename detail::identity<P2>::type p2,
+    typename detail::identity<P3>::type p3,
+    typename detail::identity<P4>::type p4,
+    typename detail::identity<P5>::type p5,
+    typename detail::identity<P6>::type p6,
+    typename detail::identity<P7>::type p7) {
+  return MethodFunctor7<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6,
+                        P7>(method, object, p1, p2, p3, p4, p5, p6, p7);
+}
+
+#undef FP_T
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7)
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7>
+MethodFunctor7<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7> Bind(
+    FP_T(method),
+    const scoped_refptr<ObjectT>& object,
+    typename detail::identity<P1>::type p1,
+    typename detail::identity<P2>::type p2,
+    typename detail::identity<P3>::type p3,
+    typename detail::identity<P4>::type p4,
+    typename detail::identity<P5>::type p5,
+    typename detail::identity<P6>::type p6,
+    typename detail::identity<P7>::type p7) {
+  return MethodFunctor7<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7>(
+      method, object.get(), p1, p2, p3, p4, p5, p6, p7);
+}
+
+#undef FP_T
+#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7)
+
+template <class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7>
+Functor7<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7> Bind(
+    FP_T(function),
+    typename detail::identity<P1>::type p1,
+    typename detail::identity<P2>::type p2,
+    typename detail::identity<P3>::type p3,
+    typename detail::identity<P4>::type p4,
+    typename detail::identity<P5>::type p5,
+    typename detail::identity<P6>::type p6,
+    typename detail::identity<P7>::type p7) {
+  return Functor7<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7>(
+      function, p1, p2, p3, p4, p5, p6, p7);
+}
+
+#undef FP_T
+
+template <class ObjectT,
+          class MethodT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8>
+class MethodFunctor8 {
+ public:
+  MethodFunctor8(MethodT method,
+                 ObjectT* object,
+                 P1 p1,
+                 P2 p2,
+                 P3 p3,
+                 P4 p4,
+                 P5 p5,
+                 P6 p6,
+                 P7 p7,
+                 P8 p8)
+      : method_(method),
+        object_(object),
+        p1_(p1),
+        p2_(p2),
+        p3_(p3),
+        p4_(p4),
+        p5_(p5),
+        p6_(p6),
+        p7_(p7),
+        p8_(p8) {}
+  R operator()() const {
+    return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_);
+  }
+
+ private:
+  MethodT method_;
+  typename detail::PointerType<ObjectT>::type object_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
+  typename rtc::remove_reference<P6>::type p6_;
+  typename rtc::remove_reference<P7>::type p7_;
+  typename rtc::remove_reference<P8>::type p8_;
+};
+
+template <class FunctorT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8>
+class Functor8 {
+ public:
+  Functor8(const FunctorT& functor,
+           P1 p1,
+           P2 p2,
+           P3 p3,
+           P4 p4,
+           P5 p5,
+           P6 p6,
+           P7 p7,
+           P8 p8)
+      : functor_(functor),
+        p1_(p1),
+        p2_(p2),
+        p3_(p3),
+        p4_(p4),
+        p5_(p5),
+        p6_(p6),
+        p7_(p7),
+        p8_(p8) {}
+  R operator()() const {
+    return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_);
+  }
+
+ private:
+  FunctorT functor_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
+  typename rtc::remove_reference<P6>::type p6_;
+  typename rtc::remove_reference<P7>::type p7_;
+  typename rtc::remove_reference<P8>::type p8_;
+};
+
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8)
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8>
+MethodFunctor8<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8> Bind(
+    FP_T(method),
+    ObjectT* object,
+    typename detail::identity<P1>::type p1,
+    typename detail::identity<P2>::type p2,
+    typename detail::identity<P3>::type p3,
+    typename detail::identity<P4>::type p4,
+    typename detail::identity<P5>::type p5,
+    typename detail::identity<P6>::type p6,
+    typename detail::identity<P7>::type p7,
+    typename detail::identity<P8>::type p8) {
+  return MethodFunctor8<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7,
+                        P8>(method, object, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+#undef FP_T
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8) const
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8>
+MethodFunctor8<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8>
+Bind(FP_T(method),
+     const ObjectT* object,
+     typename detail::identity<P1>::type p1,
+     typename detail::identity<P2>::type p2,
+     typename detail::identity<P3>::type p3,
+     typename detail::identity<P4>::type p4,
+     typename detail::identity<P5>::type p5,
+     typename detail::identity<P6>::type p6,
+     typename detail::identity<P7>::type p7,
+     typename detail::identity<P8>::type p8) {
+  return MethodFunctor8<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6,
+                        P7, P8>(method, object, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+#undef FP_T
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8)
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8>
+MethodFunctor8<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8> Bind(
+    FP_T(method),
+    const scoped_refptr<ObjectT>& object,
+    typename detail::identity<P1>::type p1,
+    typename detail::identity<P2>::type p2,
+    typename detail::identity<P3>::type p3,
+    typename detail::identity<P4>::type p4,
+    typename detail::identity<P5>::type p5,
+    typename detail::identity<P6>::type p6,
+    typename detail::identity<P7>::type p7,
+    typename detail::identity<P8>::type p8) {
+  return MethodFunctor8<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7,
+                        P8>(method, object.get(), p1, p2, p3, p4, p5, p6, p7,
+                            p8);
+}
+
+#undef FP_T
+#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7, P8)
+
+template <class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8>
+Functor8<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8> Bind(
+    FP_T(function),
+    typename detail::identity<P1>::type p1,
+    typename detail::identity<P2>::type p2,
+    typename detail::identity<P3>::type p3,
+    typename detail::identity<P4>::type p4,
+    typename detail::identity<P5>::type p5,
+    typename detail::identity<P6>::type p6,
+    typename detail::identity<P7>::type p7,
+    typename detail::identity<P8>::type p8) {
+  return Functor8<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8>(
+      function, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+#undef FP_T
+
+template <class ObjectT,
+          class MethodT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8,
+          class P9>
+class MethodFunctor9 {
+ public:
+  MethodFunctor9(MethodT method,
+                 ObjectT* object,
+                 P1 p1,
+                 P2 p2,
+                 P3 p3,
+                 P4 p4,
+                 P5 p5,
+                 P6 p6,
+                 P7 p7,
+                 P8 p8,
+                 P9 p9)
+      : method_(method),
+        object_(object),
+        p1_(p1),
+        p2_(p2),
+        p3_(p3),
+        p4_(p4),
+        p5_(p5),
+        p6_(p6),
+        p7_(p7),
+        p8_(p8),
+        p9_(p9) {}
+  R operator()() const {
+    return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_, p9_);
+  }
+
+ private:
+  MethodT method_;
+  typename detail::PointerType<ObjectT>::type object_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
+  typename rtc::remove_reference<P6>::type p6_;
+  typename rtc::remove_reference<P7>::type p7_;
+  typename rtc::remove_reference<P8>::type p8_;
+  typename rtc::remove_reference<P9>::type p9_;
+};
+
+template <class FunctorT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8,
+          class P9>
+class Functor9 {
+ public:
+  Functor9(const FunctorT& functor,
+           P1 p1,
+           P2 p2,
+           P3 p3,
+           P4 p4,
+           P5 p5,
+           P6 p6,
+           P7 p7,
+           P8 p8,
+           P9 p9)
+      : functor_(functor),
+        p1_(p1),
+        p2_(p2),
+        p3_(p3),
+        p4_(p4),
+        p5_(p5),
+        p6_(p6),
+        p7_(p7),
+        p8_(p8),
+        p9_(p9) {}
+  R operator()() const {
+    return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_, p9_);
+  }
+
+ private:
+  FunctorT functor_;
+  typename rtc::remove_reference<P1>::type p1_;
+  typename rtc::remove_reference<P2>::type p2_;
+  typename rtc::remove_reference<P3>::type p3_;
+  typename rtc::remove_reference<P4>::type p4_;
+  typename rtc::remove_reference<P5>::type p5_;
+  typename rtc::remove_reference<P6>::type p6_;
+  typename rtc::remove_reference<P7>::type p7_;
+  typename rtc::remove_reference<P8>::type p8_;
+  typename rtc::remove_reference<P9>::type p9_;
+};
+
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9)
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8,
+          class P9>
+MethodFunctor9<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8, P9>
+Bind(FP_T(method),
+     ObjectT* object,
+     typename detail::identity<P1>::type p1,
+     typename detail::identity<P2>::type p2,
+     typename detail::identity<P3>::type p3,
+     typename detail::identity<P4>::type p4,
+     typename detail::identity<P5>::type p5,
+     typename detail::identity<P6>::type p6,
+     typename detail::identity<P7>::type p7,
+     typename detail::identity<P8>::type p8,
+     typename detail::identity<P9>::type p9) {
+  return MethodFunctor9<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7,
+                        P8, P9>(method, object, p1, p2, p3, p4, p5, p6, p7, p8,
+                                p9);
+}
+
+#undef FP_T
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8,
+          class P9>
+MethodFunctor9<const ObjectT,
+               FP_T(NONAME),
+               R,
+               P1,
+               P2,
+               P3,
+               P4,
+               P5,
+               P6,
+               P7,
+               P8,
+               P9>
+Bind(FP_T(method),
+     const ObjectT* object,
+     typename detail::identity<P1>::type p1,
+     typename detail::identity<P2>::type p2,
+     typename detail::identity<P3>::type p3,
+     typename detail::identity<P4>::type p4,
+     typename detail::identity<P5>::type p5,
+     typename detail::identity<P6>::type p6,
+     typename detail::identity<P7>::type p7,
+     typename detail::identity<P8>::type p8,
+     typename detail::identity<P9>::type p9) {
+  return MethodFunctor9<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6,
+                        P7, P8, P9>(method, object, p1, p2, p3, p4, p5, p6, p7,
+                                    p8, p9);
+}
+
+#undef FP_T
+#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9)
+
+template <class ObjectT,
+          class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8,
+          class P9>
+MethodFunctor9<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8, P9>
+Bind(FP_T(method),
+     const scoped_refptr<ObjectT>& object,
+     typename detail::identity<P1>::type p1,
+     typename detail::identity<P2>::type p2,
+     typename detail::identity<P3>::type p3,
+     typename detail::identity<P4>::type p4,
+     typename detail::identity<P5>::type p5,
+     typename detail::identity<P6>::type p6,
+     typename detail::identity<P7>::type p7,
+     typename detail::identity<P8>::type p8,
+     typename detail::identity<P9>::type p9) {
+  return MethodFunctor9<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7,
+                        P8, P9>(method, object.get(), p1, p2, p3, p4, p5, p6,
+                                p7, p8, p9);
+}
+
+#undef FP_T
+#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9)
+
+template <class R,
+          class P1,
+          class P2,
+          class P3,
+          class P4,
+          class P5,
+          class P6,
+          class P7,
+          class P8,
+          class P9>
+Functor9<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8, P9> Bind(
+    FP_T(function),
+    typename detail::identity<P1>::type p1,
+    typename detail::identity<P2>::type p2,
+    typename detail::identity<P3>::type p3,
+    typename detail::identity<P4>::type p4,
+    typename detail::identity<P5>::type p5,
+    typename detail::identity<P6>::type p6,
+    typename detail::identity<P7>::type p7,
+    typename detail::identity<P8>::type p8,
+    typename detail::identity<P9>::type p9) {
+  return Functor9<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8, P9>(
+      function, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+#undef FP_T
+
 }  // namespace rtc
 
 #undef NONAME
diff --git a/webrtc/base/bind.h.pump b/webrtc/base/bind.h.pump
index e1cea61..6fb8490 100644
--- a/webrtc/base/bind.h.pump
+++ b/webrtc/base/bind.h.pump
@@ -61,6 +61,7 @@
 #define WEBRTC_BASE_BIND_H_
 
 #include "webrtc/base/scoped_ref_ptr.h"
+#include "webrtc/base/template_util.h"
 
 #define NONAME
 
@@ -124,21 +125,9 @@
                                        T*>::type type;
 };
 
-// RemoveScopedPtrRef will capture scoped_refptr by-value instead of
-// by-reference.
-template <class T> struct RemoveScopedPtrRef { typedef T type; };
-template <class T>
-struct RemoveScopedPtrRef<const scoped_refptr<T>&> {
-  typedef scoped_refptr<T> type;
-};
-template <class T>
-struct RemoveScopedPtrRef<scoped_refptr<T>&> {
-  typedef scoped_refptr<T> type;
-};
-
 }  // namespace detail
 
-$var n = 6
+$var n = 9
 $range i 0..n
 $for i [[
 $range j 1..i
@@ -157,7 +146,7 @@
   MethodT method_;
   typename detail::PointerType<ObjectT>::type object_;$for j [[
 
-  typename detail::RemoveScopedPtrRef<P$j>::type p$(j)_;]]
+  typename rtc::remove_reference<P$j>::type p$(j)_;]]
 
 };
 
@@ -174,7 +163,7 @@
  private:
   FunctorT functor_;$for j [[
 
-  typename detail::RemoveScopedPtrRef<P$j>::type p$(j)_;]]
+  typename rtc::remove_reference<P$j>::type p$(j)_;]]
 
 };
 
diff --git a/webrtc/base/bind_unittest.cc b/webrtc/base/bind_unittest.cc
index fa47d27..be8d79c 100644
--- a/webrtc/base/bind_unittest.cc
+++ b/webrtc/base/bind_unittest.cc
@@ -25,7 +25,14 @@
   int NullaryConst() const { ++call_count; return 2; }
   void UnaryVoid(int dummy) { ++call_count; }
   template <class T> T Identity(T value) { ++call_count; return value; }
-  int UnaryByRef(int& value) const { ++call_count; return ++value; }  // NOLINT
+  int UnaryByPointer(int* value) const {
+    ++call_count;
+    return ++(*value);
+  }
+  int UnaryByRef(const int& value) const {
+    ++call_count;
+    return ++const_cast<int&>(value);
+  }
   int Multiply(int a, int b) const { ++call_count; return a * b; }
   void RefArgument(const scoped_refptr<LifeTimeCheck>& object) {
     EXPECT_TRUE(object.get() != nullptr);
@@ -64,26 +71,25 @@
 
 // Try to catch any problem with scoped_refptr type deduction in rtc::Bind at
 // compile time.
-static_assert(is_same<detail::RemoveScopedPtrRef<
-                          const scoped_refptr<RefCountInterface>&>::type,
-                      scoped_refptr<RefCountInterface>>::value,
-              "const scoped_refptr& should be captured by value");
+static_assert(
+    is_same<
+        rtc::remove_reference<const scoped_refptr<RefCountInterface>&>::type,
+        const scoped_refptr<RefCountInterface>>::value,
+    "const scoped_refptr& should be captured by value");
 
-static_assert(is_same<detail::RemoveScopedPtrRef<const scoped_refptr<F>&>::type,
-                      scoped_refptr<F>>::value,
+static_assert(is_same<rtc::remove_reference<const scoped_refptr<F>&>::type,
+                      const scoped_refptr<F>>::value,
               "const scoped_refptr& should be captured by value");
 
 static_assert(
-    is_same<detail::RemoveScopedPtrRef<const int&>::type, const int&>::value,
-    "const int& should be captured as const int&");
+    is_same<rtc::remove_reference<const int&>::type, const int>::value,
+    "const int& should be captured as const int");
 
-static_assert(
-    is_same<detail::RemoveScopedPtrRef<const F&>::type, const F&>::value,
-    "const F& should be captured as const F&");
+static_assert(is_same<rtc::remove_reference<const F&>::type, const F>::value,
+              "const F& should be captured as const F");
 
-static_assert(
-    is_same<detail::RemoveScopedPtrRef<F&>::type, F&>::value,
-    "F& should be captured as F&");
+static_assert(is_same<rtc::remove_reference<F&>::type, F>::value,
+              "F& should be captured as F");
 
 #define EXPECT_IS_CAPTURED_AS_PTR(T)                              \
   static_assert(is_same<detail::PointerType<T>::type, T*>::value, \
@@ -129,11 +135,20 @@
                                &object, string_value)());
   EXPECT_EQ(6, object.call_count);
   int value = 11;
-  EXPECT_EQ(12, Bind(&MethodBindTester::UnaryByRef, &object, value)());
+  // Bind binds by value, even if the method signature is by reference, so
+  // "reference" binds require pointers.
+  EXPECT_EQ(12, Bind(&MethodBindTester::UnaryByPointer, &object, &value)());
   EXPECT_EQ(12, value);
   EXPECT_EQ(7, object.call_count);
-  EXPECT_EQ(56, Bind(&MethodBindTester::Multiply, &object, 7, 8)());
+  // It's possible to bind to a function that takes a const reference, though
+  // the capture will be a copy. See UnaryByRef hackery above where it removes
+  // the const to make sure the underlying storage is, in fact, a copy.
+  EXPECT_EQ(13, Bind(&MethodBindTester::UnaryByRef, &object, value)());
+  // But the original value is unmodified.
+  EXPECT_EQ(12, value);
   EXPECT_EQ(8, object.call_count);
+  EXPECT_EQ(56, Bind(&MethodBindTester::Multiply, &object, 7, 8)());
+  EXPECT_EQ(9, object.call_count);
 }
 
 TEST(BindTest, BindToFunction) {
@@ -210,13 +225,14 @@
 
 }  // anonymous namespace
 
-// Test Bind with non-scoped_refptr<> reference argument.
+// Test Bind with non-scoped_refptr<> reference argument, which should be
+// modified to a non-reference capture.
 TEST(BindTest, RefArgument) {
   const int x = 42;
-  EXPECT_TRUE(Ref(x) == &x);
-  // Bind() should not make a copy of |x|, i.e. the pointers should be the same.
+  EXPECT_EQ(&x, Ref(x));
+  // Bind() should make a copy of |x|, i.e. the pointers should be different.
   auto functor = Bind(&Ref, x);
-  EXPECT_TRUE(functor() == &x);
+  EXPECT_NE(&x, functor());
 }
 
 }  // namespace rtc
diff --git a/webrtc/base/template_util.h b/webrtc/base/template_util.h
index 86e541d..31464cf 100644
--- a/webrtc/base/template_util.h
+++ b/webrtc/base/template_util.h
@@ -48,6 +48,19 @@
 template <class T> struct is_void : false_type {};
 template <> struct is_void<void> : true_type {};
 
+template <class T>
+struct remove_reference {
+  typedef T type;
+};
+template <class T>
+struct remove_reference<T&> {
+  typedef T type;
+};
+template <class T>
+struct remove_reference<T&&> {
+  typedef T type;
+};
+
 namespace internal {
 
 // Types YesType and NoType are guaranteed such that sizeof(YesType) <