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