dbe552f02aac940b79c34b2708ae18e4c4201d75
[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 <cstdint>
20 #include <type_traits>
21 #include <utility>
22
23 namespace folly {
24
25 /**
26  *  copy
27  *
28  *  Usable when you have a function with two overloads:
29  *
30  *      class MyData;
31  *      void something(MyData&&);
32  *      void something(const MyData&);
33  *
34  *  Where the purpose is to make copies and moves explicit without having to
35  *  spell out the full type names - in this case, for copies, to invoke copy
36  *  constructors.
37  *
38  *  When the caller wants to pass a copy of an lvalue, the caller may:
39  *
40  *      void foo() {
41  *        MyData data;
42  *        something(folly::copy(data)); // explicit copy
43  *        something(std::move(data)); // explicit move
44  *        something(data); // const& - neither move nor copy
45  *      }
46  *
47  *  Note: If passed an rvalue, invokes the move-ctor, not the copy-ctor. This
48  *  can be used to to force a move, where just using std::move would not:
49  *
50  *      std::copy(std::move(data)); // force-move, not just a cast to &&
51  *
52  *  Note: The following text appears in the standard:
53  *
54  *  > In several places in this Clause the operation //DECAY_COPY(x)// is used.
55  *  > All such uses mean call the function `decay_copy(x)` and use the result,
56  *  > where `decay_copy` is defined as follows:
57  *  >
58  *  >   template <class T> decay_t<T> decay_copy(T&& v)
59  *  >     { return std::forward<T>(v); }
60  *  >
61  *  > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
62  *  >   30.2.6 `decay_copy` [thread.decaycopy].
63  *
64  *  We mimic it, with a `noexcept` specifier for good measure.
65  */
66
67 template <typename T>
68 constexpr typename std::decay<T>::type copy(T&& value) noexcept(
69     noexcept(typename std::decay<T>::type(std::forward<T>(value)))) {
70   return std::forward<T>(value);
71 }
72
73 /**
74  * A simple helper for getting a constant reference to an object.
75  *
76  * Example:
77  *
78  *   std::vector<int> v{1,2,3};
79  *   // The following two lines are equivalent:
80  *   auto a = const_cast<const std::vector<int>&>(v).begin();
81  *   auto b = folly::as_const(v).begin();
82  *
83  * Like C++17's std::as_const. See http://wg21.link/p0007
84  */
85 #if __cpp_lib_as_const || _MSC_VER
86
87 /* using override */ using std::as_const;
88
89 #else
90
91 template <class T>
92 constexpr T const& as_const(T& t) noexcept {
93   return t;
94 }
95
96 template <class T>
97 void as_const(T const&&) = delete;
98
99 #endif
100
101 #if __cpp_lib_integer_sequence || _MSC_VER
102
103 /* using override */ using std::integer_sequence;
104 /* using override */ using std::index_sequence;
105 /* using override */ using std::make_index_sequence;
106
107 #else
108
109 template <class T, T... Ints>
110 struct integer_sequence {
111   using value_type = T;
112
113   static constexpr std::size_t size() noexcept {
114     return sizeof...(Ints);
115   }
116 };
117
118 template <std::size_t... Ints>
119 using index_sequence = folly::integer_sequence<std::size_t, Ints...>;
120
121 namespace detail {
122 template <std::size_t N, std::size_t... Ints>
123 struct make_index_sequence
124     : detail::make_index_sequence<N - 1, N - 1, Ints...> {};
125
126 template <std::size_t... Ints>
127 struct make_index_sequence<0, Ints...> : folly::index_sequence<Ints...> {};
128 }
129
130 template <std::size_t N>
131 using make_index_sequence = detail::make_index_sequence<N>;
132
133 #endif
134
135 /**
136  *  Backports from C++17 of:
137  *    std::in_place_t
138  *    std::in_place_type_t
139  *    std::in_place_index_t
140  *    std::in_place
141  *    std::in_place_type
142  *    std::in_place_index
143  */
144
145 struct in_place_tag {};
146 template <class>
147 struct in_place_type_tag {};
148 template <std::size_t>
149 struct in_place_index_tag {};
150
151 using in_place_t = in_place_tag (&)(in_place_tag);
152 template <class T>
153 using in_place_type_t = in_place_type_tag<T> (&)(in_place_type_tag<T>);
154 template <std::size_t I>
155 using in_place_index_t = in_place_index_tag<I> (&)(in_place_index_tag<I>);
156
157 inline in_place_tag in_place(in_place_tag = {}) {
158   return {};
159 }
160 template <class T>
161 inline in_place_type_tag<T> in_place_type(in_place_type_tag<T> = {}) {
162   return {};
163 }
164 template <std::size_t I>
165 inline in_place_index_tag<I> in_place_index(in_place_index_tag<I> = {}) {
166   return {};
167 }
168
169 /**
170  * Initializer lists are a powerful compile time syntax introduced in C++11
171  * but due to their often conflicting syntax they are not used by APIs for
172  * construction.
173  *
174  * Further standard conforming compilers *strongly* favor an
175  * std::initalizer_list overload for construction if one exists.  The
176  * following is a simple tag used to disambiguate construction with
177  * initializer lists and regular uniform initialization.
178  *
179  * For example consider the following case
180  *
181  *  class Something {
182  *  public:
183  *    explicit Something(int);
184  *    Something(std::intiializer_list<int>);
185  *
186  *    operator int();
187  *  };
188  *
189  *  ...
190  *  Something something{1}; // SURPRISE!!
191  *
192  * The last call to instantiate the Something object will go to the
193  * initializer_list overload.  Which may be surprising to users.
194  *
195  * If however this tag was used to disambiguate such construction it would be
196  * easy for users to see which construction overload their code was referring
197  * to.  For example
198  *
199  *  class Something {
200  *  public:
201  *    explicit Something(int);
202  *    Something(folly::initlist_construct_t, std::initializer_list<int>);
203  *
204  *    operator int();
205  *  };
206  *
207  *  ...
208  *  Something something_one{1}; // not the initializer_list overload
209  *  Something something_two{folly::initlist_construct, {1}}; // correct
210  */
211 struct initlist_construct_t {};
212 constexpr initlist_construct_t initlist_construct{};
213
214 /**
215  * A simple function object that passes its argument through unchanged.
216  *
217  * Example:
218  *
219  *   int i = 42;
220  *   int &j = Identity()(i);
221  *   assert(&i == &j);
222  *
223  * Warning: passing a prvalue through Identity turns it into an xvalue,
224  * which can effect whether lifetime extension occurs or not. For instance:
225  *
226  *   auto&& x = std::make_unique<int>(42);
227  *   cout << *x ; // OK, x refers to a valid unique_ptr.
228  *
229  *   auto&& y = Identity()(std::make_unique<int>(42));
230  *   cout << *y ; // ERROR: y did not lifetime-extend the unique_ptr. It
231  *                // is no longer valid
232  */
233 struct Identity {
234   using is_transparent = void;
235   template <class T>
236   constexpr T&& operator()(T&& x) const noexcept {
237     return static_cast<T&&>(x);
238   }
239 };
240
241 namespace moveonly_ { // Protection from unintended ADL.
242
243 /**
244  * Disallow copy but not move in derived types. This is essentially
245  * boost::noncopyable (the implementation is almost identical) but it
246  * doesn't delete move constructor and move assignment.
247  */
248 class MoveOnly {
249  protected:
250   constexpr MoveOnly() = default;
251   ~MoveOnly() = default;
252
253   MoveOnly(MoveOnly&&) = default;
254   MoveOnly& operator=(MoveOnly&&) = default;
255   MoveOnly(const MoveOnly&) = delete;
256   MoveOnly& operator=(const MoveOnly&) = delete;
257 };
258
259 } // namespace moveonly_
260
261 using MoveOnly = moveonly_::MoveOnly;
262
263 /**
264  * Backport from C++17 of std::launder
265  */
266 template <typename T>
267 constexpr T* launder(T* in) {
268   return (in + 1) - 1;
269 }
270 } // namespace folly