Fixes RCU test cases error (loads should use Consume ordering)
[folly.git] / folly / MoveWrapper.h
1 /*
2  * Copyright 2013-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <memory>
20
21 namespace folly {
22
23 /** C++11 closures don't support move-in capture. Nor does std::bind.
24     facepalm.
25
26     http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3610.html
27
28     "[...] a work-around that should make people's stomach crawl:
29     write a wrapper that performs move-on-copy, much like the deprecated
30     auto_ptr"
31
32     Unlike auto_ptr, this doesn't require a heap allocation.
33     */
34 template <class T>
35 class MoveWrapper {
36  public:
37   /** If value can be default-constructed, why not?
38       Then we don't have to move it in */
39   MoveWrapper() = default;
40
41   /// Move a value in.
42   explicit
43   MoveWrapper(T&& t) : value(std::move(t)) {}
44
45   /// copy is move
46   MoveWrapper(const MoveWrapper& other) : value(std::move(other.value)) {}
47
48   /// move is also move
49   MoveWrapper(MoveWrapper&& other) : value(std::move(other.value)) {}
50
51   const T& operator*() const { return value; }
52         T& operator*()       { return value; }
53
54   const T* operator->() const { return &value; }
55         T* operator->()       { return &value; }
56
57   /// move the value out (sugar for std::move(*moveWrapper))
58   T&& move() { return std::move(value); }
59
60   // If you want these you're probably doing it wrong, though they'd be
61   // easy enough to implement
62   MoveWrapper& operator=(MoveWrapper const&) = delete;
63   MoveWrapper& operator=(MoveWrapper&&) = delete;
64
65  private:
66   mutable T value;
67 };
68
69 /// Make a MoveWrapper from the argument. Because the name "makeMoveWrapper"
70 /// is already quite transparent in its intent, this will work for lvalues as
71 /// if you had wrapped them in std::move.
72 template <class T, class T0 = typename std::remove_reference<T>::type>
73 MoveWrapper<T0> makeMoveWrapper(T&& t) {
74   return MoveWrapper<T0>(std::forward<T0>(t));
75 }
76
77 } // namespace folly