49 #include <meta/meta.hpp> 80 template <
typename union_t,
81 template <
typename>
typename fun_t,
83 inline bool constexpr one_alternative_is =
false;
88 template <
typename ... alternatives,
89 template <
typename>
typename fun_t,
91 inline bool constexpr one_alternative_is<union_composition<alternatives...>,
94 = !
meta::empty<meta::find_if<meta::list<alternatives...>, fun_t<target_t>>>::value;
97 template <
typename ... alternatives,
98 template <
typename>
typename fun_t>
99 inline bool constexpr one_alternative_is<union_composition<alternatives...>,
101 union_composition<alternatives...>> =
false;
104 template <
typename ... alternatives,
105 template <
typename>
typename fun_t,
107 requires convertible_to_by_member_concept<target_t, union_composition<alternatives...>>
108 inline bool constexpr one_alternative_is<union_composition<alternatives...>,
113 template <
typename ... alternatives,
114 template <
typename>
typename fun_t,
116 requires cartesian_composition_concept<target_t> &&
117 meta::in<detail::transformation_trait_or_t<recursive_cartesian_components<target_t>, meta::list<>>,
118 union_composition<alternatives...>>::value
119 inline bool constexpr one_alternative_is<union_composition<alternatives...>,
124 template <
typename ... alternatives,
125 template <
typename>
typename fun_t,
127 requires type_in_pack_v<target_t, alternatives...>
128 inline bool constexpr one_alternative_is<union_composition<alternatives...>,
133 template <
typename ... alternatives,
134 template <
typename>
typename fun_t,
136 requires type_in_pack_v<target_t, alternatives...>
137 inline bool constexpr one_alternative_is<target_t,
139 union_composition<alternatives...>> =
false;
142 template <
typename ... alternatives,
143 template <
typename>
typename fun_t,
146 requires requires {
std::Same<
typename target_t::value_type, union_composition<alternatives...>>; }
147 inline bool constexpr one_alternative_is<union_composition<alternatives...>,
153 template <
typename ... alternatives,
154 template <
typename>
typename fun_t,
156 requires tuple_size_concept<target_t> && !cartesian_composition_concept<target_t>
157 inline bool constexpr one_alternative_is<union_composition<alternatives...>,
197 template <
typename ...alternative_types>
199 requires (detail::constexpr_alphabet_concept<alternative_types> && ...) &&
200 (
sizeof...(alternative_types) >= 2)
203 class union_composition :
public alphabet_base<union_composition<alternative_types...>,
204 (static_cast<size_t>(alphabet_size_v<alternative_types>) + ...),
210 using base_t = alphabet_base<union_composition<alternative_types...>,
211 (
static_cast<size_t>(alphabet_size_v<alternative_types>) + ...),
217 using alternatives = meta::list<alternative_types...>;
219 static_assert(
std::Same<alternatives, meta::unique<alternatives>>,
220 "All types in a union_composition must be distinct.");
223 using base_t::value_size;
227 using typename base_t::char_type;
228 using typename base_t::rank_type;
235 template <
typename alternative_t>
238 return detail::type_in_pack_v<alternative_t, alternative_types...>;
257 template <
typename alternative_t>
259 requires holds_alternative<alternative_t>()
274 template <
typename indirect_alternative_t>
277 detail::implicitly_convertible_from,
278 indirect_alternative_t> &&
279 detail::one_alternative_is<union_composition,
280 detail::constructible_from,
281 indirect_alternative_t>
285 assign_rank(rank_by_type_(meta::front<meta::find_if<alternatives,
286 detail::constructible_from<indirect_alternative_t>>>(rhs)));
290 template <
typename indirect_alternative_t>
291 requires detail::one_alternative_is<union_composition,
292 detail::implicitly_convertible_from,
293 indirect_alternative_t>
294 constexpr union_composition(indirect_alternative_t
const & rhs) noexcept
298 meta::front<meta::find_if<alternatives,
299 detail::implicitly_convertible_from<indirect_alternative_t>>>(rhs)));
309 template <
typename indirect_alternative_t>
311 requires !detail::one_alternative_is<union_composition,
312 detail::implicitly_convertible_from,
313 indirect_alternative_t> &&
314 !detail::one_alternative_is<union_composition,
315 detail::constructible_from,
316 indirect_alternative_t> &&
317 detail::one_alternative_is<union_composition,
318 detail::assignable_from,
319 indirect_alternative_t>
321 constexpr union_composition &
operator=(indirect_alternative_t
const & rhs) noexcept
323 using alternative_t = meta::front<meta::find_if<alternatives, detail::assignable_from<indirect_alternative_t>>>;
324 alternative_t alternative{};
334 template <
size_t index>
339 static_assert(index < value_size,
"The union_composition contains less alternatives than you are checking.");
340 return (
to_rank() >= partial_sum_sizes[index]) && (
to_rank() < partial_sum_sizes[index + 1]);
347 template <
size_t index>
350 return convert_impl<index, true>();
356 template <
size_t index>
359 return convert_impl<index, false>();
369 template <
typename alternative_t>
371 requires holds_alternative<alternative_t>()
373 constexpr
size_t index = meta::find_index<alternatives, alternative_t>::value;
374 return is_alternative<index>();
381 template <
typename alternative_t>
383 requires holds_alternative<alternative_t>()
385 constexpr
size_t index = meta::find_index<alternatives, alternative_t>::value;
386 return convert_impl<index, true>();
392 template <
typename alternative_t>
394 requires holds_alternative<alternative_t>()
396 constexpr
size_t index = meta::find_index<alternatives, alternative_t>::value;
397 return convert_impl<index, false>();
407 template <
typename alternative_t>
408 constexpr
bool operator==(alternative_t
const & rhs)
const noexcept
409 requires holds_alternative<alternative_t>()
411 return is_alternative<alternative_t>() && (convert_unsafely_to<alternative_t>() == rhs);
414 template <
typename alternative_t>
415 constexpr
bool operator!=(alternative_t
const & rhs)
const noexcept
416 requires holds_alternative<alternative_t>()
418 return !operator==(rhs);
429 template <
typename indirect_alternative_type>
430 constexpr
bool operator==(indirect_alternative_type
const & rhs)
const noexcept
432 requires detail::one_alternative_is<union_composition,
433 detail::weakly_equality_comparable_with,
434 indirect_alternative_type>
437 using alternative_t =
438 meta::front<meta::find_if<alternatives,
439 detail::weakly_equality_comparable_with<indirect_alternative_type>>>;
440 return is_alternative<alternative_t>() && (convert_unsafely_to<alternative_t>() == rhs);
443 template <
typename indirect_alternative_type>
444 constexpr
bool operator!=(indirect_alternative_type
const & rhs)
const noexcept
446 requires detail::one_alternative_is<union_composition,
447 detail::weakly_equality_comparable_with,
448 indirect_alternative_type>
451 return !operator==(rhs);
462 template <
size_t index,
bool throws>
463 constexpr
auto convert_impl()
const noexcept(!
throws) -> meta::at_c<alternatives, index>
465 static_assert(index < value_size,
"The union_composition contains less alternatives than you are checking.");
466 using alternative_t = meta::at_c<alternatives, index>;
468 if constexpr (
throws)
470 if (!is_alternative<index>())
472 throw std::bad_variant_access{};
487 static constexpr std::array partial_sum_sizes = []() constexpr
489 constexpr
size_t N =
sizeof...(alternative_types) + 1;
491 std::array<rank_type, N> partial_sum{0, alphabet_size_v<alternative_types>...};
492 for (
size_t i = 1u; i < N; ++i)
493 partial_sum[i] += partial_sum[i-1];
505 static constexpr std::array<char_type, value_size> rank_to_char = []() constexpr
510 auto assign_rank_to_char = [](
auto alternative,
size_t rank) constexpr
515 auto assign_value_to_char = [assign_rank_to_char] (
auto alternative,
auto & value_to_char,
auto & value) constexpr
517 using alternative_t = std::decay_t<decltype(alternative)>;
518 for (
size_t i = 0u; i < alphabet_size_v<alternative_t>; ++i, ++value)
519 value_to_char[value] = assign_rank_to_char(alternative, i);
523 std::array<char_type, value_size> value_to_char{};
529 ((assign_value_to_char(alternative_types{}, value_to_char, value)),...);
531 return value_to_char;
541 static constexpr std::array char_to_rank = []() constexpr
543 constexpr
size_t table_size = 1 << (
sizeof(
char_type) * 8);
545 std::array<rank_type, table_size> char_to_rank{};
546 for (
size_t i = 0u; i < rank_to_char.size(); ++i)
548 using index_t = std::make_unsigned_t<char_type>;
549 rank_type & old_entry = char_to_rank[
static_cast<index_t
>(rank_to_char[i])];
550 bool is_new_entry = rank_to_char[0] != rank_to_char[i] && old_entry == 0;
561 template <
size_t index,
typename alternative_t>
563 requires holds_alternative<alternative_t>()
565 static constexpr
rank_type rank_by_index_(alternative_t
const & alternative) noexcept
574 template <
typename alternative_t>
576 requires holds_alternative<alternative_t>()
578 static constexpr
rank_type rank_by_type_(alternative_t
const & alternative) noexcept
580 constexpr
size_t index = meta::find_index<alternatives, alternative_t>::value;
581 return rank_by_index_<index>(alternative);
590 template <
typename lhs_t,
typename ...alternative_types>
593 requires detail::weakly_equality_comparable_by_members_with_concept<
union_composition<alternative_types...>, lhs_t> &&
594 !detail::weakly_equality_comparable_by_members_with_concept<lhs_t,
union_composition<alternative_types...>>
600 template <
typename lhs_t,
typename ...alternative_types>
603 requires detail::weakly_equality_comparable_by_members_with_concept<
union_composition<alternative_types...>, lhs_t> &&
604 !detail::weakly_equality_comparable_by_members_with_concept<lhs_t,
union_composition<alternative_types...>>
Provides concepts for core language types and relations that don't have concepts in C++20 (yet)...
constexpr auto convert_unsafely_to() const noexcept
Convert to the specified alphabet (undefined behaviour if is_alternative() would be false)...
Definition: union_composition.hpp:357
Contains metaprogramming utilities for integer types.
Provides various metafunctions on a set of types, usually provided as template argument pack...
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:58
Provides implementation detail for seqan3::union_composition and seqan3::cartesian_composition.
constexpr bool is_alternative() const noexcept requires holds_alternative< alternative_t >()
Whether the union alphabet currently holds a value of the given alternative.
Definition: union_composition.hpp:370
constexpr union_composition(indirect_alternative_t const &rhs) noexcept
Construction via the value of a type that an alternative type is constructible from.
Definition: union_composition.hpp:283
A combined alphabet that can hold values of either of its alternatives.
Definition: detail.hpp:194
constexpr bool is_alternative() const noexcept
Whether the union alphabet currently holds a value of the given alternative.
Definition: union_composition.hpp:337
constexpr union_composition(alternative_t const &alternative) noexcept
Construction via the value of an alternative.
Definition: union_composition.hpp:261
constexpr alphabet_type & assign_rank(alphabet_type &alph, underlying_rank_t< alphabet_type > const rank) requires requires(alphabet_type alph)
Implementation of seqan3::semi_alphabet_concept::assign_rank() that delegates to a member function...
Definition: member_exposure.hpp:110
static constexpr bool holds_alternative() noexcept
Returns true if alternative_t is one of the given alternative types.
Definition: union_composition.hpp:236
Provides utility functions for tuple like interfaces.
char_t char_type
The type of the alphabet when converted to char (e.g. via to_char()).
Definition: alphabet_base.hpp:87
constexpr auto convert_to() const
Convert to the specified alphabet (throws if is_alternative() would be false).
Definition: union_composition.hpp:348
Provides seqan3::alphabet_base.
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
auto const to_char
A view that calls seqan3::to_char() on each element in the input range.
Definition: to_char.hpp:88
Definition: aligned_sequence_concept.hpp:288
constexpr union_composition & operator=(indirect_alternative_t const &rhs) noexcept
Assignment via a value that one of the alternative types is assignable from.
Definition: union_composition.hpp:321
constexpr alternative_t convert_to() const requires holds_alternative< alternative_t >()
Convert to the specified alphabet (throws if is_alternative() would be false).
Definition: union_composition.hpp:382
detail::min_viable_uint_t< size - 1 > rank_type
The type of the alphabet when represented as a number (e.g. via to_rank()).
Definition: alphabet_base.hpp:89
Provides C++20 additions to the type_traits header.
::ranges::empty empty
Alias for ranges::empty. Checks whether a range is empty.
Definition: ranges:205
Core alphabet concept and free function/metafunction wrappers.
Provides various metafunctions used by the range module.
constexpr underlying_rank_t< alphabet_type > to_rank(alphabet_type const alph) requires requires(alphabet_type alph)
Implementation of seqan3::semi_alphabet_concept::to_rank() that delegates to a member function...
Definition: member_exposure.hpp:97
constexpr underlying_char_t< alphabet_type > to_char(alphabet_type const alph) requires requires(alphabet_type alph)
Implementation of seqan3::alphabet_concept::to_char() that delegates to a member function.
Definition: member_exposure.hpp:165
constexpr alternative_t convert_unsafely_to() const noexcept requires holds_alternative< alternative_t >()
Convert to the specified alphabet (undefined behaviour if is_alternative() would be false)...
Definition: union_composition.hpp:393
auto const to_rank
A view that calls seqan3::to_rank() on each element in the input range.
Definition: to_rank.hpp:90