Fix dynamic MPMCQueue tryObtainPromisedPushTicket() to prevent tryWriteUntil() and...
[folly.git] / folly / Utility.h
1 /*
2  * Copyright 2017 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 <type_traits>
20 #include <utility>
21
22 namespace folly {
23
24 /**
25  *  copy
26  *
27  *  Usable when you have a function with two overloads:
28  *
29  *      class MyData;
30  *      void something(MyData&&);
31  *      void something(const MyData&);
32  *
33  *  Where the purpose is to make copies and moves explicit without having to
34  *  spell out the full type names - in this case, for copies, to invoke copy
35  *  constructors.
36  *
37  *  When the caller wants to pass a copy of an lvalue, the caller may:
38  *
39  *      void foo() {
40  *        MyData data;
41  *        something(folly::copy(data)); // explicit copy
42  *        something(std::move(data)); // explicit move
43  *        something(data); // const& - neither move nor copy
44  *      }
45  *
46  *  Note: If passed an rvalue, invokes the move-ctor, not the copy-ctor. This
47  *  can be used to to force a move, where just using std::move would not:
48  *
49  *      std::copy(std::move(data)); // force-move, not just a cast to &&
50  *
51  *  Note: The following text appears in the standard:
52  *
53  *  > In several places in this Clause the operation //DECAY_COPY(x)// is used.
54  *  > All such uses mean call the function `decay_copy(x)` and use the result,
55  *  > where `decay_copy` is defined as follows:
56  *  >
57  *  >   template <class T> decay_t<T> decay_copy(T&& v)
58  *  >     { return std::forward<T>(v); }
59  *  >
60  *  > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
61  *  >   30.2.6 `decay_copy` [thread.decaycopy].
62  *
63  *  We mimic it, with a `noexcept` specifier for good measure.
64  */
65
66 template <typename T>
67 constexpr typename std::decay<T>::type copy(T&& value) noexcept(
68     noexcept(typename std::decay<T>::type(std::forward<T>(value)))) {
69   return std::forward<T>(value);
70 }
71
72 /**
73  * A simple helper for getting a constant reference to an object.
74  *
75  * Example:
76  *
77  *   std::vector<int> v{1,2,3};
78  *   // The following two lines are equivalent:
79  *   auto a = const_cast<const std::vector<int>&>(v).begin();
80  *   auto b = folly::as_const(v).begin();
81  *
82  * Like C++17's std::as_const. See http://wg21.link/p0007
83  */
84 #if __cpp_lib_as_const || _MSC_VER
85
86 /* using override */ using std::as_const
87
88 #else
89
90 template <class T>
91 constexpr T const& as_const(T& t) noexcept {
92   return t;
93 }
94
95 template <class T>
96 void as_const(T const&&) = delete;
97
98 #endif
99 }