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