Line data Source code
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 2174037 : pilfered(T&& t) noexcept
68 2174037 : : t_(t)
69 : {
70 2174037 : }
71 :
72 : /** Return a reference to the pilferable object.
73 :
74 : This returns a reference to the wrapped object.
75 : */
76 : constexpr T&
77 4316568 : get() const noexcept
78 : {
79 4316568 : return t_;
80 : }
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 6327165 : 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 : {
188 : using U =
189 : typename std::remove_reference<T>::type;
190 : static_assert(
191 : is_pilfer_constructible<U>::value, "");
192 : return typename std::conditional<
193 : std::is_nothrow_constructible<
194 : U, pilfered<U> >::value &&
195 : ! std::is_nothrow_constructible<
196 : U, detail_pilfer::not_pilfered<U> >::value,
197 : pilfered<U>, U&&
198 6327165 : >::type(std::move(t));
199 : }
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
|