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 -
#include <boost/core/detail/static_assert.hpp>
 
13  

12  

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

16  

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

19  

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

23  

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

26  

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

28  

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

31  

33  
    @par Example
32  
    @par Example
34  

33  

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

36  

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

43  

45  
    @note
44  
    @note
46  

45  

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

47  

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

56  

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

59  

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

61  

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

71  

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

73  

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

81  

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

83  

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

96  

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

106  

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

108  

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

112  

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

131  

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

133  

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

144  

146  
    @par Example
145  
    @par Example
147  

146  

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

149  

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

156  

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

158  

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

163  

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

167  

169  
    @see @ref pilfered, @ref is_pilfer_constructible,
168  
    @see @ref pilfered, @ref is_pilfer_constructible,
170  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
169  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
171  
        Valueless Variants Considered Harmful</a>
170  
        Valueless Variants Considered Harmful</a>
172  
*/
171  
*/
173  
template<class T>
172  
template<class T>
174  
auto
173  
auto
175  
pilfer(T&& t) noexcept ->
174  
pilfer(T&& t) noexcept ->
176  
    typename std::conditional<
175  
    typename std::conditional<
177  
        std::is_nothrow_constructible<
176  
        std::is_nothrow_constructible<
178  
            typename std::remove_reference<T>::type,
177  
            typename std::remove_reference<T>::type,
179  
            pilfered<typename
178  
            pilfered<typename
180  
                std::remove_reference<T>::type> >::value &&
179  
                std::remove_reference<T>::type> >::value &&
181  
        ! std::is_nothrow_constructible<
180  
        ! std::is_nothrow_constructible<
182  
            typename std::remove_reference<T>::type,
181  
            typename std::remove_reference<T>::type,
183  
            detail_pilfer::not_pilfered<typename
182  
            detail_pilfer::not_pilfered<typename
184  
                std::remove_reference<T>::type> >::value,
183  
                std::remove_reference<T>::type> >::value,
185  
        pilfered<typename std::remove_reference<T>::type>,
184  
        pilfered<typename std::remove_reference<T>::type>,
186  
        typename std::remove_reference<T>::type&&
185  
        typename std::remove_reference<T>::type&&
187  
            >::type
186  
            >::type
188  
{
187  
{
189  
    using U =
188  
    using U =
190  
        typename std::remove_reference<T>::type;
189  
        typename std::remove_reference<T>::type;
191 -
    BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<U>::value );
190 +
    static_assert(
 
191 +
        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 +
    static_assert(
 
207 +
        is_pilfer_constructible<T>::value, "");
207  
    ::new(dest) T(pilfer(src));
208  
    ::new(dest) T(pilfer(src));
208  
    src.~T();
209  
    src.~T();
209  
}
210  
}
210  
*/
211  
*/
211  

212  

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

215  

215  

216  

216  
#endif
217  
#endif