/* * Copyright 2016-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include namespace folly { /** * copy * * Usable when you have a function with two overloads: * * class MyData; * void something(MyData&&); * void something(const MyData&); * * Where the purpose is to make copies and moves explicit without having to * spell out the full type names - in this case, for copies, to invoke copy * constructors. * * When the caller wants to pass a copy of an lvalue, the caller may: * * void foo() { * MyData data; * something(folly::copy(data)); // explicit copy * something(std::move(data)); // explicit move * something(data); // const& - neither move nor copy * } * * Note: If passed an rvalue, invokes the move-ctor, not the copy-ctor. This * can be used to to force a move, where just using std::move would not: * * std::copy(std::move(data)); // force-move, not just a cast to && * * Note: The following text appears in the standard: * * > In several places in this Clause the operation //DECAY_COPY(x)// is used. * > All such uses mean call the function `decay_copy(x)` and use the result, * > where `decay_copy` is defined as follows: * > * > template decay_t decay_copy(T&& v) * > { return std::forward(v); } * > * > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf * > 30.2.6 `decay_copy` [thread.decaycopy]. * * We mimic it, with a `noexcept` specifier for good measure. */ template constexpr typename std::decay::type copy(T&& value) noexcept( noexcept(typename std::decay::type(std::forward(value)))) { return std::forward(value); } /** * A simple helper for getting a constant reference to an object. * * Example: * * std::vector v{1,2,3}; * // The following two lines are equivalent: * auto a = const_cast&>(v).begin(); * auto b = folly::as_const(v).begin(); * * Like C++17's std::as_const. See http://wg21.link/p0007 */ #if __cpp_lib_as_const || _MSC_VER /* using override */ using std::as_const; #else template constexpr T const& as_const(T& t) noexcept { return t; } template void as_const(T const&&) = delete; #endif // mimic: forward_like, p0847r0 template constexpr like_t&& forward_like(Dst&& dst) noexcept { return static_cast&&>(std::forward(dst)); } #if __cpp_lib_exchange_function || _LIBCPP_STD_VER > 11 || _MSC_VER /* using override */ using std::exchange; #else // mimic: std::exchange, C++14 // from: http://en.cppreference.com/w/cpp/utility/exchange, CC-BY-SA template T exchange(T& obj, U&& new_value) { T old_value = std::move(obj); obj = std::forward(new_value); return old_value; } #endif namespace utility_detail { template struct make_seq_cat; template < template class S, typename T, T... Ta, T... Tb, T... Tc> struct make_seq_cat, S, S> { using type = S; }; // Not parameterizing by `template class, typename` because // clang precisely v4.0 fails to compile that. Note that clang v3.9 and v5.0 // handle that code correctly. // // For this to work, `S0` is required to be `Sequence` and `S1` is required // to be `Sequence`. template struct make_seq { template using apply = typename make_seq_cat< typename make_seq::template apply, typename make_seq::template apply, typename make_seq::template apply>::type; }; template <> struct make_seq<1> { template using apply = S1; }; template <> struct make_seq<0> { template using apply = S0; }; } // namespace utility_detail #if __cpp_lib_integer_sequence || _MSC_VER /* using override */ using std::index_sequence; /* using override */ using std::integer_sequence; #else // TODO: Remove after upgrading to C++14 baseline template struct integer_sequence { using value_type = T; static constexpr std::size_t size() noexcept { return sizeof...(Ints); } }; template using index_sequence = integer_sequence; #endif #if FOLLY_HAS_BUILTIN(__make_integer_seq) || _MSC_FULL_VER >= 190023918 template using make_integer_sequence = __make_integer_seq; #else template using make_integer_sequence = typename utility_detail::make_seq< Size>::template apply, integer_sequence>; #endif template using make_index_sequence = make_integer_sequence; template using index_sequence_for = make_index_sequence; /** * Backports from C++17 of: * std::in_place_t * std::in_place_type_t * std::in_place_index_t * std::in_place * std::in_place_type * std::in_place_index */ struct in_place_tag {}; template struct in_place_type_tag {}; template struct in_place_index_tag {}; using in_place_t = in_place_tag (&)(in_place_tag); template using in_place_type_t = in_place_type_tag (&)(in_place_type_tag); template using in_place_index_t = in_place_index_tag (&)(in_place_index_tag); inline in_place_tag in_place(in_place_tag = {}) { return {}; } template inline in_place_type_tag in_place_type(in_place_type_tag = {}) { return {}; } template inline in_place_index_tag in_place_index(in_place_index_tag = {}) { return {}; } /** * Initializer lists are a powerful compile time syntax introduced in C++11 * but due to their often conflicting syntax they are not used by APIs for * construction. * * Further standard conforming compilers *strongly* favor an * std::initalizer_list overload for construction if one exists. The * following is a simple tag used to disambiguate construction with * initializer lists and regular uniform initialization. * * For example consider the following case * * class Something { * public: * explicit Something(int); * Something(std::intiializer_list); * * operator int(); * }; * * ... * Something something{1}; // SURPRISE!! * * The last call to instantiate the Something object will go to the * initializer_list overload. Which may be surprising to users. * * If however this tag was used to disambiguate such construction it would be * easy for users to see which construction overload their code was referring * to. For example * * class Something { * public: * explicit Something(int); * Something(folly::initlist_construct_t, std::initializer_list); * * operator int(); * }; * * ... * Something something_one{1}; // not the initializer_list overload * Something something_two{folly::initlist_construct, {1}}; // correct */ struct initlist_construct_t {}; constexpr initlist_construct_t initlist_construct{}; /** * A generic tag type to indicate that some constructor or method accepts a * presorted container. * * Example: * * void takes_numbers(std::vector alist) { * std::sort(alist.begin(), alist.end()); * takes_numbers(folly::presorted, alist); * } * * void takes_numbers(folly::presorted_t, std::vector alist) { * assert(std::is_sorted(alist.begin(), alist.end())); // debug mode only * for (i : alist) { * // some behavior which is defined and safe only when alist is sorted ... * } * } */ struct presorted_t {}; constexpr presorted_t presorted{}; /** * A generic tag type to indicate that some constructor or method accepts an * unsorted container. Useful in contexts which might have some reason to assume * a container to be sorted. * * Example: * * void takes_numbers(std::vector alist) { * takes_numbers(folly::unsorted, alist); * } * * void takes_numbers(folly::unsorted_t, std::vector alist) { * std::sort(alist.begin(), alist.end()); * for (i : alist) { * // some behavior which is defined and safe only when alist is sorted ... * } * } */ struct unsorted_t {}; constexpr unsorted_t unsorted{}; template struct transparent : T { using is_transparent = void; using T::T; }; /** * A simple function object that passes its argument through unchanged. * * Example: * * int i = 42; * int &j = Identity()(i); * assert(&i == &j); * * Warning: passing a prvalue through Identity turns it into an xvalue, * which can effect whether lifetime extension occurs or not. For instance: * * auto&& x = std::make_unique(42); * cout << *x ; // OK, x refers to a valid unique_ptr. * * auto&& y = Identity()(std::make_unique(42)); * cout << *y ; // ERROR: y did not lifetime-extend the unique_ptr. It * // is no longer valid */ struct Identity { template constexpr T&& operator()(T&& x) const noexcept { return static_cast(x); } }; namespace moveonly_ { // Protection from unintended ADL. /** * Disallow copy but not move in derived types. This is essentially * boost::noncopyable (the implementation is almost identical) but it * doesn't delete move constructor and move assignment. */ class MoveOnly { protected: constexpr MoveOnly() = default; ~MoveOnly() = default; MoveOnly(MoveOnly&&) = default; MoveOnly& operator=(MoveOnly&&) = default; MoveOnly(const MoveOnly&) = delete; MoveOnly& operator=(const MoveOnly&) = delete; }; } // namespace moveonly_ using MoveOnly = moveonly_::MoveOnly; template constexpr auto to_signed(T const& t) -> typename std::make_signed::type { using S = typename std::make_signed::type; // note: static_cast(t) would be more straightforward, but it would also be // implementation-defined behavior and that is typically to be avoided; the // following code optimized into the same thing, though return std::numeric_limits::max() < t ? -static_cast(~t) + S{-1} : static_cast(t); } template constexpr auto to_unsigned(T const& t) -> typename std::make_unsigned::type { using U = typename std::make_unsigned::type; return static_cast(t); } } // namespace folly