100.00% Lines (68/68) 100.00% Functions (20/20)
TLA Baseline Branch
Line Hits Code Line Hits Code
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_STORAGE_PTR_HPP 10   #ifndef BOOST_JSON_STORAGE_PTR_HPP
11   #define BOOST_JSON_STORAGE_PTR_HPP 11   #define BOOST_JSON_STORAGE_PTR_HPP
12   12  
13   #include <boost/core/detail/static_assert.hpp> 13   #include <boost/core/detail/static_assert.hpp>
14   #include <boost/container/pmr/polymorphic_allocator.hpp> 14   #include <boost/container/pmr/polymorphic_allocator.hpp>
15   #include <boost/json/detail/config.hpp> 15   #include <boost/json/detail/config.hpp>
16   #include <boost/json/detail/shared_resource.hpp> 16   #include <boost/json/detail/shared_resource.hpp>
17   #include <boost/json/detail/default_resource.hpp> 17   #include <boost/json/detail/default_resource.hpp>
18   #include <boost/json/is_deallocate_trivial.hpp> 18   #include <boost/json/is_deallocate_trivial.hpp>
19   #include <new> 19   #include <new>
20   #include <type_traits> 20   #include <type_traits>
21   #include <utility> 21   #include <utility>
22   22  
23   namespace boost { 23   namespace boost {
24   namespace json { 24   namespace json {
25   25  
26   /** A smart pointer to a memory resource. 26   /** A smart pointer to a memory resource.
27   27  
28   This class is used to hold a pointer to a memory resource. The pointed-to 28   This class is used to hold a pointer to a memory resource. The pointed-to
29   resource is always valid. Depending on the means of construction, the 29   resource is always valid. Depending on the means of construction, the
30   ownership will be either: 30   ownership will be either:
31   31  
32   @li Non-owning, when constructing from a raw pointer to 32   @li Non-owning, when constructing from a raw pointer to
33   @ref boost::container::pmr::memory_resource or from a 33   @ref boost::container::pmr::memory_resource or from a
34   @ref boost::container::pmr::polymorphic_allocator. In this case the caller 34   @ref boost::container::pmr::polymorphic_allocator. In this case the caller
35   is responsible for ensuring that the lifetime of the memory resource 35   is responsible for ensuring that the lifetime of the memory resource
36   extends until there are no more calls to allocate or deallocate. 36   extends until there are no more calls to allocate or deallocate.
37   37  
38   @li Owning, when constructing using the function @ref make_shared_resource. 38   @li Owning, when constructing using the function @ref make_shared_resource.
39   In this case ownership is shared; the lifetime of the memory resource 39   In this case ownership is shared; the lifetime of the memory resource
40   extends until the last copy of the `storage_ptr` is destroyed. 40   extends until the last copy of the `storage_ptr` is destroyed.
41   41  
42   @par Examples 42   @par Examples
43   These statements create a memory resource on the stack and construct 43   These statements create a memory resource on the stack and construct
44   a pointer from it without taking ownership: 44   a pointer from it without taking ownership:
45   45  
46   @code 46   @code
47   monotonic_resource mr; // Create our memory resource on the stack 47   monotonic_resource mr; // Create our memory resource on the stack
48   storage_ptr sp( &mr ); // Construct a non-owning pointer to the resource 48   storage_ptr sp( &mr ); // Construct a non-owning pointer to the resource
49   @endcode 49   @endcode
50   50  
51   This function creates a pointer to a memory resource using shared ownership 51   This function creates a pointer to a memory resource using shared ownership
52   and returns it. The lifetime of the memory resource extends until the last 52   and returns it. The lifetime of the memory resource extends until the last
53   copy of the pointer is destroyed: 53   copy of the pointer is destroyed:
54   54  
55   @code 55   @code
56   // Create a counted memory resource and return it 56   // Create a counted memory resource and return it
57   storage_ptr make_storage() 57   storage_ptr make_storage()
58   { 58   {
59   return make_shared_resource< monotonic_resource >(); 59   return make_shared_resource< monotonic_resource >();
60   } 60   }
61   @endcode 61   @endcode
62   62  
63   @par Thread Safety 63   @par Thread Safety
64   Instances of this type provide the default level of thread safety for all 64   Instances of this type provide the default level of thread safety for all
65   C++ objects. Specifically, it conforms to 65   C++ objects. Specifically, it conforms to
66   [16.4.6.10 Data race avoidance](http://eel.is/c++draft/res.on.data.races). 66   [16.4.6.10 Data race avoidance](http://eel.is/c++draft/res.on.data.races).
67   67  
68   @see 68   @see
69   @ref make_shared_resource, 69   @ref make_shared_resource,
70   @ref boost::container::pmr::polymorphic_allocator, 70   @ref boost::container::pmr::polymorphic_allocator,
71   @ref boost::container::pmr::memory_resource. 71   @ref boost::container::pmr::memory_resource.
72   72  
73   */ 73   */
74   class storage_ptr 74   class storage_ptr
75   { 75   {
76   #ifndef BOOST_JSON_DOCS 76   #ifndef BOOST_JSON_DOCS
77   // VFALCO doc toolchain shows this when it shouldn't 77   // VFALCO doc toolchain shows this when it shouldn't
78   friend struct detail::shared_resource; 78   friend struct detail::shared_resource;
79   #endif 79   #endif
80   using shared_resource = 80   using shared_resource =
81   detail::shared_resource; 81   detail::shared_resource;
82   82  
83   using default_resource = 83   using default_resource =
84   detail::default_resource; 84   detail::default_resource;
85   85  
86   std::uintptr_t i_; 86   std::uintptr_t i_;
87   87  
88   shared_resource* 88   shared_resource*
HITCBC 89   302 get_shared() const noexcept 89   302 get_shared() const noexcept
90   { 90   {
91   return static_cast<shared_resource*>( 91   return static_cast<shared_resource*>(
92   reinterpret_cast<container::pmr::memory_resource*>( 92   reinterpret_cast<container::pmr::memory_resource*>(
HITCBC 93   302 i_ & ~3)); 93   302 i_ & ~3));
94   } 94   }
95   95  
96   void 96   void
HITCBC 97   6352730 addref() const noexcept 97   6352730 addref() const noexcept
98   { 98   {
HITCBC 99   6352730 if(is_shared()) 99   6352730 if(is_shared())
HITCBC 100   141 get_shared()->refs.fetch_add( 100   141 get_shared()->refs.fetch_add(
101   1, std::memory_order_relaxed); 101   1, std::memory_order_relaxed);
HITCBC 102   6352730 } 102   6352730 }
103   103  
104   void 104   void
HITCBC 105   43990763 release() const noexcept 105   43990763 release() const noexcept
106   { 106   {
HITCBC 107   43990763 if(is_shared()) 107   43990763 if(is_shared())
108   { 108   {
HITCBC 109   161 auto const p = get_shared(); 109   161 auto const p = get_shared();
HITCBC 110   161 if(p->refs.fetch_sub(1, 110   161 if(p->refs.fetch_sub(1,
HITCBC 111   161 std::memory_order_acq_rel) == 1) 111   161 std::memory_order_acq_rel) == 1)
HITCBC 112   20 delete p; 112   20 delete p;
113   } 113   }
HITCBC 114   43990763 } 114   43990763 }
115   115  
116   template<class T> 116   template<class T>
HITCBC 117   20 storage_ptr( 117   20 storage_ptr(
118   detail::shared_resource_impl<T>* p) noexcept 118   detail::shared_resource_impl<T>* p) noexcept
HITCBC 119   20 : i_(reinterpret_cast<std::uintptr_t>( 119   20 : i_(reinterpret_cast<std::uintptr_t>(
HITCBC 120   20 static_cast<container::pmr::memory_resource*>(p)) + 1 + 120   20 static_cast<container::pmr::memory_resource*>(p)) + 1 +
121   (json::is_deallocate_trivial<T>::value ? 2 : 0)) 121   (json::is_deallocate_trivial<T>::value ? 2 : 0))
122   { 122   {
HITCBC 123   20 BOOST_ASSERT(p); 123   20 BOOST_ASSERT(p);
HITCBC 124   20 } 124   20 }
125   125  
126   public: 126   public:
127   /** Destructor. 127   /** Destructor.
128   128  
129   If the pointer has shared ownership of the resource, the shared 129   If the pointer has shared ownership of the resource, the shared
130   ownership is released. If this is the last owned copy, the memory 130   ownership is released. If this is the last owned copy, the memory
131   resource is destroyed. 131   resource is destroyed.
132   132  
133   @par Complexity 133   @par Complexity
134   Constant. 134   Constant.
135   135  
136   @par Exception Safety 136   @par Exception Safety
137   No-throw guarantee. 137   No-throw guarantee.
138   */ 138   */
HITCBC 139   41914113 ~storage_ptr() noexcept 139   41914113 ~storage_ptr() noexcept
140   { 140   {
HITCBC 141   41914113 release(); 141   41914113 release();
HITCBC 142   41914113 } 142   41914113 }
143   143  
144   /** Constructors. 144   /** Constructors.
145   145  
146   @li **(1)** constructs a non-owning pointer that refers to the 146   @li **(1)** constructs a non-owning pointer that refers to the
147   \<\<default_memory_resource,default memory resource\>\>. 147   \<\<default_memory_resource,default memory resource\>\>.
148   148  
149   @li **(2)** constructs a non-owning pointer that points to the memory 149   @li **(2)** constructs a non-owning pointer that points to the memory
150   resource `r`. 150   resource `r`.
151   151  
152   @li **(3)** constructs a non-owning pointer that points to the same 152   @li **(3)** constructs a non-owning pointer that points to the same
153   memory resource as `alloc`, obtained by calling `alloc.resource()`. 153   memory resource as `alloc`, obtained by calling `alloc.resource()`.
154   154  
155   @li **(4)**, **(5)** construct a pointer to the same memory resource as 155   @li **(4)**, **(5)** construct a pointer to the same memory resource as
156   `other`, with the same ownership. 156   `other`, with the same ownership.
157   157  
158   After **(4)** and **(5)** if `other` was owning, then the constructed 158   After **(4)** and **(5)** if `other` was owning, then the constructed
159   pointer is also owning. In particular, **(4)** transfers ownership to 159   pointer is also owning. In particular, **(4)** transfers ownership to
160   the constructed pointer while **(5)** causes it to share ownership with 160   the constructed pointer while **(5)** causes it to share ownership with
161   `other`. Otherwise, and with other overloads the constructed pointer 161   `other`. Otherwise, and with other overloads the constructed pointer
162   doesn't own its memory resource and the caller is responsible for 162   doesn't own its memory resource and the caller is responsible for
163   maintaining the lifetime of the pointed-to 163   maintaining the lifetime of the pointed-to
164   @ref boost::container::pmr::memory_resource. 164   @ref boost::container::pmr::memory_resource.
165   165  
166   After **(4)**, `other` will point to the default memory resource. 166   After **(4)**, `other` will point to the default memory resource.
167   167  
168   @par Constraints 168   @par Constraints
169   @code 169   @code
170   std::is_convertible< T*, boost::container::pmr::memory_resource* >::value == true 170   std::is_convertible< T*, boost::container::pmr::memory_resource* >::value == true
171   @endcode 171   @endcode
172   172  
173   @pre 173   @pre
174   @code 174   @code
175   r != nullptr 175   r != nullptr
176   @endcode 176   @endcode
177   177  
178   @par Complexity 178   @par Complexity
179   Constant. 179   Constant.
180   180  
181   @par Exception Safety 181   @par Exception Safety
182   No-throw guarantee. 182   No-throw guarantee.
183   183  
184   @{ 184   @{
185   */ 185   */
HITCBC 186   14653478 storage_ptr() noexcept 186   14653478 storage_ptr() noexcept
HITCBC 187   14653478 : i_(0) 187   14653478 : i_(0)
188   { 188   {
HITCBC 189   14653478 } 189   14653478 }
190   190  
191   /** Overload 191   /** Overload
192   192  
193   @tparam T The type of memory resource. 193   @tparam T The type of memory resource.
194   @param r A non-null pointer to the memory resource to use. 194   @param r A non-null pointer to the memory resource to use.
195   */ 195   */
196   template<class T 196   template<class T
197   #ifndef BOOST_JSON_DOCS 197   #ifndef BOOST_JSON_DOCS
198   , class = typename std::enable_if< 198   , class = typename std::enable_if<
199   std::is_convertible<T*, 199   std::is_convertible<T*,
200   container::pmr::memory_resource*>::value>::type 200   container::pmr::memory_resource*>::value>::type
201   #endif 201   #endif
202   > 202   >
HITCBC 203   57222 storage_ptr(T* r) noexcept 203   57222 storage_ptr(T* r) noexcept
HITCBC 204   57222 : i_(reinterpret_cast<std::uintptr_t>( 204   57222 : i_(reinterpret_cast<std::uintptr_t>(
HITCBC 205   18 static_cast<container::pmr::memory_resource *>(r)) + 205   18 static_cast<container::pmr::memory_resource *>(r)) +
206   (json::is_deallocate_trivial<T>::value ? 2 : 0)) 206   (json::is_deallocate_trivial<T>::value ? 2 : 0))
207   { 207   {
HITCBC 208   57222 BOOST_ASSERT(r); 208   57222 BOOST_ASSERT(r);
HITCBC 209   57222 } 209   57222 }
210   210  
211   /** Overload 211   /** Overload
212   212  
213   @tparam V Any type. 213   @tparam V Any type.
214   @param alloc A @ref boost::container::pmr::polymorphic_allocator to 214   @param alloc A @ref boost::container::pmr::polymorphic_allocator to
215   construct from. 215   construct from.
216   */ 216   */
217   template<class V> 217   template<class V>
HITCBC 218   10 storage_ptr( 218   10 storage_ptr(
219   container::pmr::polymorphic_allocator<V> const& alloc) noexcept 219   container::pmr::polymorphic_allocator<V> const& alloc) noexcept
HITCBC 220   10 : i_(reinterpret_cast<std::uintptr_t>( 220   10 : i_(reinterpret_cast<std::uintptr_t>(
HITCBC 221   10 alloc.resource())) 221   10 alloc.resource()))
222   { 222   {
HITCBC 223   10 } 223   10 }
224   224  
225   /** Overload 225   /** Overload
226   226  
227   @param other Another pointer. 227   @param other Another pointer.
228   */ 228   */
HITCBC 229   22965882 storage_ptr( 229   22965882 storage_ptr(
230   storage_ptr&& other) noexcept 230   storage_ptr&& other) noexcept
HITCBC 231   22965882 : i_(detail::exchange(other.i_, 0)) 231   22965882 : i_(detail::exchange(other.i_, 0))
232   { 232   {
HITCBC 233   22965882 } 233   22965882 }
234   234  
235   /** Overload 235   /** Overload
236   236  
237   @param other 237   @param other
238   */ 238   */
HITCBC 239   6352729 storage_ptr( 239   6352729 storage_ptr(
240   storage_ptr const& other) noexcept 240   storage_ptr const& other) noexcept
HITCBC 241   6352729 : i_(other.i_) 241   6352729 : i_(other.i_)
242   { 242   {
HITCBC 243   6352729 addref(); 243   6352729 addref();
HITCBC 244   6352729 } 244   6352729 }
245   /// @} 245   /// @}
246   246  
247   /** Assignment operators. 247   /** Assignment operators.
248   248  
249   This function assigns a pointer that points to the same memory resource 249   This function assigns a pointer that points to the same memory resource
250   as `other`, with the same ownership: 250   as `other`, with the same ownership:
251   251  
252   @li If `other` is non-owning, then the assigned-to pointer will be be 252   @li If `other` is non-owning, then the assigned-to pointer will be be
253   non-owning. 253   non-owning.
254   254  
255   @li If `other` has shared ownership, then **(1)** transfers ownership 255   @li If `other` has shared ownership, then **(1)** transfers ownership
256   to the assigned-to pointer, while after **(2)** it shares the ownership 256   to the assigned-to pointer, while after **(2)** it shares the ownership
257   with `other`. 257   with `other`.
258   258  
259   If the assigned-to pointer previously had shared ownership, it is 259   If the assigned-to pointer previously had shared ownership, it is
260   released before the function returns. 260   released before the function returns.
261   261  
262   After **(1)**, `other` will point to the 262   After **(1)**, `other` will point to the
263   \<\<default_memory_resource,default memory resource\>\>. 263   \<\<default_memory_resource,default memory resource\>\>.
264   264  
265   @par Complexity 265   @par Complexity
266   Constant. 266   Constant.
267   267  
268   @par Exception Safety 268   @par Exception Safety
269   No-throw guarantee. 269   No-throw guarantee.
270   270  
271   @param other Another pointer. 271   @param other Another pointer.
272   272  
273   @{ 273   @{
274   */ 274   */
275   storage_ptr& 275   storage_ptr&
HITCBC 276   2076649 operator=( 276   2076649 operator=(
277   storage_ptr&& other) noexcept 277   storage_ptr&& other) noexcept
278   { 278   {
HITCBC 279   2076649 release(); 279   2076649 release();
HITCBC 280   2076649 i_ = detail::exchange(other.i_, 0); 280   2076649 i_ = detail::exchange(other.i_, 0);
HITCBC 281   2076649 return *this; 281   2076649 return *this;
282   } 282   }
283   283  
284   storage_ptr& 284   storage_ptr&
HITCBC 285   1 operator=( 285   1 operator=(
286   storage_ptr const& other) noexcept 286   storage_ptr const& other) noexcept
287   { 287   {
HITCBC 288   1 other.addref(); 288   1 other.addref();
HITCBC 289   1 release(); 289   1 release();
HITCBC 290   1 i_ = other.i_; 290   1 i_ = other.i_;
HITCBC 291   1 return *this; 291   1 return *this;
292   } 292   }
293   /// @} 293   /// @}
294   294  
295   /** Check if ownership of the memory resource is shared. 295   /** Check if ownership of the memory resource is shared.
296   296  
297   This function returns true for memory resources created using @ref 297   This function returns true for memory resources created using @ref
298   make_shared_resource. 298   make_shared_resource.
299   */ 299   */
300   bool 300   bool
HITCBC 301   50343494 is_shared() const noexcept 301   50343494 is_shared() const noexcept
302   { 302   {
HITCBC 303   50343494 return (i_ & 1) != 0; 303   50343494 return (i_ & 1) != 0;
304   } 304   }
305   305  
306   /** Check if calling `deallocate` on the memory resource has no effect. 306   /** Check if calling `deallocate` on the memory resource has no effect.
307   307  
308   This function is used to determine if the deallocate function of the 308   This function is used to determine if the deallocate function of the
309   pointed to memory resource is trivial. The value of @ref 309   pointed to memory resource is trivial. The value of @ref
310   is_deallocate_trivial is evaluated and saved when the memory resource 310   is_deallocate_trivial is evaluated and saved when the memory resource
311   is constructed and the type is known, before the type is erased. 311   is constructed and the type is known, before the type is erased.
312   */ 312   */
313   bool 313   bool
HITCBC 314   1 is_deallocate_trivial() const noexcept 314   1 is_deallocate_trivial() const noexcept
315   { 315   {
HITCBC 316   1 return (i_ & 2) != 0; 316   1 return (i_ & 2) != 0;
317   } 317   }
318   318  
319   /** Check if ownership of the memory resource is not shared and deallocate is trivial. 319   /** Check if ownership of the memory resource is not shared and deallocate is trivial.
320   320  
321   This function is used to determine if calls to deallocate can 321   This function is used to determine if calls to deallocate can
322   effectively be skipped. Equivalent to `! is_shared() && 322   effectively be skipped. Equivalent to `! is_shared() &&
323   is_deallocate_trivial()`. 323   is_deallocate_trivial()`.
324   */ 324   */
325   bool 325   bool
HITCBC 326   4323577 is_not_shared_and_deallocate_is_trivial() const noexcept 326   4323577 is_not_shared_and_deallocate_is_trivial() const noexcept
327   { 327   {
HITCBC 328   4323577 return (i_ & 3) == 2; 328   4323577 return (i_ & 3) == 2;
329   } 329   }
330   330  
331   /** Return a pointer to the memory resource. 331   /** Return a pointer to the memory resource.
332   332  
333   This function returns a pointer to the 333   This function returns a pointer to the
334   referenced @ref boost::container::pmr::memory_resource. 334   referenced @ref boost::container::pmr::memory_resource.
335   335  
336   @par Complexity 336   @par Complexity
337   Constant. 337   Constant.
338   338  
339   @par Exception Safety 339   @par Exception Safety
340   No-throw guarantee. 340   No-throw guarantee.
341   */ 341   */
342   container::pmr::memory_resource* 342   container::pmr::memory_resource*
HITCBC 343   653431 get() const noexcept 343   653431 get() const noexcept
344   { 344   {
HITCBC 345   653431 if(i_ != 0) 345   653431 if(i_ != 0)
346   return reinterpret_cast< 346   return reinterpret_cast<
HITCBC 347   122583 container::pmr::memory_resource*>(i_ & ~3); 347   122583 container::pmr::memory_resource*>(i_ & ~3);
HITCBC 348   530848 return default_resource::get(); 348   530848 return default_resource::get();
349   } 349   }
350   350  
351   /** Return a pointer to the memory resource. 351   /** Return a pointer to the memory resource.
352   352  
353   This function returns a pointer to the referenced @ref 353   This function returns a pointer to the referenced @ref
354   boost::container::pmr::memory_resource. 354   boost::container::pmr::memory_resource.
355   355  
356   @par Complexity 356   @par Complexity
357   Constant. 357   Constant.
358   358  
359   @par Exception Safety 359   @par Exception Safety
360   No-throw guarantee. 360   No-throw guarantee.
361   */ 361   */
362   container::pmr::memory_resource* 362   container::pmr::memory_resource*
HITCBC 363   649785 operator->() const noexcept 363   649785 operator->() const noexcept
364   { 364   {
HITCBC 365   649785 return get(); 365   649785 return get();
366   } 366   }
367   367  
368   /** Return a reference to the memory resource. 368   /** Return a reference to the memory resource.
369   369  
370   This function returns a reference to the pointed-to @ref 370   This function returns a reference to the pointed-to @ref
371   boost::container::pmr::memory_resource. 371   boost::container::pmr::memory_resource.
372   372  
373   @par Complexity 373   @par Complexity
374   374  
375   Constant. 375   Constant.
376   376  
377   @par Exception Safety 377   @par Exception Safety
378   378  
379   No-throw guarantee. 379   No-throw guarantee.
380   */ 380   */
381   container::pmr::memory_resource& 381   container::pmr::memory_resource&
HITCBC 382   3614 operator*() const noexcept 382   3614 operator*() const noexcept
383   { 383   {
HITCBC 384   3614 return *get(); 384   3614 return *get();
385   } 385   }
386   386  
387   template<class U, class... Args> 387   template<class U, class... Args>
388   friend 388   friend
389   storage_ptr 389   storage_ptr
390   make_shared_resource(Args&&... args); 390   make_shared_resource(Args&&... args);
391   }; 391   };
392   392  
393   #if defined(_MSC_VER) 393   #if defined(_MSC_VER)
394   # pragma warning( push ) 394   # pragma warning( push )
395   # if !defined(__clang__) && _MSC_VER <= 1900 395   # if !defined(__clang__) && _MSC_VER <= 1900
396   # pragma warning( disable : 4702 ) 396   # pragma warning( disable : 4702 )
397   # endif 397   # endif
398   #endif 398   #endif
399   399  
400   /** Return a pointer that owns a new, dynamically allocated memory resource. 400   /** Return a pointer that owns a new, dynamically allocated memory resource.
401   401  
402   This function dynamically allocates a new memory resource as if by 402   This function dynamically allocates a new memory resource as if by
403   `operator new` that uses shared ownership. The lifetime of the memory 403   `operator new` that uses shared ownership. The lifetime of the memory
404   resource will be extended until the last @ref storage_ptr which points to 404   resource will be extended until the last @ref storage_ptr which points to
405   it is destroyed. 405   it is destroyed.
406   406  
407   @par Constraints 407   @par Constraints
408   @code 408   @code
409   std::is_base_of< boost::container::pmr::memory_resource, U >::value == true 409   std::is_base_of< boost::container::pmr::memory_resource, U >::value == true
410   @endcode 410   @endcode
411   411  
412   @par Complexity 412   @par Complexity
413   Same as `new U( std::forward<Args>(args)... )`. 413   Same as `new U( std::forward<Args>(args)... )`.
414   414  
415   @par Exception Safety 415   @par Exception Safety
416   Strong guarantee. 416   Strong guarantee.
417   417  
418   @tparam U The type of memory resource to create. 418   @tparam U The type of memory resource to create.
419   419  
420   @param args Parameters forwarded to the constructor of `U`. 420   @param args Parameters forwarded to the constructor of `U`.
421   */ 421   */
422   template<class U, class... Args> 422   template<class U, class... Args>
423   storage_ptr 423   storage_ptr
HITCBC 424   21 make_shared_resource(Args&&... args) 424   21 make_shared_resource(Args&&... args)
425   { 425   {
426   // If this generates an error, it means that 426   // If this generates an error, it means that
427   // `T` is not a memory resource. 427   // `T` is not a memory resource.
428   BOOST_CORE_STATIC_ASSERT(( 428   BOOST_CORE_STATIC_ASSERT((
429   std::is_base_of<container::pmr::memory_resource, U>::value)); 429   std::is_base_of<container::pmr::memory_resource, U>::value));
HITCBC 430   23 return storage_ptr(new 430   23 return storage_ptr(new
431   detail::shared_resource_impl<U>( 431   detail::shared_resource_impl<U>(
HITCBC 432   22 std::forward<Args>(args)...)); 432   22 std::forward<Args>(args)...));
433   } 433   }
434   #if defined(_MSC_VER) 434   #if defined(_MSC_VER)
435   # pragma warning( pop ) 435   # pragma warning( pop )
436   #endif 436   #endif
437   437  
438   /// Overload 438   /// Overload
439   inline 439   inline
440   bool 440   bool
HITCBC 441   5 operator==( 441   5 operator==(
442   storage_ptr const& lhs, 442   storage_ptr const& lhs,
443   storage_ptr const& rhs) noexcept 443   storage_ptr const& rhs) noexcept
444   { 444   {
HITCBC 445   5 return lhs.get() == rhs.get(); 445   5 return lhs.get() == rhs.get();
446   } 446   }
447   447  
448   /// Overload 448   /// Overload
449   inline 449   inline
450   bool 450   bool
451   operator!=( 451   operator!=(
452   storage_ptr const& lhs, 452   storage_ptr const& lhs,
453   storage_ptr const& rhs) noexcept 453   storage_ptr const& rhs) noexcept
454   { 454   {
455   return lhs.get() != rhs.get(); 455   return lhs.get() != rhs.get();
456   } 456   }
457   457  
458   } // namespace json 458   } // namespace json
459   } // namespace boost 459   } // namespace boost
460   460  
461   #endif 461   #endif