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;
106 template <
typename ALLOC,
typename T>
109 using AllocTraits = std::allocator_traits<ALLOC>;
115 using OptionalType = std::optional<typename detail::optional_element<T>::type>;
127 constexpr
BasicOptional(std::nullopt_t,
const ALLOC& allocator = {}) noexcept :
168 template <
typename... ARGS,
typename TT = T,
169 std::enable_if_t<!detail::is_optional_heap_allocated_v<TT>>* =
nullptr,
172 m_data(
std::in_place,
std::forward<ARGS>(args)...)
184 template <
typename... ARGS,
typename TT = T,
185 std::enable_if_t<!detail::is_optional_heap_allocated_v<TT>>* =
nullptr>
186 constexpr
BasicOptional(std::in_place_t,
const ALLOC& allocator, ARGS&&... args) :
188 m_data(
std::in_place,
std::forward<ARGS>(args)...)
200 template <
typename... ARGS,
typename TT = T,
201 std::enable_if_t<detail::is_optional_heap_allocated_v<TT>>* =
nullptr>
202 constexpr
BasicOptional(std::in_place_t,
const ALLOC& allocator, ARGS&&... args) :
204 m_data(
std::in_place, allocateValue(
std::forward<ARGS>(args)...))
215 template <
typename... ARGS,
typename TT = T,
216 std::enable_if_t<detail::is_optional_heap_allocated_v<TT>>* =
nullptr,
219 m_data(
std::in_place, allocateValue(
std::forward<ARGS>(args)...))
247 template <
typename U>
277 template <
typename A,
typename U>
298 if constexpr (AllocTraits::propagate_on_container_copy_assignment::value)
317 template <
typename A,
typename U>
321 if constexpr (AllocTraits::propagate_on_container_copy_assignment::value)
348 template <
typename U = T,
349 std::enable_if_t<!detail::is_optional_v<std::decay_t<U>> &&
350 !(std::is_same_v<T, std::decay_t<U>> && std::is_scalar_v<U>)>* =
nullptr>
367 move(std::move(other));
381 move(std::move(other));
396 if constexpr (AllocTraits::propagate_on_container_move_assignment::value)
400 move(std::move(other));
411 template <
typename U>
415 move(std::move(other));
424 template <
typename U>
428 move(std::move(other));
438 template <
typename U>
441 static_assert(!std::is_same_v<T, U>);
444 if constexpr (AllocTraits::propagate_on_container_move_assignment::value)
448 move(std::move(other));
459 if (!m_data.has_value())
463 if constexpr (detail::is_optional_heap_allocated_v<T>)
489 m_data.swap(other.m_data);
490 if constexpr (AllocTraits::propagate_on_container_swap::value)
502 constexpr
explicit operator bool() const noexcept
514 template <
typename... ARGS>
518 if constexpr (detail::is_optional_heap_allocated_v<T>)
520 T* ptr = allocateValue(std::forward<ARGS>(args)...);
521 return *m_data.emplace(ptr);
525 return m_data.emplace(std::forward<ARGS>(args)...);
542 if constexpr (detail::is_optional_heap_allocated_v<T>)
544 return *m_data.value();
548 return m_data.value();
561 return std::move(
value());
577 if constexpr (detail::is_optional_heap_allocated_v<T>)
579 return *m_data.value();
583 return m_data.value();
596 return std::move(
value());
620 return std::move(
value());
644 return std::move(
value());
678 template <
typename U>
683 return static_cast<T
>(std::forward<U>(def));
695 template <
typename U>
700 return static_cast<T
>(std::forward<U>(def));
707 template <
typename A,
typename U>
710 template <
typename... ARGS>
711 T* allocateValue(ARGS&&... args)
714 using MyAllocTraits = std::allocator_traits<MyAllocType>;
716 auto ptr = MyAllocTraits::allocate(typedAlloc, 1);
719 MyAllocTraits::construct(typedAlloc, std::addressof(*ptr), std::forward<ARGS>(args)...);
723 MyAllocTraits::deallocate(typedAlloc, ptr, 1);
731 void destroyValue(T* ptr)
735 using MyAllocType = RebindAlloc<ALLOC, T>;
736 using MyAllocTraits = std::allocator_traits<MyAllocType>;
738 MyAllocTraits::destroy(typedAlloc, ptr);
739 MyAllocTraits::deallocate(typedAlloc, ptr, 1);
743 template <
typename A,
typename U>
744 void copy(
const BasicOptional<A, U>& other)
748 if (!other.has_value())
762 if (!other.has_value())
768 if constexpr (detail::is_optional_heap_allocated_v<T>)
774 auto& ptr = other.m_data.value();
780 auto&
value = *other.m_data.value();
781 T* ptr = allocateValue(std::move(
value));
787 auto&
value = other.m_data.value();
788 m_data.emplace(std::move(
value));
793 template <
typename U>
794 void move(BasicOptional<ALLOC, U>&& other)
797 static_assert(!std::is_same_v<T, U>);
799 if (!other.has_value())
805 if constexpr (detail::is_optional_heap_allocated_v<T> && detail::is_optional_heap_allocated_v<U>)
807 auto&
value = *other.m_data.value();
808 T* ptr = allocateValue(std::move(
value));
811 else if constexpr (detail::is_optional_heap_allocated_v<T>)
813 auto&
value = other.m_data.value();
814 T* ptr = allocateValue(std::move(
value));
817 else if constexpr (detail::is_optional_heap_allocated_v<U>)
819 auto&
value = *other.m_data.value();
820 m_data.emplace(std::move(
value));
824 auto&
value = other.m_data.value();
825 m_data.emplace(std::move(
value));
836 if constexpr (detail::is_optional_heap_allocated_v<T>)
838 auto& ptr = m_data.value();
849 template <
typename T>
860 template <
typename ALLOC,
typename T>
863 uint32_t result = seed;
878 template <
typename T>
891 template <
typename T,
typename... ARGS>
894 return Optional<T>(std::in_place, std::forward<ARGS>(args)...);
905 template <
typename A1,
typename T,
typename A2,
typename U>
922 template <
typename A,
typename T>
935 template <
typename A,
typename T>
949 template <
typename A,
typename T,
typename U>
963 template <
typename A,
typename T,
typename U>
977 template <
typename A1,
typename T,
typename A2,
typename U>
980 return !(first == second);
990 template <
typename A,
typename T>
993 return !(opt == std::nullopt);
1003 template <
typename A,
typename T>
1006 return !(std::nullopt == opt);
1017 template <
typename A,
typename T,
typename U>
1020 return !(opt == value);
1031 template <
typename A,
typename T,
typename U>
1034 return !(value == opt);
1045 template <
typename A1,
typename T,
typename A2,
typename U>
1062 template <
typename A,
typename T>
1075 template <
typename A,
typename T>
1089 template <
typename A,
typename T,
typename U>
1103 template <
typename A,
typename T,
typename U>
1117 template <
typename A1,
typename T,
typename A2,
typename U>
1134 template <
typename A,
typename T>
1147 template <
typename A,
typename T>
1161 template <
typename A,
typename T,
typename U>
1175 template <
typename A,
typename T,
typename U>
1189 template <
typename A1,
typename T,
typename A2,
typename U>
1192 return !(first > second);
1202 template <
typename A,
typename T>
1205 return !(opt > std::nullopt);
1215 template <
typename A,
typename T>
1218 return !(std::nullopt > opt);
1229 template <
typename A,
typename T,
typename U>
1232 return !(opt > value);
1243 template <
typename A,
typename T,
typename U>
1246 return !(value > opt);
1257 template <
typename A1,
typename T,
typename A2,
typename U>
1260 return !(first < second);
1270 template <
typename A,
typename T>
1273 return !(opt < std::nullopt);
1283 template <
typename A,
typename T>
1286 return !(std::nullopt < opt);
1297 template <
typename A,
typename T,
typename U>
1300 return !(opt < value);
1311 template <
typename A,
typename T,
typename U>
1314 return !(value < opt);
1322 template <
typename ALLOC,
typename T>
allocator_type & get_allocator_ref()
void set_allocator(const allocator_type &allocator)
~BadOptionalAccess() override
constexpr BasicOptional(BasicOptional< ALLOC, U > &&other, const ALLOC &allocator)
constexpr BasicOptional(const T &value, const ALLOC &allocator={})
constexpr BasicOptional(const ALLOC &allocator)
void swap(BasicOptional &other)
constexpr T && value() &&
const T & operator*() const &
constexpr BasicOptional() noexcept
BasicOptional(BasicOptional &&other)
T & emplace(ARGS &&... args)
constexpr BasicOptional(BasicOptional< ALLOC, U > &&other)
constexpr const T & value() const &
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 & 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)
friend class BasicOptional
constexpr BasicOptional(const BasicOptional &other)
T value_or(U &&def) const
constexpr BasicOptional(const BasicOptional< A, U > &other, const ALLOC &allocator)
constexpr BasicOptional(std::nullopt_t, const ALLOC &allocator={}) noexcept
BasicOptional & operator=(BasicOptional &&other)
constexpr BasicOptional(T &&value, const ALLOC &allocator={})
const T && operator*() const &&
constexpr bool has_value() const noexcept
BasicOptional & operator=(BasicOptional< ALLOC, U > &&other)
constexpr const T && value() const &&
constexpr BasicOptional(const BasicOptional< ALLOC, U > &other)
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