support for move-only types
authorJames Sedgwick <jsedgwick@fb.com>
Wed, 15 Oct 2014 22:58:44 +0000 (15:58 -0700)
committerdcsommer <dcsommer@fb.com>
Fri, 17 Oct 2014 18:44:01 +0000 (11:44 -0700)
Summary: universal references and perfect forwarding to the rescue

Test Plan: added demonstrative unit tests

Reviewed By: hans@fb.com

Subscribers: trunkagent, fugalh, njormrod, bmatheny

FB internal diff: D1592032

Tasks: 5283342

folly/experimental/wangle/rx/Observer.h
folly/experimental/wangle/rx/Subject.h
folly/experimental/wangle/rx/test/RxTest.cpp

index e2a7486b715c44c51ff11e589c1fbb197fc13fcd..cfe49dd9862ebfe00af1d57e84a612603a272377 100644 (file)
@@ -31,7 +31,7 @@ template <class T> class FunctionObserver;
 template <class T>
 struct Observer {
   // These are what it means to be an Observer.
-  virtual void onNext(T) = 0;
+  virtual void onNext(const T&) = 0;
   virtual void onError(Error) = 0;
   virtual void onCompleted() = 0;
 
@@ -79,7 +79,7 @@ struct Observer {
 /// make one of these directly - instead use the Observer::create() methods.
 template <class T>
 struct FunctionObserver : public Observer<T> {
-  typedef std::function<void(T)> OnNext;
+  typedef std::function<void(const T&)> OnNext;
   typedef std::function<void(Error)> OnError;
   typedef std::function<void()> OnCompleted;
 
@@ -92,7 +92,7 @@ struct FunctionObserver : public Observer<T> {
       onCompleted_(std::forward<C>(c))
   {}
 
-  void onNext(T val) override {
+  void onNext(const T& val) override {
     if (onNext_) onNext_(val);
   }
 
index 67857205c6c6c683e5cced378fbde858842bff7c..0cb357fe9cbdd56df71ed73acea74b45a5dfb63b 100644 (file)
@@ -27,7 +27,7 @@ namespace folly { namespace wangle {
 template <class T>
 struct Subject : public Observable<T>, public Observer<T> {
   typedef typename Observable<T>::ObserversGuard ObserversGuard;
-  void onNext(T val) override {
+  void onNext(const T& val) override {
     ObserversGuard guard(this);
     for (auto& kv : Observable<T>::getObservers()) {
       kv.second->onNext(val);
index a62d11ce476f043002f18ff40530f35756739385..ab44657a2313b9c7cc51df898750d1adbaef0573 100644 (file)
@@ -105,3 +105,43 @@ TEST(RxTest, SubscribeUnsubscribeDuringCallback) {
   EXPECT_EQ(2, outerCount);
   EXPECT_EQ(0, innerCount);
 }
+
+// Move only type
+typedef std::unique_ptr<int> MO;
+static MO makeMO() { return folly::make_unique<int>(1); }
+template <typename T>
+static ObserverPtr<T> makeMOObserver() {
+  return Observer<T>::create([](const T& mo) {
+    EXPECT_EQ(1, *mo);
+  });
+}
+
+TEST(RxTest, MoveOnlyRvalue) {
+  Subject<MO> subject;
+  auto s1 = subject.subscribe(makeMOObserver<MO>());
+  auto s2 = subject.subscribe(makeMOObserver<MO>());
+  auto mo = makeMO();
+  // Can't bind lvalues to rvalue references
+  // subject.onNext(mo);
+  subject.onNext(std::move(mo));
+  subject.onNext(makeMO());
+}
+
+// Copy only type
+struct CO {
+  CO() = default;
+  CO(const CO&) = default;
+  CO(CO&&) = delete;
+};
+
+template <typename T>
+static ObserverPtr<T> makeCOObserver() {
+  return Observer<T>::create([](const T& mo) {});
+}
+
+TEST(RxTest, CopyOnly) {
+  Subject<CO> subject;
+  auto s1 = subject.subscribe(makeCOObserver<CO>());
+  CO co;
+  subject.onNext(co);
+}