Fix copyright line in folly/synchronization/test/ParkingLotBenchmark.cpp
[folly.git] / folly / Utility.h
1 /*
2  * Copyright 2016-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 <cstdint>
20 #include <type_traits>
21 #include <utility>
22
23 #include <folly/CPortability.h>
24
25 namespace folly {
26
27 /**
28  *  copy
29  *
30  *  Usable when you have a function with two overloads:
31  *
32  *      class MyData;
33  *      void something(MyData&&);
34  *      void something(const MyData&);
35  *
36  *  Where the purpose is to make copies and moves explicit without having to
37  *  spell out the full type names - in this case, for copies, to invoke copy
38  *  constructors.
39  *
40  *  When the caller wants to pass a copy of an lvalue, the caller may:
41  *
42  *      void foo() {
43  *        MyData data;
44  *        something(folly::copy(data)); // explicit copy
45  *        something(std::move(data)); // explicit move
46  *        something(data); // const& - neither move nor copy
47  *      }
48  *
49  *  Note: If passed an rvalue, invokes the move-ctor, not the copy-ctor. This
50  *  can be used to to force a move, where just using std::move would not:
51  *
52  *      std::copy(std::move(data)); // force-move, not just a cast to &&
53  *
54  *  Note: The following text appears in the standard:
55  *
56  *  > In several places in this Clause the operation //DECAY_COPY(x)// is used.
57  *  > All such uses mean call the function `decay_copy(x)` and use the result,
58  *  > where `decay_copy` is defined as follows:
59  *  >
60  *  >   template <class T> decay_t<T> decay_copy(T&& v)
61  *  >     { return std::forward<T>(v); }
62  *  >
63  *  > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
64  *  >   30.2.6 `decay_copy` [thread.decaycopy].
65  *
66  *  We mimic it, with a `noexcept` specifier for good measure.
67  */
68
69 template <typename T>
70 constexpr typename std::decay<T>::type copy(T&& value) noexcept(
71     noexcept(typename std::decay<T>::type(std::forward<T>(value)))) {
72   return std::forward<T>(value);
73 }
74
75 /**
76  * A simple helper for getting a constant reference to an object.
77  *
78  * Example:
79  *
80  *   std::vector<int> v{1,2,3};
81  *   // The following two lines are equivalent:
82  *   auto a = const_cast<const std::vector<int>&>(v).begin();
83  *   auto b = folly::as_const(v).begin();
84  *
85  * Like C++17's std::as_const. See http://wg21.link/p0007
86  */
87 #if __cpp_lib_as_const || _MSC_VER
88
89 /* using override */ using std::as_const;
90
91 #else
92
93 template <class T>
94 constexpr T const& as_const(T& t) noexcept {
95   return t;
96 }
97
98 template <class T>
99 void as_const(T const&&) = delete;
100
101 #endif
102
103 namespace utility_detail {
104 template <typename...>
105 struct make_seq_cat;
106 template <
107     template <typename T, T...> class S,
108     typename T,
109     T... Ta,
110     T... Tb,
111     T... Tc>
112 struct make_seq_cat<S<T, Ta...>, S<T, Tb...>, S<T, Tc...>> {
113   using type =
114       S<T,
115         Ta...,
116         (sizeof...(Ta) + Tb)...,
117         (sizeof...(Ta) + sizeof...(Tb) + Tc)...>;
118 };
119
120 // Not parameterizing by `template <typename T, T...> class, typename` because
121 // clang precisely v4.0 fails to compile that. Note that clang v3.9 and v5.0
122 // handle that code correctly.
123 //
124 // For this to work, `S0` is required to be `Sequence<T>` and `S1` is required
125 // to be `Sequence<T, 0>`.
126
127 template <std::size_t Size>
128 struct make_seq {
129   template <typename S0, typename S1>
130   using apply = typename make_seq_cat<
131       typename make_seq<Size / 2>::template apply<S0, S1>,
132       typename make_seq<Size / 2>::template apply<S0, S1>,
133       typename make_seq<Size % 2>::template apply<S0, S1>>::type;
134 };
135 template <>
136 struct make_seq<1> {
137   template <typename S0, typename S1>
138   using apply = S1;
139 };
140 template <>
141 struct make_seq<0> {
142   template <typename S0, typename S1>
143   using apply = S0;
144 };
145 } // namespace utility_detail
146
147 #if __cpp_lib_integer_sequence || _MSC_VER
148
149 /* using override */ using std::integer_sequence;
150 /* using override */ using std::index_sequence;
151
152 #else
153
154 // TODO: Remove after upgrading to C++14 baseline
155
156 template <class T, T... Ints>
157 struct integer_sequence {
158   using value_type = T;
159
160   static constexpr std::size_t size() noexcept {
161     return sizeof...(Ints);
162   }
163 };
164
165 template <std::size_t... Ints>
166 using index_sequence = integer_sequence<std::size_t, Ints...>;
167
168 #endif
169
170 #if FOLLY_HAS_BUILTIN(__make_integer_seq) || _MSC_FULL_VER >= 190023918
171
172 template <typename T, std::size_t Size>
173 using make_integer_sequence = __make_integer_seq<integer_sequence, T, Size>;
174
175 #else
176
177 template <typename T, std::size_t Size>
178 using make_integer_sequence = typename utility_detail::make_seq<
179     Size>::template apply<integer_sequence<T>, integer_sequence<T, 0>>;
180
181 #endif
182
183 template <std::size_t Size>
184 using make_index_sequence = make_integer_sequence<std::size_t, Size>;
185
186 /**
187  *  Backports from C++17 of:
188  *    std::in_place_t
189  *    std::in_place_type_t
190  *    std::in_place_index_t
191  *    std::in_place
192  *    std::in_place_type
193  *    std::in_place_index
194  */
195
196 struct in_place_tag {};
197 template <class>
198 struct in_place_type_tag {};
199 template <std::size_t>
200 struct in_place_index_tag {};
201
202 using in_place_t = in_place_tag (&)(in_place_tag);
203 template <class T>
204 using in_place_type_t = in_place_type_tag<T> (&)(in_place_type_tag<T>);
205 template <std::size_t I>
206 using in_place_index_t = in_place_index_tag<I> (&)(in_place_index_tag<I>);
207
208 inline in_place_tag in_place(in_place_tag = {}) {
209   return {};
210 }
211 template <class T>
212 inline in_place_type_tag<T> in_place_type(in_place_type_tag<T> = {}) {
213   return {};
214 }
215 template <std::size_t I>
216 inline in_place_index_tag<I> in_place_index(in_place_index_tag<I> = {}) {
217   return {};
218 }
219
220 /**
221  * Initializer lists are a powerful compile time syntax introduced in C++11
222  * but due to their often conflicting syntax they are not used by APIs for
223  * construction.
224  *
225  * Further standard conforming compilers *strongly* favor an
226  * std::initalizer_list overload for construction if one exists.  The
227  * following is a simple tag used to disambiguate construction with
228  * initializer lists and regular uniform initialization.
229  *
230  * For example consider the following case
231  *
232  *  class Something {
233  *  public:
234  *    explicit Something(int);
235  *    Something(std::intiializer_list<int>);
236  *
237  *    operator int();
238  *  };
239  *
240  *  ...
241  *  Something something{1}; // SURPRISE!!
242  *
243  * The last call to instantiate the Something object will go to the
244  * initializer_list overload.  Which may be surprising to users.
245  *
246  * If however this tag was used to disambiguate such construction it would be
247  * easy for users to see which construction overload their code was referring
248  * to.  For example
249  *
250  *  class Something {
251  *  public:
252  *    explicit Something(int);
253  *    Something(folly::initlist_construct_t, std::initializer_list<int>);
254  *
255  *    operator int();
256  *  };
257  *
258  *  ...
259  *  Something something_one{1}; // not the initializer_list overload
260  *  Something something_two{folly::initlist_construct, {1}}; // correct
261  */
262 struct initlist_construct_t {};
263 constexpr initlist_construct_t initlist_construct{};
264
265 /**
266  * A generic tag type to indicate that some constructor or method is in some way
267  * unsafe and should be used only with extreme care and with full test coverage,
268  * if ever.
269  *
270  * Example:
271  *
272  *  void takes_numbers(std::vector<int> alist) {
273  *    std::sort(alist.begin(), alist.end());
274  *    takes_numbers_assume_sorted(folly::unsafe, alist);
275  *  }
276  *
277  *  void takes_numbers_assume_sorted(folly::unsafe_t, std::vector<int> alist) {
278  *    assert(std::is_sorted(alist.begin(), alist.end())); // debug mode only
279  *    for (i : alist) {
280  *      // some behavior which is defined and safe only when alist is sorted ...
281  *    }
282  *  }
283  */
284 struct unsafe_t {};
285 constexpr unsafe_t unsafe{};
286
287 /**
288  * A simple function object that passes its argument through unchanged.
289  *
290  * Example:
291  *
292  *   int i = 42;
293  *   int &j = Identity()(i);
294  *   assert(&i == &j);
295  *
296  * Warning: passing a prvalue through Identity turns it into an xvalue,
297  * which can effect whether lifetime extension occurs or not. For instance:
298  *
299  *   auto&& x = std::make_unique<int>(42);
300  *   cout << *x ; // OK, x refers to a valid unique_ptr.
301  *
302  *   auto&& y = Identity()(std::make_unique<int>(42));
303  *   cout << *y ; // ERROR: y did not lifetime-extend the unique_ptr. It
304  *                // is no longer valid
305  */
306 struct Identity {
307   using is_transparent = void;
308   template <class T>
309   constexpr T&& operator()(T&& x) const noexcept {
310     return static_cast<T&&>(x);
311   }
312 };
313
314 namespace moveonly_ { // Protection from unintended ADL.
315
316 /**
317  * Disallow copy but not move in derived types. This is essentially
318  * boost::noncopyable (the implementation is almost identical) but it
319  * doesn't delete move constructor and move assignment.
320  */
321 class MoveOnly {
322  protected:
323   constexpr MoveOnly() = default;
324   ~MoveOnly() = default;
325
326   MoveOnly(MoveOnly&&) = default;
327   MoveOnly& operator=(MoveOnly&&) = default;
328   MoveOnly(const MoveOnly&) = delete;
329   MoveOnly& operator=(const MoveOnly&) = delete;
330 };
331
332 } // namespace moveonly_
333
334 using MoveOnly = moveonly_::MoveOnly;
335
336 /**
337  * A pithy alias for std::integral_constant<bool, B>.
338  */
339 template <bool B>
340 using Bool = std::integral_constant<bool, B>;
341
342 } // namespace folly