]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | // This source code is licensed under both the GPLv2 (found in the | |
3 | // COPYING file in the root directory) and Apache 2.0 License | |
4 | // (found in the LICENSE.Apache file in the root directory). | |
5 | ||
6 | #pragma once | |
7 | ||
8 | #include <utility> | |
9 | #include <type_traits> | |
10 | ||
11 | namespace folly { | |
12 | ||
13 | /** | |
14 | * Backports from C++17 of: | |
15 | * std::in_place_t | |
16 | * std::in_place_type_t | |
17 | * std::in_place_index_t | |
18 | * std::in_place | |
19 | * std::in_place_type | |
20 | * std::in_place_index | |
21 | */ | |
22 | ||
23 | struct in_place_tag {}; | |
24 | template <class> | |
25 | struct in_place_type_tag {}; | |
26 | template <std::size_t> | |
27 | struct in_place_index_tag {}; | |
28 | ||
29 | using in_place_t = in_place_tag (&)(in_place_tag); | |
30 | template <class T> | |
31 | using in_place_type_t = in_place_type_tag<T> (&)(in_place_type_tag<T>); | |
32 | template <std::size_t I> | |
33 | using in_place_index_t = in_place_index_tag<I> (&)(in_place_index_tag<I>); | |
34 | ||
35 | inline in_place_tag in_place(in_place_tag = {}) { | |
36 | return {}; | |
37 | } | |
38 | template <class T> | |
39 | inline in_place_type_tag<T> in_place_type(in_place_type_tag<T> = {}) { | |
40 | return {}; | |
41 | } | |
42 | template <std::size_t I> | |
43 | inline in_place_index_tag<I> in_place_index(in_place_index_tag<I> = {}) { | |
44 | return {}; | |
45 | } | |
46 | ||
47 | template <class T, class U = T> | |
48 | T exchange(T& obj, U&& new_value) { | |
49 | T old_value = std::move(obj); | |
50 | obj = std::forward<U>(new_value); | |
51 | return old_value; | |
52 | } | |
53 | ||
54 | namespace utility_detail { | |
55 | template <typename...> | |
56 | struct make_seq_cat; | |
57 | template < | |
58 | template <typename T, T...> class S, | |
59 | typename T, | |
60 | T... Ta, | |
61 | T... Tb, | |
62 | T... Tc> | |
63 | struct make_seq_cat<S<T, Ta...>, S<T, Tb...>, S<T, Tc...>> { | |
64 | using type = | |
65 | S<T, | |
66 | Ta..., | |
67 | (sizeof...(Ta) + Tb)..., | |
68 | (sizeof...(Ta) + sizeof...(Tb) + Tc)...>; | |
69 | }; | |
70 | ||
71 | // Not parameterizing by `template <typename T, T...> class, typename` because | |
72 | // clang precisely v4.0 fails to compile that. Note that clang v3.9 and v5.0 | |
73 | // handle that code correctly. | |
74 | // | |
75 | // For this to work, `S0` is required to be `Sequence<T>` and `S1` is required | |
76 | // to be `Sequence<T, 0>`. | |
77 | ||
78 | template <std::size_t Size> | |
79 | struct make_seq { | |
80 | template <typename S0, typename S1> | |
81 | using apply = typename make_seq_cat< | |
82 | typename make_seq<Size / 2>::template apply<S0, S1>, | |
83 | typename make_seq<Size / 2>::template apply<S0, S1>, | |
84 | typename make_seq<Size % 2>::template apply<S0, S1>>::type; | |
85 | }; | |
86 | template <> | |
87 | struct make_seq<1> { | |
88 | template <typename S0, typename S1> | |
89 | using apply = S1; | |
90 | }; | |
91 | template <> | |
92 | struct make_seq<0> { | |
93 | template <typename S0, typename S1> | |
94 | using apply = S0; | |
95 | }; | |
96 | } // namespace utility_detail | |
97 | ||
98 | // TODO: Remove after upgrading to C++14 baseline | |
99 | ||
100 | template <class T, T... Ints> | |
101 | struct integer_sequence { | |
102 | using value_type = T; | |
103 | ||
104 | static constexpr std::size_t size() noexcept { | |
105 | return sizeof...(Ints); | |
106 | } | |
107 | }; | |
108 | ||
109 | template <std::size_t... Ints> | |
110 | using index_sequence = integer_sequence<std::size_t, Ints...>; | |
111 | ||
112 | template <typename T, std::size_t Size> | |
113 | using make_integer_sequence = typename utility_detail::make_seq< | |
114 | Size>::template apply<integer_sequence<T>, integer_sequence<T, 0>>; | |
115 | ||
116 | template <std::size_t Size> | |
117 | using make_index_sequence = make_integer_sequence<std::size_t, Size>; | |
118 | template <class... T> | |
119 | using index_sequence_for = make_index_sequence<sizeof...(T)>; | |
120 | ||
121 | /** | |
122 | * A simple helper for getting a constant reference to an object. | |
123 | * | |
124 | * Example: | |
125 | * | |
126 | * std::vector<int> v{1,2,3}; | |
127 | * // The following two lines are equivalent: | |
128 | * auto a = const_cast<const std::vector<int>&>(v).begin(); | |
129 | * auto b = folly::as_const(v).begin(); | |
130 | * | |
131 | * Like C++17's std::as_const. See http://wg21.link/p0007 | |
132 | */ | |
133 | template <class T> | |
134 | T const& as_const(T& t) noexcept { | |
135 | return t; | |
136 | } | |
137 | ||
138 | template <class T> | |
139 | void as_const(T const&&) = delete; | |
140 | ||
141 | } // namespace folly |