1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_PILFER_HPP
10  
#ifndef BOOST_JSON_PILFER_HPP
11  
#define BOOST_JSON_PILFER_HPP
11  
#define BOOST_JSON_PILFER_HPP
12  

12  

13  
#include <boost/core/detail/static_assert.hpp>
13  
#include <boost/core/detail/static_assert.hpp>
14  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/detail/config.hpp>
15  
#include <type_traits>
15  
#include <type_traits>
16  
#include <utility>
16  
#include <utility>
17  

17  

18  
/*
18  
/*
19  
    Implements "pilfering" from P0308R0
19  
    Implements "pilfering" from P0308R0
20  

20  

21  
    @see
21  
    @see
22  
        http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html
22  
        http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html
23  
*/
23  
*/
24  

24  

25  
namespace boost {
25  
namespace boost {
26  
namespace json {
26  
namespace json {
27  

27  

28  
/** Tag wrapper to specify pilfer-construction.
28  
/** Tag wrapper to specify pilfer-construction.
29  

29  

30  
    This wrapper is used to specify a pilfer constructor
30  
    This wrapper is used to specify a pilfer constructor
31  
    overload.
31  
    overload.
32  

32  

33  
    @par Example
33  
    @par Example
34  

34  

35  
    A pilfer constructor accepts a single argument
35  
    A pilfer constructor accepts a single argument
36  
    of type @ref pilfered and throws nothing:
36  
    of type @ref pilfered and throws nothing:
37  

37  

38  
    @code
38  
    @code
39  
    struct T
39  
    struct T
40  
    {
40  
    {
41  
        T( pilfered<T> ) noexcept;
41  
        T( pilfered<T> ) noexcept;
42  
    };
42  
    };
43  
    @endcode
43  
    @endcode
44  

44  

45  
    @note
45  
    @note
46  

46  

47  
    The constructor should not be marked explicit.
47  
    The constructor should not be marked explicit.
48  

48  

49  
    @see @ref pilfer, @ref is_pilfer_constructible,
49  
    @see @ref pilfer, @ref is_pilfer_constructible,
50  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
50  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
51  
        Valueless Variants Considered Harmful</a>
51  
        Valueless Variants Considered Harmful</a>
52  
*/
52  
*/
53  
template<class T>
53  
template<class T>
54  
class pilfered
54  
class pilfered
55  
{
55  
{
56  
    T& t_;
56  
    T& t_;
57  

57  

58  
public:
58  
public:
59  
    /** Constructor
59  
    /** Constructor
60  

60  

61  
        Construct the wrapper from `t`.
61  
        Construct the wrapper from `t`.
62  

62  

63  
        @param t The pilferable object. Ownership
63  
        @param t The pilferable object. Ownership
64  
        is not transferred.
64  
        is not transferred.
65  
    */
65  
    */
66  
    explicit
66  
    explicit
67  
    constexpr
67  
    constexpr
68  
    pilfered(T&& t) noexcept
68  
    pilfered(T&& t) noexcept
69  
        : t_(t)
69  
        : t_(t)
70  
    {
70  
    {
71  
    }
71  
    }
72  

72  

73  
    /** Return a reference to the pilferable object.
73  
    /** Return a reference to the pilferable object.
74  

74  

75  
        This returns a reference to the wrapped object.
75  
        This returns a reference to the wrapped object.
76  
    */
76  
    */
77  
    constexpr T&
77  
    constexpr T&
78  
    get() const noexcept
78  
    get() const noexcept
79  
    {
79  
    {
80  
        return t_;
80  
        return t_;
81  
    }
81  
    }
82  

82  

83  
    /** Return a pointer to the pilferable object.
83  
    /** Return a pointer to the pilferable object.
84  

84  

85  
        This returns a pointer to the wrapped object.
85  
        This returns a pointer to the wrapped object.
86  
    */
86  
    */
87  
    constexpr T*
87  
    constexpr T*
88  
    operator->() const noexcept
88  
    operator->() const noexcept
89  
    {
89  
    {
90  
        //return std::addressof(t_);
90  
        //return std::addressof(t_);
91  
        return reinterpret_cast<T*>(
91  
        return reinterpret_cast<T*>(
92  
            const_cast<char *>(
92  
            const_cast<char *>(
93  
                &reinterpret_cast<
93  
                &reinterpret_cast<
94  
                    const volatile char &>(t_)));
94  
                    const volatile char &>(t_)));
95  
    }
95  
    }
96  
};
96  
};
97  

97  

98  
#ifndef BOOST_JSON_DOCS
98  
#ifndef BOOST_JSON_DOCS
99  
// VFALCO Renamed this to work around an msvc bug
99  
// VFALCO Renamed this to work around an msvc bug
100  
namespace detail_pilfer {
100  
namespace detail_pilfer {
101  
template<class>
101  
template<class>
102  
struct not_pilfered
102  
struct not_pilfered
103  
{
103  
{
104  
};
104  
};
105  
} // detail_pilfer
105  
} // detail_pilfer
106  
#endif
106  
#endif
107  

107  

108  
/** Metafunction returning `true` if `T` is <em>PilferConstructible</em>
108  
/** Metafunction returning `true` if `T` is <em>PilferConstructible</em>
109  

109  

110  
    If `T` can be pilfer constructed, this metafunction is
110  
    If `T` can be pilfer constructed, this metafunction is
111  
    equal to `std::true_type`. Otherwise it is equal to
111  
    equal to `std::true_type`. Otherwise it is equal to
112  
    `std::false_type`.
112  
    `std::false_type`.
113  

113  

114  
    @see @ref pilfer, @ref pilfered,
114  
    @see @ref pilfer, @ref pilfered,
115  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
115  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
116  
        Valueless Variants Considered Harmful</a>
116  
        Valueless Variants Considered Harmful</a>
117  
*/
117  
*/
118  
template<class T>
118  
template<class T>
119  
struct is_pilfer_constructible
119  
struct is_pilfer_constructible
120  
#ifndef BOOST_JSON_DOCS
120  
#ifndef BOOST_JSON_DOCS
121  
    : std::integral_constant<bool,
121  
    : std::integral_constant<bool,
122  
        std::is_nothrow_move_constructible<T>::value ||
122  
        std::is_nothrow_move_constructible<T>::value ||
123  
        (
123  
        (
124  
            std::is_nothrow_constructible<
124  
            std::is_nothrow_constructible<
125  
                T, pilfered<T> >::value &&
125  
                T, pilfered<T> >::value &&
126  
            ! std::is_nothrow_constructible<
126  
            ! std::is_nothrow_constructible<
127  
                T, detail_pilfer::not_pilfered<T> >::value
127  
                T, detail_pilfer::not_pilfered<T> >::value
128  
        )>
128  
        )>
129  
#endif
129  
#endif
130  
{
130  
{
131  
};
131  
};
132  

132  

133  
/** Indicate that an object `t` may be pilfered from.
133  
/** Indicate that an object `t` may be pilfered from.
134  

134  

135  
    A <em>pilfer</em> operation is the construction
135  
    A <em>pilfer</em> operation is the construction
136  
    of a new object of type `T` from an existing
136  
    of a new object of type `T` from an existing
137  
    object `t`. After the construction, the only
137  
    object `t`. After the construction, the only
138  
    valid operation on the pilfered-from object is
138  
    valid operation on the pilfered-from object is
139  
    destruction. This permits optimizations beyond
139  
    destruction. This permits optimizations beyond
140  
    those available for a move-construction, as the
140  
    those available for a move-construction, as the
141  
    pilfered-from object is not required to be in
141  
    pilfered-from object is not required to be in
142  
    a "usable" state.
142  
    a "usable" state.
143  
\n
143  
\n
144  
    This is used similarly to `std::move`.
144  
    This is used similarly to `std::move`.
145  

145  

146  
    @par Example
146  
    @par Example
147  

147  

148  
    A pilfer constructor accepts a single argument
148  
    A pilfer constructor accepts a single argument
149  
    of type @ref pilfered and throws nothing:
149  
    of type @ref pilfered and throws nothing:
150  

150  

151  
    @code
151  
    @code
152  
    struct T
152  
    struct T
153  
    {
153  
    {
154  
        T( pilfered<T> ) noexcept;
154  
        T( pilfered<T> ) noexcept;
155  
    };
155  
    };
156  
    @endcode
156  
    @endcode
157  

157  

158  
    Pilfer construction is performed using @ref pilfer :
158  
    Pilfer construction is performed using @ref pilfer :
159  

159  

160  
    @code
160  
    @code
161  
    {
161  
    {
162  
        T t1;                       // default construction
162  
        T t1;                       // default construction
163  
        T t2( pilfer( t1 ) );       // pilfer-construct from t1
163  
        T t2( pilfer( t1 ) );       // pilfer-construct from t1
164  

164  

165  
        // At this point, t1 may only be destroyed
165  
        // At this point, t1 may only be destroyed
166  
    }
166  
    }
167  
    @endcode
167  
    @endcode
168  

168  

169  
    @see @ref pilfered, @ref is_pilfer_constructible,
169  
    @see @ref pilfered, @ref is_pilfer_constructible,
170  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
170  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
171  
        Valueless Variants Considered Harmful</a>
171  
        Valueless Variants Considered Harmful</a>
172  
*/
172  
*/
173  
template<class T>
173  
template<class T>
174  
auto
174  
auto
175  
pilfer(T&& t) noexcept ->
175  
pilfer(T&& t) noexcept ->
176  
    typename std::conditional<
176  
    typename std::conditional<
177  
        std::is_nothrow_constructible<
177  
        std::is_nothrow_constructible<
178  
            typename std::remove_reference<T>::type,
178  
            typename std::remove_reference<T>::type,
179  
            pilfered<typename
179  
            pilfered<typename
180  
                std::remove_reference<T>::type> >::value &&
180  
                std::remove_reference<T>::type> >::value &&
181  
        ! std::is_nothrow_constructible<
181  
        ! std::is_nothrow_constructible<
182  
            typename std::remove_reference<T>::type,
182  
            typename std::remove_reference<T>::type,
183  
            detail_pilfer::not_pilfered<typename
183  
            detail_pilfer::not_pilfered<typename
184  
                std::remove_reference<T>::type> >::value,
184  
                std::remove_reference<T>::type> >::value,
185  
        pilfered<typename std::remove_reference<T>::type>,
185  
        pilfered<typename std::remove_reference<T>::type>,
186  
        typename std::remove_reference<T>::type&&
186  
        typename std::remove_reference<T>::type&&
187  
            >::type
187  
            >::type
188  
{
188  
{
189  
    using U =
189  
    using U =
190  
        typename std::remove_reference<T>::type;
190  
        typename std::remove_reference<T>::type;
191  
    BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<U>::value );
191  
    BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<U>::value );
192  
    return typename std::conditional<
192  
    return typename std::conditional<
193  
        std::is_nothrow_constructible<
193  
        std::is_nothrow_constructible<
194  
            U, pilfered<U> >::value &&
194  
            U, pilfered<U> >::value &&
195  
        ! std::is_nothrow_constructible<
195  
        ! std::is_nothrow_constructible<
196  
            U, detail_pilfer::not_pilfered<U> >::value,
196  
            U, detail_pilfer::not_pilfered<U> >::value,
197  
        pilfered<U>, U&&
197  
        pilfered<U>, U&&
198  
            >::type(std::move(t));
198  
            >::type(std::move(t));
199  
}
199  
}
200  

200  

201  
/*
201  
/*
202  
template<class T>
202  
template<class T>
203  
void
203  
void
204  
relocate(T* dest, T& src) noexcept
204  
relocate(T* dest, T& src) noexcept
205  
{
205  
{
206  
    BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<T>::value );
206  
    BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<T>::value );
207  
    ::new(dest) T(pilfer(src));
207  
    ::new(dest) T(pilfer(src));
208  
    src.~T();
208  
    src.~T();
209  
}
209  
}
210  
*/
210  
*/
211  

211  

212  
} // json
212  
} // json
213  
} // boost
213  
} // boost
214  

214  

215  

215  

216  
#endif
216  
#endif