/src/boost/boost/json/pilfer.hpp
Line | Count | Source |
1 | | // |
2 | | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) |
3 | | // |
4 | | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
5 | | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | | // |
7 | | // Official repository: https://github.com/boostorg/json |
8 | | // |
9 | | |
10 | | #ifndef BOOST_JSON_PILFER_HPP |
11 | | #define BOOST_JSON_PILFER_HPP |
12 | | |
13 | | #include <boost/json/detail/config.hpp> |
14 | | #include <type_traits> |
15 | | #include <utility> |
16 | | |
17 | | /* |
18 | | Implements "pilfering" from P0308R0 |
19 | | |
20 | | @see |
21 | | http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html |
22 | | */ |
23 | | |
24 | | namespace boost { |
25 | | namespace json { |
26 | | |
27 | | /** Tag wrapper to specify pilfer-construction. |
28 | | |
29 | | This wrapper is used to specify a pilfer constructor |
30 | | overload. |
31 | | |
32 | | @par Example |
33 | | |
34 | | A pilfer constructor accepts a single argument |
35 | | of type @ref pilfered and throws nothing: |
36 | | |
37 | | @code |
38 | | struct T |
39 | | { |
40 | | T( pilfered<T> ) noexcept; |
41 | | }; |
42 | | @endcode |
43 | | |
44 | | @note |
45 | | |
46 | | The constructor should not be marked explicit. |
47 | | |
48 | | @see @ref pilfer, @ref is_pilfer_constructible, |
49 | | <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html"> |
50 | | Valueless Variants Considered Harmful</a> |
51 | | */ |
52 | | template<class T> |
53 | | class pilfered |
54 | | { |
55 | | T& t_; |
56 | | |
57 | | public: |
58 | | /** Constructor |
59 | | |
60 | | Construct the wrapper from `t`. |
61 | | |
62 | | @param t The pilferable object. Ownership |
63 | | is not transferred. |
64 | | */ |
65 | | explicit |
66 | | constexpr |
67 | | pilfered(T&& t) noexcept |
68 | 1.81M | : t_(t) |
69 | 1.81M | { |
70 | 1.81M | } boost::json::pilfered<boost::json::value>::pilfered(boost::json::value&&) Line | Count | Source | 68 | 1.81M | : t_(t) | 69 | 1.81M | { | 70 | 1.81M | } |
Unexecuted instantiation: boost::json::pilfered<boost::json::array>::pilfered(boost::json::array&&) Unexecuted instantiation: boost::json::pilfered<boost::json::object>::pilfered(boost::json::object&&) Unexecuted instantiation: boost::json::pilfered<boost::json::key_value_pair>::pilfered(boost::json::key_value_pair&&) Unexecuted instantiation: boost::json::pilfered<boost::json::string>::pilfered(boost::json::string&&) |
71 | | |
72 | | /** Return a reference to the pilferable object. |
73 | | |
74 | | This returns a reference to the wrapped object. |
75 | | */ |
76 | | constexpr T& |
77 | | get() const noexcept |
78 | 2.73M | { |
79 | 2.73M | return t_; |
80 | 2.73M | } Unexecuted instantiation: boost::json::pilfered<boost::json::array>::get() const Unexecuted instantiation: boost::json::pilfered<boost::json::object>::get() const Unexecuted instantiation: boost::json::pilfered<boost::json::string>::get() const boost::json::pilfered<boost::json::value>::get() const Line | Count | Source | 78 | 2.73M | { | 79 | 2.73M | return t_; | 80 | 2.73M | } |
Unexecuted instantiation: boost::json::pilfered<boost::json::key_value_pair>::get() const |
81 | | |
82 | | /** Return a pointer to the pilferable object. |
83 | | |
84 | | This returns a pointer to the wrapped object. |
85 | | */ |
86 | | constexpr T* |
87 | | operator->() const noexcept |
88 | | { |
89 | | //return std::addressof(t_); |
90 | | return reinterpret_cast<T*>( |
91 | | const_cast<char *>( |
92 | | &reinterpret_cast< |
93 | | const volatile char &>(t_))); |
94 | | } |
95 | | }; |
96 | | |
97 | | #ifndef BOOST_JSON_DOCS |
98 | | // VFALCO Renamed this to work around an msvc bug |
99 | | namespace detail_pilfer { |
100 | | template<class> |
101 | | struct not_pilfered |
102 | | { |
103 | | }; |
104 | | } // detail_pilfer |
105 | | #endif |
106 | | |
107 | | /** Metafunction returning `true` if `T` is <em>PilferConstructible</em> |
108 | | |
109 | | If `T` can be pilfer constructed, this metafunction is |
110 | | equal to `std::true_type`. Otherwise it is equal to |
111 | | `std::false_type`. |
112 | | |
113 | | @see @ref pilfer, @ref pilfered, |
114 | | <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html"> |
115 | | Valueless Variants Considered Harmful</a> |
116 | | */ |
117 | | template<class T> |
118 | | struct is_pilfer_constructible |
119 | | #ifndef BOOST_JSON_DOCS |
120 | | : std::integral_constant<bool, |
121 | | std::is_nothrow_move_constructible<T>::value || |
122 | | ( |
123 | | std::is_nothrow_constructible< |
124 | | T, pilfered<T> >::value && |
125 | | ! std::is_nothrow_constructible< |
126 | | T, detail_pilfer::not_pilfered<T> >::value |
127 | | )> |
128 | | #endif |
129 | | { |
130 | | }; |
131 | | |
132 | | /** Indicate that an object `t` may be pilfered from. |
133 | | |
134 | | A <em>pilfer</em> operation is the construction |
135 | | of a new object of type `T` from an existing |
136 | | object `t`. After the construction, the only |
137 | | valid operation on the pilfered-from object is |
138 | | destruction. This permits optimizations beyond |
139 | | those available for a move-construction, as the |
140 | | pilfered-from object is not required to be in |
141 | | a "usable" state. |
142 | | \n |
143 | | This is used similarly to `std::move`. |
144 | | |
145 | | @par Example |
146 | | |
147 | | A pilfer constructor accepts a single argument |
148 | | of type @ref pilfered and throws nothing: |
149 | | |
150 | | @code |
151 | | struct T |
152 | | { |
153 | | T( pilfered<T> ) noexcept; |
154 | | }; |
155 | | @endcode |
156 | | |
157 | | Pilfer construction is performed using @ref pilfer : |
158 | | |
159 | | @code |
160 | | { |
161 | | T t1; // default construction |
162 | | T t2( pilfer( t1 ) ); // pilfer-construct from t1 |
163 | | |
164 | | // At this point, t1 may only be destroyed |
165 | | } |
166 | | @endcode |
167 | | |
168 | | @see @ref pilfered, @ref is_pilfer_constructible, |
169 | | <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html"> |
170 | | Valueless Variants Considered Harmful</a> |
171 | | */ |
172 | | template<class T> |
173 | | auto |
174 | | pilfer(T&& t) noexcept -> |
175 | | typename std::conditional< |
176 | | std::is_nothrow_constructible< |
177 | | typename std::remove_reference<T>::type, |
178 | | pilfered<typename |
179 | | std::remove_reference<T>::type> >::value && |
180 | | ! std::is_nothrow_constructible< |
181 | | typename std::remove_reference<T>::type, |
182 | | detail_pilfer::not_pilfered<typename |
183 | | std::remove_reference<T>::type> >::value, |
184 | | pilfered<typename std::remove_reference<T>::type>, |
185 | | typename std::remove_reference<T>::type&& |
186 | | >::type |
187 | 1.83M | { |
188 | 1.83M | using U = |
189 | 1.83M | typename std::remove_reference<T>::type; |
190 | 1.83M | static_assert( |
191 | 1.83M | is_pilfer_constructible<U>::value, ""); |
192 | 1.83M | return typename std::conditional< |
193 | 1.83M | std::is_nothrow_constructible< |
194 | 1.83M | U, pilfered<U> >::value && |
195 | 1.83M | ! std::is_nothrow_constructible< |
196 | 1.83M | U, detail_pilfer::not_pilfered<U> >::value, |
197 | 1.83M | pilfered<U>, U&& |
198 | 1.83M | >::type(std::move(t)); |
199 | 1.83M | } _ZN5boost4json6pilferIRNS0_5valueEEENSt3__111conditionalIXaasr3std24is_nothrow_constructibleINS4_16remove_referenceIT_E4typeENS0_8pilferedIS9_EEEE5valuentsr3std24is_nothrow_constructibleIS9_NS0_13detail_pilfer12not_pilferedIS9_EEEE5valueESB_OS9_E4typeEOS7_ Line | Count | Source | 187 | 1.81M | { | 188 | 1.81M | using U = | 189 | 1.81M | typename std::remove_reference<T>::type; | 190 | 1.81M | static_assert( | 191 | 1.81M | is_pilfer_constructible<U>::value, ""); | 192 | 1.81M | return typename std::conditional< | 193 | 1.81M | std::is_nothrow_constructible< | 194 | 1.81M | U, pilfered<U> >::value && | 195 | 1.81M | ! std::is_nothrow_constructible< | 196 | 1.81M | U, detail_pilfer::not_pilfered<U> >::value, | 197 | 1.81M | pilfered<U>, U&& | 198 | 1.81M | >::type(std::move(t)); | 199 | 1.81M | } |
Unexecuted instantiation: _ZN5boost4json6pilferIRNS0_5arrayEEENSt3__111conditionalIXaasr3std24is_nothrow_constructibleINS4_16remove_referenceIT_E4typeENS0_8pilferedIS9_EEEE5valuentsr3std24is_nothrow_constructibleIS9_NS0_13detail_pilfer12not_pilferedIS9_EEEE5valueESB_OS9_E4typeEOS7_ Unexecuted instantiation: _ZN5boost4json6pilferIRNS0_6objectEEENSt3__111conditionalIXaasr3std24is_nothrow_constructibleINS4_16remove_referenceIT_E4typeENS0_8pilferedIS9_EEEE5valuentsr3std24is_nothrow_constructibleIS9_NS0_13detail_pilfer12not_pilferedIS9_EEEE5valueESB_OS9_E4typeEOS7_ Unexecuted instantiation: _ZN5boost4json6pilferIRNS0_14key_value_pairEEENSt3__111conditionalIXaasr3std24is_nothrow_constructibleINS4_16remove_referenceIT_E4typeENS0_8pilferedIS9_EEEE5valuentsr3std24is_nothrow_constructibleIS9_NS0_13detail_pilfer12not_pilferedIS9_EEEE5valueESB_OS9_E4typeEOS7_ Unexecuted instantiation: _ZN5boost4json6pilferIRNS0_6stringEEENSt3__111conditionalIXaasr3std24is_nothrow_constructibleINS4_16remove_referenceIT_E4typeENS0_8pilferedIS9_EEEE5valuentsr3std24is_nothrow_constructibleIS9_NS0_13detail_pilfer12not_pilferedIS9_EEEE5valueESB_OS9_E4typeEOS7_ _ZN5boost4json6pilferIRNS0_11storage_ptrEEENSt3__111conditionalIXaasr3std24is_nothrow_constructibleINS4_16remove_referenceIT_E4typeENS0_8pilferedIS9_EEEE5valuentsr3std24is_nothrow_constructibleIS9_NS0_13detail_pilfer12not_pilferedIS9_EEEE5valueESB_OS9_E4typeEOS7_ Line | Count | Source | 187 | 13.4k | { | 188 | 13.4k | using U = | 189 | 13.4k | typename std::remove_reference<T>::type; | 190 | 13.4k | static_assert( | 191 | 13.4k | is_pilfer_constructible<U>::value, ""); | 192 | 13.4k | return typename std::conditional< | 193 | 13.4k | std::is_nothrow_constructible< | 194 | 13.4k | U, pilfered<U> >::value && | 195 | 13.4k | ! std::is_nothrow_constructible< | 196 | 13.4k | U, detail_pilfer::not_pilfered<U> >::value, | 197 | 13.4k | pilfered<U>, U&& | 198 | 13.4k | >::type(std::move(t)); | 199 | 13.4k | } |
|
200 | | |
201 | | /* |
202 | | template<class T> |
203 | | void |
204 | | relocate(T* dest, T& src) noexcept |
205 | | { |
206 | | static_assert( |
207 | | is_pilfer_constructible<T>::value, ""); |
208 | | ::new(dest) T(pilfer(src)); |
209 | | src.~T(); |
210 | | } |
211 | | */ |
212 | | |
213 | | } // json |
214 | | } // boost |
215 | | |
216 | | |
217 | | #endif |