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/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 2174306 : pilfered(T&& t) noexcept
69 2174306 : : t_(t)
70 : {
71 2174306 : }
72 :
73 : /** Return a reference to the pilferable object.
74 :
75 : This returns a reference to the wrapped object.
76 : */
77 : constexpr T&
78 4317069 : get() const noexcept
79 : {
80 4317069 : return t_;
81 : }
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 6327460 : 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 : {
189 : using U =
190 : typename std::remove_reference<T>::type;
191 : BOOST_CORE_STATIC_ASSERT( 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 6327460 : >::type(std::move(t));
199 : }
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
|