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