Making 'just()' reference arguments like 'from()'
authorTom Jackson <tjackson@fb.com>
Thu, 29 Jan 2015 18:56:30 +0000 (10:56 -0800)
committerwoo <woo@fb.com>
Mon, 2 Feb 2015 21:14:23 +0000 (13:14 -0800)
Summary: That is, for all inputs except r-values.

Test Plan:
Run tests
@override-test-failures

Reviewed By: ajaymenon@fb.com

Subscribers: trunkagent, folly-diffs@

FB internal diff: D1807789

Signature: t1:1807789:1422410689:442d50ab17f8e3b08e34f33318a4dc7f23b4c6cc

folly/gen/Base-inl.h
folly/gen/Base.h
folly/gen/Parallel-inl.h
folly/gen/test/BaseTest.cpp

index 083cf979b0f030051e75a2e72e49893bb0bfab26..e04c246cfe40501cbcb74e4910fdabe74798f7ae 100644 (file)
@@ -328,13 +328,32 @@ class Empty : public GenImpl<Value, Empty<Value>> {
   void foreach(Body&&) const {}
 };
 
-template<class Value>
-class Just : public GenImpl<const Value&, Just<Value>> {
+template <class Value>
+class SingleReference : public GenImpl<Value&, SingleReference<Value>> {
+  static_assert(!std::is_reference<Value>::value,
+                "SingleReference requires non-ref types");
+  Value* ptr_;
+ public:
+  explicit SingleReference(Value* ptr) : ptr_(ptr){}
+
+  template <class Handler>
+  bool apply(Handler&& handler) const {
+    return handler(*ptr_);
+  }
+
+  template <class Body>
+  void foreach(Body&& body) const {
+    body(*ptr_);
+  }
+};
+
+template <class Value>
+class SingleCopy : public GenImpl<const Value&, SingleCopy<Value>> {
   static_assert(!std::is_reference<Value>::value,
-                "Just requires non-ref types");
-  const Value value_;
+                "SingleCopy requires non-ref types");
+  Value value_;
  public:
-  explicit Just(Value value) : value_(std::forward<Value>(value)) {}
+  explicit SingleCopy(Value value) : value_(std::forward<Value>(value)) {}
 
   template <class Handler>
   bool apply(Handler&& handler) const {
index 12d917edac6a3bed58f9907f2f056fdc4fd39d11..bf9b4b535367446ae5f5943d4054de4ca9a62f3f 100644 (file)
@@ -297,7 +297,10 @@ template<class Value>
 class Empty;
 
 template<class Value>
-class Just;
+class SingleReference;
+
+template<class Value>
+class SingleCopy;
 
 /*
  * Operators
@@ -482,14 +485,25 @@ Yield generator(Source&& source) {
 /*
  * empty() - for producing empty sequences.
  */
-template<class Value>
+template <class Value>
 detail::Empty<Value> empty() {
   return {};
 }
 
-template<class Value>
-detail::Just<Value> just(Value value) {
-  return detail::Just<Value>(std::move(value));
+template <class Value, class Just = detail::SingleReference<Value>>
+Just just(Value& value) {
+  return Just(&value);
+}
+
+template <class Value, class Just = detail::SingleReference<const Value>>
+Just just(const Value& value) {
+  return Just(&value);
+}
+
+template <class Value,
+          class Just = detail::SingleCopy<typename std::decay<Value>::type>>
+Just just(Value&& value) {
+  return Just(std::move(value));
 }
 
 /*
index 666acb16d1e356c6a192ce177bb2af899cb6d931..06f1af012edc4dcadee6f49e082161221b34be76 100644 (file)
@@ -136,7 +136,7 @@ class Sub : public Operator<Sub<Sink>> {
             class Source,
             class Result =
                 decltype(std::declval<Sink>().compose(std::declval<Source>())),
-            class Just = Just<typename std::decay<Result>::type>>
+            class Just = SingleCopy<typename std::decay<Result>::type>>
   Just compose(const GenImpl<Value, Source>& source) const {
     return Just(source | sink_);
   }
index 2b99f15704c293f07b9f5b30fca30f2a919804cc..d403d99d4aeab579c2fa0d6cfb8f91c042da301b 100644 (file)
@@ -1073,6 +1073,31 @@ TEST(Gen, BatchMove) {
   EXPECT_EQ(expected, actual);
 }
 
+TEST(Gen, Just) {
+  {
+    int x = 3;
+    auto j = just(x);
+    EXPECT_EQ(&x, j | mapped([](const int& v) { return &v; }) | first);
+    x = 4;
+    EXPECT_EQ(4, j | first);
+  }
+  {
+    int x = 3;
+    const int& cx = x;
+    auto j = just(cx);
+    EXPECT_EQ(&x, j | mapped([](const int& v) { return &v; }) | first);
+    x = 5;
+    EXPECT_EQ(5, j | first);
+  }
+  {
+    int x = 3;
+    auto j = just(std::move(x));
+    EXPECT_NE(&x, j | mapped([](const int& v) { return &v; }) | first);
+    x = 5;
+    EXPECT_EQ(3, j | first);
+  }
+}
+
 int main(int argc, char *argv[]) {
   testing::InitGoogleTest(&argc, argv);
   gflags::ParseCommandLineFlags(&argc, &argv, true);