1 #ifndef ZSERIO_VARIANT_H_INC
2 #define ZSERIO_VARIANT_H_INC
16 template <
size_t I,
typename... T>
19 using type = std::tuple_element_t<I, std::tuple<T...>>;
22 template <
auto I,
typename... T>
23 using type_at_t =
typename type_at<static_cast<size_t>(I), T...>::type;
25 template <
size_t N,
typename V,
typename F>
26 void for_active_item(
const V&, F&&, std::false_type)
29 template <
size_t N,
typename V,
typename F>
30 void for_active_item(
const V& var, F&& fun, std::true_type = {})
32 using INDEX =
typename V::IndexType;
33 if (
static_cast<size_t>(var.index()) == N - 1)
35 std::forward<F>(fun)(*var.template get_if<static_cast<INDEX>(N - 1)>());
37 for_active_item<N - 1>(var, std::forward<F>(fun), std::bool_constant<(N - 1 > 0)>());
40 template <
size_t N,
typename V,
typename F>
41 void for_active_item(V& var, F&& fun, std::true_type = {})
43 using INDEX =
typename V::IndexType;
44 if (
static_cast<size_t>(var.index()) == N - 1)
46 std::forward<F>(fun)(*var.template get_if<static_cast<INDEX>(N - 1)>());
48 for_active_item<N - 1>(var, std::forward<F>(fun), std::bool_constant<(N - 1 > 0)>());
51 template <
size_t N,
typename V,
typename F>
52 void for_active_item_2(
const V&,
const V&, F&&, std::false_type)
55 template <
size_t N,
typename V,
typename F>
56 void for_active_item_2(
const V& var1,
const V& var2, F&& fun, std::true_type = {})
59 using INDEX =
typename V::IndexType;
60 if (
static_cast<size_t>(var1.index()) == N - 1)
62 std::forward<F>(fun)(*var1.template get_if<static_cast<INDEX>(N - 1)>(),
63 *var2.template
get_if<
static_cast<INDEX
>(N - 1)>());
65 for_active_item_2<N - 1>(var1, var2, std::forward<F>(fun), std::bool_constant<(N - 1 > 0)>());
101 template <
typename ALLOC,
typename INDEX,
typename... T>
104 using AllocTraits = std::allocator_traits<ALLOC>;
138 template <INDEX I,
typename... ARGS, std::enable_if_t<!
is_first_allocator_v<ARGS...>>* =
nullptr>
141 emplace<I>(std::forward<ARGS>(args)...);
153 template <INDEX I,
typename... ARGS>
157 emplace<I>(std::forward<ARGS>(args)...);
166 m_data(other.m_data),
167 m_index(other.m_index)
179 m_data(other.m_data, allocator),
180 m_index(other.m_index)
194 m_data = other.m_data;
195 m_index = other.m_index;
207 m_data(
std::move(other.m_data)),
208 m_index(other.m_index)
220 m_data(
std::move(other.m_data), allocator),
221 m_index(other.m_index)
240 m_data = std::move(other.m_data);
241 m_index = other.m_index;
257 return static_cast<size_t>(
index()) == std::variant_npos || !m_data.
hasValue();
265 template <INDEX I,
typename... ARGS>
268 using U = detail::type_at_t<I, T...>;
269 auto& ret = m_data.template emplace<U>(std::forward<ARGS>(args)...);
279 return m_data.
hasValue() ? m_index :
static_cast<INDEX
>(std::variant_npos);
285 template <INDEX I,
typename U = detail::type_at_t<I, T...>>
292 return m_data.template get_if<U>();
298 template <INDEX I,
typename U = detail::type_at_t<I, T...>>
305 return m_data.template get_if<U>();
313 template <INDEX I,
typename U = detail::type_at_t<I, T...>>
316 auto ptr = get_if<I>();
319 throw BadVariantAccess(
"Variant: Attempt to retrieve an inactive element at index ")
320 <<
static_cast<size_t>(I) <<
". Active element index is " <<
static_cast<size_t>(
index());
330 template <INDEX I,
typename U = detail::type_at_t<I, T...>>
333 auto ptr = get_if<I>();
336 throw BadVariantAccess(
"Variant: Attempt to retrieve an inactive element at index ")
337 <<
static_cast<size_t>(I) <<
". Active element index is " <<
static_cast<size_t>(
index());
349 m_data.
swap(other.m_data);
350 std::swap(m_index, other.m_index);
360 template <
typename F>
361 auto visit(F&& fun) -> decltype(fun(std::declval<detail::type_at_t<0, T...>>()))
367 using R = decltype(fun(std::declval<detail::type_at_t<0, T...>>()));
368 if constexpr (std::is_same_v<R, void>)
370 detail::for_active_item<
sizeof...(T)>(*
this, [func = std::forward<F>(fun)](
auto& elem) {
371 std::move(func)(elem);
377 detail::for_active_item<
sizeof...(T)>(*
this, [&ret, func = std::forward<F>(fun)](
auto& elem) {
378 ret = std::move(func)(elem);
391 template <
typename F>
392 auto visit(F&& fun)
const -> decltype(fun(std::declval<detail::type_at_t<0, T...>>()))
398 using R = decltype(fun(std::declval<detail::type_at_t<0, T...>>()));
399 if constexpr (std::is_same_v<R, void>)
401 detail::for_active_item<
sizeof...(T)>(*
this, [func = std::forward<F>(fun)](
auto& elem) {
402 std::move(func)(elem);
408 detail::for_active_item<
sizeof...(T)>(*
this, [&ret, func = std::forward<F>(fun)](
auto& elem) {
409 ret = std::move(func)(elem);
428 detail::for_active_item_2<
sizeof...(T)>(*
this, other, [&ret](
auto& elem1,
auto& elem2) {
429 ret = elem1 == elem2;
441 return !(*
this == other);
457 detail::for_active_item_2<
sizeof...(T)>(*
this, other, [&ret](
auto& elem1,
auto& elem2) {
470 return other < *
this;
480 return !(other < *
this);
490 return !(other > *
this);
500 template <
typename INDEX,
typename... T>
510 template <
auto I,
typename ALLOC,
typename INDEX,
typename... T>
513 static_assert(std::is_same_v<decltype(I), INDEX>,
"Index has a wrong type");
514 return var.template get<I>();
524 template <
auto I,
typename ALLOC,
typename INDEX,
typename... T>
527 static_assert(std::is_same_v<decltype(I), INDEX>,
"Index has a wrong type");
528 return var.template get<I>();
536 template <
auto I,
typename ALLOC,
typename INDEX,
typename... T>
539 static_assert(std::is_same_v<decltype(I), INDEX>,
"Index has a wrong type");
540 return var->template get_if<I>();
548 template <
auto I,
typename ALLOC,
typename INDEX,
typename... T>
551 static_assert(std::is_same_v<decltype(I), INDEX>,
"Index has a wrong type");
552 return var->template get_if<I>();
563 template <
typename F,
typename ALLOC,
typename INDEX,
typename... T>
566 return var.visit(std::forward<F>(fun));
577 template <
typename F,
typename ALLOC,
typename INDEX,
typename... T>
580 return var.visit(std::forward<F>(fun));
589 template <
typename ALLOC,
typename INDEX,
typename... T>
592 uint32_t result = seed;
594 var.
visit([&result](
const auto& value) {
605 template <
typename ALLOC,
typename INDEX,
typename... T>
606 struct hash<
zserio::BasicVariant<ALLOC, INDEX, T...>>
~BadVariantAccess() override
bool hasValue() const noexcept
void swap(BasicAny &other)
auto visit(F &&fun) const -> decltype(fun(std::declval< detail::type_at_t< 0, T... >>()))
BasicVariant(const BasicVariant &other, const ALLOC &allocator)
void swap(BasicVariant &other)
BasicVariant(BasicVariant &&other, const ALLOC &allocator)
BasicVariant(const ALLOC &allocator)
bool operator<=(const BasicVariant &other) const
bool operator<(const BasicVariant &other) const
bool operator>(const BasicVariant &other) const
BasicVariant & operator=(BasicVariant &&other)
BasicVariant(in_place_index_t< I >, ARGS &&... args)
bool valueless_by_exception() const noexcept
BasicVariant & operator=(const BasicVariant &other)
BasicVariant(in_place_index_t< I >, const ALLOC &allocator, ARGS &&... args)
bool operator==(const BasicVariant &other) const
const U * get_if() const noexcept
bool operator>=(const BasicVariant &other) const
auto visit(F &&fun) -> decltype(fun(std::declval< detail::type_at_t< 0, T... >>()))
INDEX index() const noexcept
BasicVariant(const BasicVariant &other)
BasicVariant(BasicVariant &&other)
decltype(auto) emplace(ARGS &&... args)
bool operator!=(const BasicVariant &other) const
CppRuntimeException(const char *message="")
decltype(auto) visit(F &&fun, BasicVariant< ALLOC, INDEX, T... > &var)
constexpr in_place_index_t< I > in_place_index
decltype(auto) get(BasicVariant< ALLOC, INDEX, T... > &var)
uint32_t calcHashCode(uint32_t seedValue, const ArrayView< T, ARRAY_TRAITS > &array)
decltype(auto) get_if(BasicVariant< ALLOC, INDEX, T... > *var)
constexpr bool is_first_allocator_v
size_t operator()(const zserio::BasicVariant< ALLOC, INDEX, T... > &var) const