1 #ifndef ZSERIO_OPTIONAL_H_INC
2 #define ZSERIO_OPTIONAL_H_INC
15 template <
typename ALLOC,
typename T>
21 template <
typename T,
bool = (sizeof(T) > 3 *
sizeof(
void*))>
22 struct is_optional_big : std::false_type
26 struct is_optional_big<T, true> : std::true_type
29 template <
typename T,
typename =
void>
30 struct is_recursive : std::false_type
34 struct is_recursive<T,
std::void_t<typename T::IS_RECURSIVE>> : std::true_type
37 template <typename T, bool = is_recursive<T>::value>
38 struct is_optional_heap_allocated_impl : is_optional_big<T>::type
42 struct is_optional_heap_allocated_impl<T, true> : std::true_type
46 struct is_optional_heap_allocated : is_optional_heap_allocated_impl<T>
50 struct is_optional_heap_allocated<
View<T>> : std::false_type
54 constexpr
bool is_optional_heap_allocated_v = is_optional_heap_allocated<T>::value;
56 template <
typename T,
bool heap = is_optional_heap_allocated_v<T>>
57 struct optional_element
63 struct optional_element<T, true>
69 struct is_optional : std::false_type
72 template <
typename A,
typename T>
73 struct is_optional<BasicOptional<A, T>> : std::true_type
77 constexpr
bool is_optional_v = is_optional<T>::value;
104 template <
typename ALLOC,
typename T>
107 using AllocTraits = std::allocator_traits<ALLOC>;
113 using OptionalType = std::optional<typename detail::optional_element<T>::type>;
125 constexpr
BasicOptional(std::nullopt_t,
const ALLOC& allocator = {}) noexcept :
166 template <
typename... ARGS,
typename TT = T,
167 std::enable_if_t<!detail::is_optional_heap_allocated_v<TT>>* =
nullptr,
170 m_data(
std::in_place,
std::forward<ARGS>(args)...)
182 template <
typename... ARGS,
typename TT = T,
183 std::enable_if_t<!detail::is_optional_heap_allocated_v<TT>>* =
nullptr>
184 constexpr
BasicOptional(std::in_place_t,
const ALLOC& allocator, ARGS&&... args) :
186 m_data(
std::in_place,
std::forward<ARGS>(args)...)
198 template <
typename... ARGS,
typename TT = T,
199 std::enable_if_t<detail::is_optional_heap_allocated_v<TT>>* =
nullptr>
200 constexpr
BasicOptional(std::in_place_t,
const ALLOC& allocator, ARGS&&... args) :
202 m_data(
std::in_place, allocateValue(
std::forward<ARGS>(args)...))
213 template <
typename... ARGS,
typename TT = T,
214 std::enable_if_t<detail::is_optional_heap_allocated_v<TT>>* =
nullptr,
217 m_data(
std::in_place, allocateValue(
std::forward<ARGS>(args)...))
245 template <
typename U>
275 template <
typename A,
typename U>
296 if constexpr (AllocTraits::propagate_on_container_copy_assignment::value)
315 template <
typename A,
typename U>
319 if constexpr (AllocTraits::propagate_on_container_copy_assignment::value)
346 template <
typename U = T,
347 std::enable_if_t<!detail::is_optional_v<std::decay_t<U>> &&
348 !(std::is_same_v<T, std::decay_t<U>> && std::is_scalar_v<U>)>* =
nullptr>
365 move(std::move(other));
379 move(std::move(other));
394 if constexpr (AllocTraits::propagate_on_container_move_assignment::value)
398 move(std::move(other));
411 if (!m_data.has_value())
415 if constexpr (detail::is_optional_heap_allocated_v<T>)
441 m_data.swap(other.m_data);
442 if constexpr (AllocTraits::propagate_on_container_swap::value)
454 constexpr
explicit operator bool() const noexcept
466 template <
typename... ARGS>
470 if constexpr (detail::is_optional_heap_allocated_v<T>)
472 T* ptr = allocateValue(std::forward<ARGS>(args)...);
473 return *m_data.emplace(ptr);
477 return m_data.emplace(std::forward<ARGS>(args)...);
494 if constexpr (detail::is_optional_heap_allocated_v<T>)
496 return *m_data.value();
500 return m_data.value();
517 if constexpr (detail::is_optional_heap_allocated_v<T>)
519 return *m_data.value();
523 return m_data.value();
582 template <
typename U>
587 return static_cast<T
>(std::forward<U>(def));
599 template <
typename U>
604 return static_cast<T
>(std::forward<U>(def));
610 template <
typename... ARGS>
611 T* allocateValue(ARGS&&... args)
614 using MyAllocTraits = std::allocator_traits<MyAllocType>;
616 auto ptr = MyAllocTraits::allocate(typedAlloc, 1);
619 MyAllocTraits::construct(typedAlloc, std::addressof(*ptr), std::forward<ARGS>(args)...);
623 MyAllocTraits::deallocate(typedAlloc, ptr, 1);
631 void destroyValue(T* ptr)
635 using MyAllocType = RebindAlloc<ALLOC, T>;
636 using MyAllocTraits = std::allocator_traits<MyAllocType>;
638 MyAllocTraits::destroy(typedAlloc, ptr);
639 MyAllocTraits::deallocate(typedAlloc, ptr, 1);
643 template <
typename A,
typename U>
644 void copy(
const BasicOptional<A, U>& other)
648 if (!other.has_value())
662 if (!other.has_value())
668 if constexpr (detail::is_optional_heap_allocated_v<T>)
674 auto& ptr = other.m_data.value();
680 auto&
value = *other.m_data.value();
681 T* ptr = allocateValue(std::move(
value));
687 auto&
value = *other.m_data;
688 m_data.emplace(std::move(
value));
699 if constexpr (detail::is_optional_heap_allocated_v<T>)
701 auto& ptr = m_data.value();
712 template <
typename T>
723 template <
typename ALLOC,
typename T>
726 uint32_t result = seed;
741 template <
typename T>
754 template <
typename T,
typename... ARGS>
757 return Optional<T>(std::in_place, std::forward<ARGS>(args)...);
768 template <
typename A1,
typename T,
typename A2,
typename U>
785 template <
typename A,
typename T>
798 template <
typename A,
typename T>
812 template <
typename A,
typename T,
typename U>
826 template <
typename A,
typename T,
typename U>
840 template <
typename A1,
typename T,
typename A2,
typename U>
843 return !(first == second);
853 template <
typename A,
typename T>
856 return !(opt == std::nullopt);
866 template <
typename A,
typename T>
869 return !(std::nullopt == opt);
880 template <
typename A,
typename T,
typename U>
883 return !(opt == value);
894 template <
typename A,
typename T,
typename U>
897 return !(value == opt);
908 template <
typename A1,
typename T,
typename A2,
typename U>
925 template <
typename A,
typename T>
938 template <
typename A,
typename T>
952 template <
typename A,
typename T,
typename U>
966 template <
typename A,
typename T,
typename U>
980 template <
typename A1,
typename T,
typename A2,
typename U>
997 template <
typename A,
typename T>
1010 template <
typename A,
typename T>
1024 template <
typename A,
typename T,
typename U>
1038 template <
typename A,
typename T,
typename U>
1052 template <
typename A1,
typename T,
typename A2,
typename U>
1055 return !(first > second);
1065 template <
typename A,
typename T>
1068 return !(opt > std::nullopt);
1078 template <
typename A,
typename T>
1081 return !(std::nullopt > opt);
1092 template <
typename A,
typename T,
typename U>
1095 return !(opt > value);
1106 template <
typename A,
typename T,
typename U>
1109 return !(value > opt);
1120 template <
typename A1,
typename T,
typename A2,
typename U>
1123 return !(first < second);
1133 template <
typename A,
typename T>
1136 return !(opt < std::nullopt);
1146 template <
typename A,
typename T>
1149 return !(std::nullopt < opt);
1160 template <
typename A,
typename T,
typename U>
1163 return !(opt < value);
1174 template <
typename A,
typename T,
typename U>
1177 return !(value < opt);
1185 template <
typename ALLOC,
typename T>
allocator_type & get_allocator_ref()
void set_allocator(const allocator_type &allocator)
constexpr BasicOptional(const T &value, const ALLOC &allocator={})
constexpr BasicOptional(const ALLOC &allocator)
void swap(BasicOptional &other)
constexpr BasicOptional() noexcept
BasicOptional(BasicOptional &&other)
constexpr const T & value() const
T & emplace(ARGS &&... args)
constexpr BasicOptional(const BasicOptional &other, const ALLOC &allocator)
BasicOptional & operator=(std::nullopt_t)
const T * operator->() const
constexpr BasicOptional(std::in_place_t, const ALLOC &allocator, ARGS &&... args)
constexpr BasicOptional(std::in_place_t, ARGS &&... args)
BasicOptional(const BasicOptional< A, U > &other, const ALLOC &allocator)
BasicOptional & operator=(const BasicOptional< A, U > &other)
std::optional< typename detail::optional_element< T >::type > OptionalType
BasicOptional(BasicOptional &&other, const ALLOC &allocator)
constexpr BasicOptional & operator=(const BasicOptional &other)
constexpr BasicOptional(const BasicOptional &other)
T value_or(U &&def) const
constexpr BasicOptional(std::nullopt_t, const ALLOC &allocator={}) noexcept
BasicOptional & operator=(BasicOptional &&other)
constexpr BasicOptional(T &&value, const ALLOC &allocator={})
constexpr bool has_value() const noexcept
constexpr BasicOptional(const BasicOptional< ALLOC, U > &other)
const T & operator*() const
CppRuntimeException(const char *message="")
bool operator>(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
bool operator==(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
typename std::allocator_traits< ALLOC >::template rebind_alloc< T > RebindAlloc
bool operator<(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
uint32_t calcHashCode(uint32_t seedValue, const ArrayView< T, ARRAY_TRAITS > &array)
View(T, ARGS &&...) -> View< T >
constexpr auto make_optional(T &&value)
bool operator<=(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
bool operator>=(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
bool operator!=(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
size_t operator()(const zserio::BasicOptional< ALLOC, T > &opt) const