move MoveWrapper to folly
authorDave Watson <davejwatson@fb.com>
Fri, 25 Oct 2013 19:35:25 +0000 (12:35 -0700)
committerSara Golemon <sgolemon@fb.com>
Wed, 6 Nov 2013 01:35:11 +0000 (17:35 -0800)
Summary: Add MoveWrapper to folly.

@override-unit-failures

Test Plan: arc unit

Reviewed By: hans@fb.com

FB internal diff: D1030005

folly/MoveWrapper.h [new file with mode: 0644]
folly/test/MoveWrapperTest.cpp [new file with mode: 0644]

diff --git a/folly/MoveWrapper.h b/folly/MoveWrapper.h
new file mode 100644 (file)
index 0000000..bbdca22
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace folly {
+
+/** C++11 closures don't support move-in capture. Nor does std::bind.
+    facepalm.
+
+    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3610.html
+
+    "[...] a work-around that should make people's stomach crawl:
+    write a wrapper that performs move-on-copy, much like the deprecated
+    auto_ptr"
+
+    Unlike auto_ptr, this doesn't require a heap allocation.
+    */
+template <class T>
+class MoveWrapper {
+ public:
+  /** If value can be default-constructed, why not?
+      Then we don't have to move it in */
+  MoveWrapper() = default;
+
+  /// Move a value in.
+  explicit
+  MoveWrapper(T&& t) : value(std::move(t)) {}
+
+  /// copy is move
+  MoveWrapper(MoveWrapper& other) : value(std::move(other.value)) {}
+
+  /// move is also move
+  MoveWrapper(MoveWrapper&& other) : value(std::move(other.value)) {}
+
+  const T& operator*() const { return value; }
+        T& operator*()       { return value; }
+
+  const T* operator->() const { return &value; }
+        T* operator->()       { return &value; }
+
+  // If you want these you're probably doing it wrong, though they'd be
+  // easy enough to implement
+  MoveWrapper& operator=(MoveWrapper const&) = delete;
+  MoveWrapper& operator=(MoveWrapper&&) = delete;
+
+ private:
+  T value;
+};
+
+template <class T>
+MoveWrapper<T> makeMoveWrapper(T&& t) {
+    return MoveWrapper<T>(std::forward<T>(t));
+}
+
+} // namespace
diff --git a/folly/test/MoveWrapperTest.cpp b/folly/test/MoveWrapperTest.cpp
new file mode 100644 (file)
index 0000000..4eb4bcb
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "folly/MoveWrapper.h"
+#include <memory>
+
+namespace folly {
+
+TEST(makeMoveWrapper, Empty) {
+  // checks for crashes
+  auto p = makeMoveWrapper(std::unique_ptr<int>());
+}
+
+TEST(makeMoveWrapper, NonEmpty) {
+  auto u = std::unique_ptr<int>(new int(5));
+  EXPECT_EQ(*u, 5);
+  auto p = makeMoveWrapper(std::move(u));
+  EXPECT_TRUE(!u);
+  EXPECT_EQ(**p, 5);
+}
+
+} // namespace