2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <type_traits>
23 #include <folly/CPortability.h>
30 * Usable when you have a function with two overloads:
33 * void something(MyData&&);
34 * void something(const MyData&);
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
40 * When the caller wants to pass a copy of an lvalue, the caller may:
44 * something(folly::copy(data)); // explicit copy
45 * something(std::move(data)); // explicit move
46 * something(data); // const& - neither move nor copy
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:
52 * std::copy(std::move(data)); // force-move, not just a cast to &&
54 * Note: The following text appears in the standard:
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:
60 * > template <class T> decay_t<T> decay_copy(T&& v)
61 * > { return std::forward<T>(v); }
63 * > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
64 * > 30.2.6 `decay_copy` [thread.decaycopy].
66 * We mimic it, with a `noexcept` specifier for good measure.
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);
76 * A simple helper for getting a constant reference to an object.
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();
85 * Like C++17's std::as_const. See http://wg21.link/p0007
87 #if __cpp_lib_as_const || _MSC_VER
89 /* using override */ using std::as_const;
94 constexpr T const& as_const(T& t) noexcept {
99 void as_const(T const&&) = delete;
103 namespace utility_detail {
104 template <typename...>
107 template <typename T, T...> class S,
112 struct make_seq_cat<S<T, Ta...>, S<T, Tb...>, S<T, Tc...>> {
116 (sizeof...(Ta) + Tb)...,
117 (sizeof...(Ta) + sizeof...(Tb) + Tc)...>;
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.
124 // For this to work, `S0` is required to be `Sequence<T>` and `S1` is required
125 // to be `Sequence<T, 0>`.
127 template <std::size_t Size>
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;
137 template <typename S0, typename S1>
142 template <typename S0, typename S1>
147 #if __cpp_lib_integer_sequence || _MSC_VER
149 /* using override */ using std::integer_sequence;
150 /* using override */ using std::index_sequence;
154 // TODO: Remove after upgrading to C++14 baseline
156 template <class T, T... Ints>
157 struct integer_sequence {
158 using value_type = T;
160 static constexpr std::size_t size() noexcept {
161 return sizeof...(Ints);
165 template <std::size_t... Ints>
166 using index_sequence = integer_sequence<std::size_t, Ints...>;
170 #if FOLLY_HAS_BUILTIN(__make_integer_seq) || _MSC_FULL_VER >= 190023918
172 template <typename T, std::size_t Size>
173 using make_integer_sequence = __make_integer_seq<integer_sequence, T, Size>;
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>>;
183 template <std::size_t Size>
184 using make_index_sequence = make_integer_sequence<std::size_t, Size>;
187 * Backports from C++17 of:
189 * std::in_place_type_t
190 * std::in_place_index_t
193 * std::in_place_index
196 struct in_place_tag {};
198 struct in_place_type_tag {};
199 template <std::size_t>
200 struct in_place_index_tag {};
202 using in_place_t = in_place_tag (&)(in_place_tag);
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>);
208 inline in_place_tag in_place(in_place_tag = {}) {
212 inline in_place_type_tag<T> in_place_type(in_place_type_tag<T> = {}) {
215 template <std::size_t I>
216 inline in_place_index_tag<I> in_place_index(in_place_index_tag<I> = {}) {
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
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.
230 * For example consider the following case
234 * explicit Something(int);
235 * Something(std::intiializer_list<int>);
241 * Something something{1}; // SURPRISE!!
243 * The last call to instantiate the Something object will go to the
244 * initializer_list overload. Which may be surprising to users.
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
252 * explicit Something(int);
253 * Something(folly::initlist_construct_t, std::initializer_list<int>);
259 * Something something_one{1}; // not the initializer_list overload
260 * Something something_two{folly::initlist_construct, {1}}; // correct
262 struct initlist_construct_t {};
263 constexpr initlist_construct_t initlist_construct{};
266 * A simple function object that passes its argument through unchanged.
271 * int &j = Identity()(i);
274 * Warning: passing a prvalue through Identity turns it into an xvalue,
275 * which can effect whether lifetime extension occurs or not. For instance:
277 * auto&& x = std::make_unique<int>(42);
278 * cout << *x ; // OK, x refers to a valid unique_ptr.
280 * auto&& y = Identity()(std::make_unique<int>(42));
281 * cout << *y ; // ERROR: y did not lifetime-extend the unique_ptr. It
282 * // is no longer valid
285 using is_transparent = void;
287 constexpr T&& operator()(T&& x) const noexcept {
288 return static_cast<T&&>(x);
292 namespace moveonly_ { // Protection from unintended ADL.
295 * Disallow copy but not move in derived types. This is essentially
296 * boost::noncopyable (the implementation is almost identical) but it
297 * doesn't delete move constructor and move assignment.
301 constexpr MoveOnly() = default;
302 ~MoveOnly() = default;
304 MoveOnly(MoveOnly&&) = default;
305 MoveOnly& operator=(MoveOnly&&) = default;
306 MoveOnly(const MoveOnly&) = delete;
307 MoveOnly& operator=(const MoveOnly&) = delete;
310 } // namespace moveonly_
312 using MoveOnly = moveonly_::MoveOnly;