6#include <bond/core/config.h>
8#include "container_interface.h"
9#include "detail/alloc.h"
11#include <boost/assert.hpp>
12#include <boost/optional.hpp>
13#include <boost/utility/enable_if.hpp>
24template<
typename T,
typename Enable =
void>
struct
27 using type = std::allocator<T>;
30template<
typename T>
struct
31allocator_type<T, typename boost::enable_if<std::is_class<typename T::allocator_type> >::type>
33 using type =
typename T::allocator_type;
37template <
typename T>
struct
39 : std::integral_constant<bool,
40 is_list_container<T>::value
41 || is_set_container<T>::value
42 || is_map_container<T>::value
43 || is_string<T>::value
44 || is_wstring<T>::value
45 || !std::is_class<T>::value> {};
48BOND_CONSTEXPR
inline T* to_address(T* ptr) BOND_NOEXCEPT
54inline typename std::pointer_traits<Ptr>::element_type*
55to_address(
const Ptr& ptr) BOND_NOEXCEPT
57 return bond::detail::to_address(ptr.operator->());
66template <
typename T,
typename Enable =
void>
70class nullable<T, typename boost::enable_if<detail::use_value<T> >::type>
71 :
private detail::allocator_holder<typename detail::allocator_type<T>::type>
73 using allocator_holder =
typename nullable::allocator_holder;
77 using allocator_type =
typename detail::allocator_type<T>::type;
82 nullable(
const allocator_type& alloc)
83 : allocator_holder(alloc)
86 nullable(
const nullable& other) =
default;
88 nullable(
const nullable& other,
const allocator_type& alloc)
89 : allocator_holder(alloc)
93 _value.emplace(*other._value, alloc);
97 nullable(nullable&& other) BOND_NOEXCEPT_IF(
98 std::is_nothrow_move_constructible<allocator_holder>::value
99 && std::is_nothrow_move_constructible<T>::value)
100 : allocator_holder(
std::move(other)),
101 _value(
std::move(other._value))
103 other._value = boost::none;
106 nullable(nullable&& other,
const allocator_type& alloc)
107 : allocator_holder(alloc),
108 _value(
std::move(other._value), alloc)
110 other._value = boost::none;
114 nullable(
const T& value)
115 : allocator_holder(get_allocator(value)),
121 : allocator_holder(get_allocator(value)),
122 _value(
std::move(value))
125 nullable& operator=(
const nullable& src) =
default;
127 nullable& operator=(nullable&& other) BOND_NOEXCEPT_IF(
128 std::is_nothrow_move_constructible<allocator_holder>::value
129 && std::is_nothrow_move_constructible<T>::value)
131 allocator_holder::operator=(std::move(other));
132 _value = std::move(other._value);
133 other._value = boost::none;
137 bool hasvalue() const BOND_NOEXCEPT
139 return static_cast<bool>(_value);
142 bool empty() const BOND_NOEXCEPT
147 explicit operator bool() const BOND_NOEXCEPT
152 T& value() BOND_NOEXCEPT
154 BOOST_ASSERT(hasvalue());
158 const T& value() const BOND_NOEXCEPT
160 BOOST_ASSERT(hasvalue());
164 T& operator*() BOND_NOEXCEPT
169 const T& operator*() const BOND_NOEXCEPT
174 T* operator->() BOND_NOEXCEPT
179 const T* operator->() const BOND_NOEXCEPT
194 void set(
const T& value) BOND_NOEXCEPT_IF(std::is_nothrow_copy_constructible<T>::value
195 && std::is_nothrow_copy_assignable<T>::value)
200 void set(T&& value) BOND_NOEXCEPT_IF(std::is_nothrow_move_constructible<T>::value
201 && std::is_nothrow_move_assignable<T>::value)
203 _value = std::move(value);
206 void reset() BOND_NOEXCEPT
208 _value = boost::none;
211 void clear() BOND_NOEXCEPT
216 void swap(nullable& other)
219 swap(
static_cast<allocator_holder&
>(*
this),
static_cast<allocator_holder&
>(other));
220 swap(_value, other._value);
223 allocator_type get_allocator() const BOND_NOEXCEPT
225 return allocator_holder::get();
229 template <
typename U = T>
230 typename boost::enable_if<std::uses_allocator<U, allocator_type> >::type
233 _value.emplace(allocator_holder::get());
236 template <
typename U = T>
237 typename boost::disable_if<std::uses_allocator<U, allocator_type> >::type
243 template <
typename U = T>
244 typename boost::enable_if<std::uses_allocator<U, allocator_type>, allocator_type>::type
245 static get_allocator(
const T& value)
247 return value.get_allocator();
250 template <
typename U = T>
251 typename boost::disable_if<std::uses_allocator<U, allocator_type>, allocator_type>::type
252 static get_allocator(
const T& )
254 return allocator_type();
257 boost::optional<T> _value;
264class nullable<T, typename boost::disable_if<detail::use_value<T> >::type>
268 using value_type = T;
269 using allocator_type =
typename detail::allocator_type<T>::type;
272 using allocator_holder =
typename nullable::allocator_holder;
273 using rebind_alloc =
typename std::allocator_traits<allocator_type>::template rebind_alloc<T>;
274 using pointer =
typename std::allocator_traits<rebind_alloc>::pointer;
279 std::is_nothrow_default_constructible<allocator_holder>::value
280 &&
std::is_nothrow_default_constructible<pointer>::value)
281 : allocator_holder(),
288 : allocator_holder(alloc),
294 : allocator_holder(other),
295 _value(other.hasvalue() ? new_value(other.value()) : pointer())
298 nullable(
const nullable& other,
const allocator_type& alloc)
299 : allocator_holder(alloc),
300 _value(other.hasvalue() ? new_value(other.value(), alloc) : pointer())
303 nullable(nullable&& other) BOND_NOEXCEPT_IF(
304 std::is_nothrow_move_constructible<allocator_holder>::value
305 && std::is_nothrow_move_constructible<pointer>::value
306 && BOND_NOEXCEPT(other._value = {}))
307 : allocator_holder(
std::move(other)),
308 _value(
std::move(other._value))
313 nullable(nullable&& other,
const allocator_type& alloc)
314 : allocator_holder(alloc),
315 _value(other.allocator_holder::get() == alloc
316 ?
std::move(other._value)
317 : (other.hasvalue() ? new_value(
std::move(*other._value), alloc) : pointer()))
324 nullable(
const T& value,
const allocator_type& alloc = {})
325 : allocator_holder(alloc),
326 _value(new_value(value))
330 nullable(T&& value,
const allocator_type& alloc = {})
331 : allocator_holder(alloc),
332 _value(new_value(std::move(value)))
338 nullable(other).swap(*
this);
342 nullable& operator=(nullable&& other)
344 nullable(std::move(other)).swap(*
this);
353 bool hasvalue() const BOND_NOEXCEPT
355 return _value != pointer();
364 explicit operator bool() const BOND_NOEXCEPT
374 BOOST_ASSERT(hasvalue());
381 const T&
value() const BOND_NOEXCEPT
383 BOOST_ASSERT(hasvalue());
403 T* operator->() BOND_NOEXCEPT
408 const T* operator->() const BOND_NOEXCEPT
418 _value = set_value();
432 set_value(std::move(value));
451 void swap(nullable& other)
454 swap(
static_cast<allocator_holder&
>(*
this),
static_cast<allocator_holder&
>(other));
455 swap(_value, other._value);
458 allocator_type get_allocator() const BOND_NOEXCEPT
460 return allocator_holder::get();
466 rebind_alloc alloc(allocator_holder::get());
467 std::allocator_traits<rebind_alloc>::destroy(alloc, bond::detail::to_address(_value));
468 alloc.deallocate(_value, 1);
471 template <
typename... Args>
472 pointer new_value(Args&&... args)
474 rebind_alloc alloc(allocator_holder::get());
475 pointer p(alloc.allocate(1));
478 std::allocator_traits<rebind_alloc>::construct(
479 alloc, bond::detail::to_address(p), std::forward<Args>(args)...);
484 alloc.deallocate(p, 1);
489 template <
typename U = T>
490 typename boost::enable_if<std::uses_allocator<U, allocator_type>, pointer>::type
493 return new_value(allocator_holder::get());
496 template <
typename U = T>
497 typename boost::disable_if<std::uses_allocator<U, allocator_type>, pointer>::type
503 template <
typename U>
504 void set_value(U&& value)
508 _value = new_value(std::forward<U>(value));
512 *_value = std::forward<U>(value);
521inline void swap(nullable<T>& x, nullable<T>& y)
528inline bool operator==(
const nullable<T>& x,
const nullable<T>& y)
530 return (x.hasvalue() == y.hasvalue() && (!x.hasvalue() || *x == *y));
535inline bool operator!=(
const nullable<T>& x,
const nullable<T>& y)
545uint32_t container_size(
const nullable<T>& value)
547 return value.empty() ? 0 : 1;
553void resize_list(nullable<T>& value, uint32_t size)
566template <
typename T>
struct
567element_type<nullable<T> >
575class const_enumerator<nullable<T> >
578 const_enumerator(
const nullable<T>& value)
580 _more(value.hasvalue())
583 const_enumerator(
const const_enumerator& other) =
delete;
584 const_enumerator& operator=(
const const_enumerator& other) =
delete;
594 return _value.value();
598 const nullable<T>& _value;
604class enumerator<nullable<T> >
607 enumerator(nullable<T>& value)
609 _more(value.hasvalue())
612 enumerator(
const enumerator& other) =
delete;
613 enumerator& operator=(
const enumerator& other) =
delete;
623 return _value.value();
632template <
typename T>
struct
633is_list_container<nullable<T> >
Helper type that holds an allocator.
Definition: alloc.h:22
void clear()
The same as reset.
Definition: nullable.h:446
void set(const T &value)
Set to specified value.
Definition: nullable.h:425
bool empty() const BOND_NOEXCEPT
Checks if the object is null.
Definition: nullable.h:359
void reset()
Reset to null.
Definition: nullable.h:436
T & value() BOND_NOEXCEPT
Return reference to contained value.
Definition: nullable.h:372
nullable(const T &value, const allocator_type &alloc={})
Construct from an instance T.
Definition: nullable.h:324
const T & operator*() const BOND_NOEXCEPT
Dereference operator.
Definition: nullable.h:398
nullable() BOND_NOEXCEPT_IF(std
Default constructor.
Definition: nullable.h:278
nullable & operator=(const nullable &other)
Assignment operator.
Definition: nullable.h:336
T & set()
Set to default instance of T and return reference to the value.
Definition: nullable.h:414
nullable(const allocator_type &alloc)
Construct nullable using specified allocator instance.
Definition: nullable.h:287
const T & value() const BOND_NOEXCEPT
Return constant reference to contained value.
Definition: nullable.h:381
nullable(const nullable &other)
Copy constructor.
Definition: nullable.h:293
T & operator*() BOND_NOEXCEPT
Dereference operator.
Definition: nullable.h:390
namespace bond
Definition: apply.h:17
void swap(blob &src, blob &dst) BOND_NOEXCEPT
Swap two blobs.
Definition: blob.h:277
boost::enable_if< is_signed_int_or_enum< SignedT >, bool >::type operator==(const Variant &variant, SignedT value)
Compares variant for equality against the provided signed integer or enum value.
Definition: metadata.h:24