From 5d9b92b53daf4db78fd090be4e210e07f786120d Mon Sep 17 00:00:00 2001 From: noahric Date: Sat, 24 Oct 2015 11:14:46 -0700 Subject: [PATCH] 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} --- talk/media/webrtc/webrtcvideocapturer.cc | 12 +- talk/media/webrtc/webrtcvideocapturer.h | 2 +- webrtc/base/bind.h | 731 +++++++++++++++++++++-- webrtc/base/bind.h.pump | 19 +- webrtc/base/bind_unittest.cc | 58 +- webrtc/base/template_util.h | 13 + webrtc/p2p/base/transport.cc | 2 - 7 files changed, 739 insertions(+), 98 deletions(-) diff --git a/talk/media/webrtc/webrtcvideocapturer.cc b/talk/media/webrtc/webrtcvideocapturer.cc index 9f1f32af4f..5ba5fb9ba2 100644 --- a/talk/media/webrtc/webrtcvideocapturer.cc +++ b/talk/media/webrtc/webrtcvideocapturer.cc @@ -382,10 +382,12 @@ void WebRtcVideoCapturer::OnIncomingCapturedFrame( // consistency with other capturers such as in Chrome, we need to do a // thread hop. // Note that Stop() can cause the async invoke call to be cancelled. - async_invoker_->AsyncInvoke(start_thread_, - // Note that this results in a shallow copying of the frame. - rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread, - this, sample)); + async_invoker_->AsyncInvoke( + start_thread_, + // Note that Bind captures by value, so there's an intermediate copy + // of sample. + rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread, this, + sample)); } } @@ -395,7 +397,7 @@ void WebRtcVideoCapturer::OnCaptureDelayChanged(const int32_t id, } void WebRtcVideoCapturer::SignalFrameCapturedOnStartThread( - const webrtc::VideoFrame frame) { + const webrtc::VideoFrame& frame) { // This can only happen between Start() and Stop(). RTC_DCHECK(start_thread_); RTC_DCHECK(start_thread_->IsCurrent()); diff --git a/talk/media/webrtc/webrtcvideocapturer.h b/talk/media/webrtc/webrtcvideocapturer.h index 66991e097f..0a99884fe1 100644 --- a/talk/media/webrtc/webrtcvideocapturer.h +++ b/talk/media/webrtc/webrtcvideocapturer.h @@ -92,7 +92,7 @@ class WebRtcVideoCapturer : public VideoCapturer, // directly from OnIncomingCapturedFrame. // TODO(tommi): Remove this workaround when we've updated the WebRTC capturers // to follow the same contract. - void SignalFrameCapturedOnStartThread(const webrtc::VideoFrame frame); + void SignalFrameCapturedOnStartThread(const webrtc::VideoFrame& frame); rtc::scoped_ptr factory_; webrtc::VideoCaptureModule* module_; diff --git a/webrtc/base/bind.h b/webrtc/base/bind.h index 923fda21b5..b50afc21ac 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 @@ struct PointerType { T*>::type type; }; -// RemoveScopedPtrRef will capture scoped_refptr by-value instead of -// by-reference. -template struct RemoveScopedPtrRef { typedef T type; }; -template -struct RemoveScopedPtrRef&> { - typedef scoped_refptr type; -}; -template -struct RemoveScopedPtrRef&> { - typedef scoped_refptr type; -}; - } // namespace detail template @@ -220,7 +209,7 @@ class MethodFunctor1 { private: MethodT method_; typename detail::PointerType::type object_; - typename detail::RemoveScopedPtrRef::type p1_; + typename rtc::remove_reference::type p1_; }; template ::type p1_; + typename rtc::remove_reference::type p1_; }; @@ -303,8 +292,8 @@ class MethodFunctor2 { private: MethodT method_; typename detail::PointerType::type object_; - typename detail::RemoveScopedPtrRef::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; }; template ::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; }; @@ -401,9 +390,9 @@ class MethodFunctor3 { private: MethodT method_; typename detail::PointerType::type object_; - typename detail::RemoveScopedPtrRef::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; - typename detail::RemoveScopedPtrRef::type p3_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; }; template ::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; - typename detail::RemoveScopedPtrRef::type p3_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; }; @@ -514,10 +503,10 @@ class MethodFunctor4 { private: MethodT method_; typename detail::PointerType::type object_; - typename detail::RemoveScopedPtrRef::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; - typename detail::RemoveScopedPtrRef::type p3_; - typename detail::RemoveScopedPtrRef::type p4_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; }; template ::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; - typename detail::RemoveScopedPtrRef::type p3_; - typename detail::RemoveScopedPtrRef::type p4_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; }; @@ -642,11 +631,11 @@ class MethodFunctor5 { private: MethodT method_; typename detail::PointerType::type object_; - typename detail::RemoveScopedPtrRef::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; - typename detail::RemoveScopedPtrRef::type p3_; - typename detail::RemoveScopedPtrRef::type p4_; - typename detail::RemoveScopedPtrRef::type p5_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; }; template ::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; - typename detail::RemoveScopedPtrRef::type p3_; - typename detail::RemoveScopedPtrRef::type p4_; - typename detail::RemoveScopedPtrRef::type p5_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; }; @@ -785,12 +774,12 @@ class MethodFunctor6 { private: MethodT method_; typename detail::PointerType::type object_; - typename detail::RemoveScopedPtrRef::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; - typename detail::RemoveScopedPtrRef::type p3_; - typename detail::RemoveScopedPtrRef::type p4_; - typename detail::RemoveScopedPtrRef::type p5_; - typename detail::RemoveScopedPtrRef::type p6_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; + typename rtc::remove_reference::type p6_; }; template ::type p1_; - typename detail::RemoveScopedPtrRef::type p2_; - typename detail::RemoveScopedPtrRef::type p3_; - typename detail::RemoveScopedPtrRef::type p4_; - typename detail::RemoveScopedPtrRef::type p5_; - typename detail::RemoveScopedPtrRef::type p6_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; + typename rtc::remove_reference::type p6_; }; @@ -912,6 +901,640 @@ Bind(FP_T(function), #undef FP_T +template +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::type object_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; + typename rtc::remove_reference::type p6_; + typename rtc::remove_reference::type p7_; +}; + +template +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::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; + typename rtc::remove_reference::type p6_; + typename rtc::remove_reference::type p7_; +}; + +#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7) + +template +MethodFunctor7 Bind( + FP_T(method), + ObjectT* object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7) { + return MethodFunctor7( + 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 +MethodFunctor7 Bind( + FP_T(method), + const ObjectT* object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7) { + return MethodFunctor7(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 +MethodFunctor7 Bind( + FP_T(method), + const scoped_refptr& object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7) { + return MethodFunctor7( + 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 +Functor7 Bind( + FP_T(function), + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7) { + return Functor7( + function, p1, p2, p3, p4, p5, p6, p7); +} + +#undef FP_T + +template +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::type object_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; + typename rtc::remove_reference::type p6_; + typename rtc::remove_reference::type p7_; + typename rtc::remove_reference::type p8_; +}; + +template +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::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; + typename rtc::remove_reference::type p6_; + typename rtc::remove_reference::type p7_; + typename rtc::remove_reference::type p8_; +}; + +#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8) + +template +MethodFunctor8 Bind( + FP_T(method), + ObjectT* object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7, + typename detail::identity::type p8) { + return MethodFunctor8(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 +MethodFunctor8 +Bind(FP_T(method), + const ObjectT* object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7, + typename detail::identity::type p8) { + return MethodFunctor8(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 +MethodFunctor8 Bind( + FP_T(method), + const scoped_refptr& object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7, + typename detail::identity::type p8) { + return MethodFunctor8(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 +Functor8 Bind( + FP_T(function), + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7, + typename detail::identity::type p8) { + return Functor8( + function, p1, p2, p3, p4, p5, p6, p7, p8); +} + +#undef FP_T + +template +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::type object_; + typename rtc::remove_reference::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; + typename rtc::remove_reference::type p6_; + typename rtc::remove_reference::type p7_; + typename rtc::remove_reference::type p8_; + typename rtc::remove_reference::type p9_; +}; + +template +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::type p1_; + typename rtc::remove_reference::type p2_; + typename rtc::remove_reference::type p3_; + typename rtc::remove_reference::type p4_; + typename rtc::remove_reference::type p5_; + typename rtc::remove_reference::type p6_; + typename rtc::remove_reference::type p7_; + typename rtc::remove_reference::type p8_; + typename rtc::remove_reference::type p9_; +}; + +#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9) + +template +MethodFunctor9 +Bind(FP_T(method), + ObjectT* object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7, + typename detail::identity::type p8, + typename detail::identity::type p9) { + return MethodFunctor9(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 +MethodFunctor9 +Bind(FP_T(method), + const ObjectT* object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7, + typename detail::identity::type p8, + typename detail::identity::type p9) { + return MethodFunctor9(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 +MethodFunctor9 +Bind(FP_T(method), + const scoped_refptr& object, + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7, + typename detail::identity::type p8, + typename detail::identity::type p9) { + return MethodFunctor9(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 +Functor9 Bind( + FP_T(function), + typename detail::identity::type p1, + typename detail::identity::type p2, + typename detail::identity::type p3, + typename detail::identity::type p4, + typename detail::identity::type p5, + typename detail::identity::type p6, + typename detail::identity::type p7, + typename detail::identity::type p8, + typename detail::identity::type p9) { + return Functor9( + 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 e1cea61fc2..6fb849095d 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 @@ struct PointerType { T*>::type type; }; -// RemoveScopedPtrRef will capture scoped_refptr by-value instead of -// by-reference. -template struct RemoveScopedPtrRef { typedef T type; }; -template -struct RemoveScopedPtrRef&> { - typedef scoped_refptr type; -}; -template -struct RemoveScopedPtrRef&> { - typedef scoped_refptr type; -}; - } // namespace detail -$var n = 6 +$var n = 9 $range i 0..n $for i [[ $range j 1..i @@ -157,7 +146,7 @@ class MethodFunctor$i { MethodT method_; typename detail::PointerType::type object_;$for j [[ - typename detail::RemoveScopedPtrRef::type p$(j)_;]] + typename rtc::remove_reference::type p$(j)_;]] }; @@ -174,7 +163,7 @@ Functor$i(const FunctorT& functor$for j [[, P$j p$j]]) private: FunctorT functor_;$for j [[ - typename detail::RemoveScopedPtrRef::type p$(j)_;]] + typename rtc::remove_reference::type p$(j)_;]] }; diff --git a/webrtc/base/bind_unittest.cc b/webrtc/base/bind_unittest.cc index fa47d279f5..be8d79cb6a 100644 --- a/webrtc/base/bind_unittest.cc +++ b/webrtc/base/bind_unittest.cc @@ -25,7 +25,14 @@ struct MethodBindTester { int NullaryConst() const { ++call_count; return 2; } void UnaryVoid(int dummy) { ++call_count; } template 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(value); + } int Multiply(int a, int b) const { ++call_count; return a * b; } void RefArgument(const scoped_refptr& object) { EXPECT_TRUE(object.get() != nullptr); @@ -64,26 +71,25 @@ int Multiply(int a, int b) { return a * b; } // Try to catch any problem with scoped_refptr type deduction in rtc::Bind at // compile time. -static_assert(is_same&>::type, - scoped_refptr>::value, - "const scoped_refptr& should be captured by value"); +static_assert( + is_same< + rtc::remove_reference&>::type, + const scoped_refptr>::value, + "const scoped_refptr& should be captured by value"); -static_assert(is_same&>::type, - scoped_refptr>::value, +static_assert(is_same&>::type, + const scoped_refptr>::value, "const scoped_refptr& should be captured by value"); static_assert( - is_same::type, const int&>::value, - "const int& should be captured as const int&"); + is_same::type, const int>::value, + "const int& should be captured as const int"); -static_assert( - is_same::type, const F&>::value, - "const F& should be captured as const F&"); +static_assert(is_same::type, const F>::value, + "const F& should be captured as const F"); -static_assert( - is_same::type, F&>::value, - "F& should be captured as F&"); +static_assert(is_same::type, F>::value, + "F& should be captured as F"); #define EXPECT_IS_CAPTURED_AS_PTR(T) \ static_assert(is_same::type, T*>::value, \ @@ -129,11 +135,20 @@ TEST(BindTest, BindToMethod) { &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 @@ const int* Ref(const int& a) { return &a; } } // 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 86e541d8cf..31464cf35d 100644 --- a/webrtc/base/template_util.h +++ b/webrtc/base/template_util.h @@ -48,6 +48,19 @@ template struct is_non_const_reference : false_type {}; template struct is_void : false_type {}; template <> struct is_void : true_type {}; +template +struct remove_reference { + typedef T type; +}; +template +struct remove_reference { + typedef T type; +}; +template +struct remove_reference { + typedef T type; +}; + namespace internal { // Types YesType and NoType are guaranteed such that sizeof(YesType) < diff --git a/webrtc/p2p/base/transport.cc b/webrtc/p2p/base/transport.cc index 58817df79d..2328e4587c 100644 --- a/webrtc/p2p/base/transport.cc +++ b/webrtc/p2p/base/transport.cc @@ -22,8 +22,6 @@ namespace cricket { -using rtc::Bind; - static bool VerifyIceParams(const TransportDescription& desc) { // For legacy protocols. if (desc.ice_ufrag.empty() && desc.ice_pwd.empty())