28 namespace seqan3::detail
31 #if SEQAN3_WORKAROUND_GCC7_AND_8_CONCEPT_ISSUES
33 SEQAN3_CONCEPT variant_guard_pseudoalphabet = requires { requires seqan3::alphabet_size<t> > 0; };
37 template <
typename other_t,
typename ... alternative_types>
38 inline constexpr
bool variant_general_guard =
39 (!std::same_as<other_t, alphabet_variant<alternative_types...>>) &&
41 (!(std::same_as<other_t, alternative_types> || ...)) &&
43 #if SEQAN3_WORKAROUND_GCC7_AND_8_CONCEPT_ISSUES
44 && variant_guard_pseudoalphabet<other_t>
49 template <
typename lhs_t,
typename rhs_t,
bool lhs_rhs_switched,
typename ... alternative_types>
50 inline constexpr
bool variant_comparison_guard =
51 (instantiate_if_v<lazy<weakly_equality_comparable_with_trait, rhs_t, alternative_types>,
52 (std::same_as<lhs_t, alphabet_variant<alternative_types...>>) &&
53 (variant_general_guard<rhs_t, alternative_types...>) &&
54 !(lhs_rhs_switched && is_type_specialisation_of_v<rhs_t, alphabet_variant>)
120 template <
typename ...alternative_types>
122 requires (detail::writable_constexpr_alphabet<alternative_types> && ...) &&
123 (std::regular<alternative_types> && ...) &&
124 (
sizeof...(alternative_types) >= 2)
128 (static_cast<size_t>(alphabet_size<alternative_types>) + ...),
135 (
static_cast<size_t>(alphabet_size<alternative_types>) + ...),
143 static_assert(((seqan3::list_traits::count<alternative_types, alternatives> == 1) && ... &&
true),
144 "All types in a alphabet_variant must be distinct.");
165 using seqan3_recursive_required_types =
167 detail::transformation_trait_or_t<detail::recursive_required_types<alternative_types>,
177 template <
typename alternative_t>
201 template <typename alternative_t>
206 detail::transformation_trait_or_t<detail::recursive_required_types<alternative_t>,
type_list<>>>) &&
232 template <
typename indirect_alternative_t>
234 requires ((detail::instantiate_if_v<
235 detail::lazy<std::is_convertible, indirect_alternative_t, alternative_types>,
236 detail::variant_general_guard<indirect_alternative_t, alternative_types...>> || ...))
240 using alternative_predicate = detail::implicitly_convertible_from<indirect_alternative_t>;
263 template <
typename indirect_alternative_t>
265 requires ((!(detail::instantiate_if_v<
266 detail::lazy<std::is_convertible, indirect_alternative_t, alternative_types>,
267 detail::variant_general_guard<indirect_alternative_t, alternative_types...>> || ...)) &&
268 (detail::instantiate_if_v<
269 detail::lazy<std::is_constructible, alternative_types, indirect_alternative_t>,
270 detail::variant_general_guard<indirect_alternative_t, alternative_types...>> || ...))
274 using alternative_predicate = detail::constructible_from<indirect_alternative_t>;
292 template <
typename indirect_alternative_t>
294 requires (detail::variant_general_guard<indirect_alternative_t, alternative_types...> &&
299 using alternative_predicate = detail::assignable_from<indirect_alternative_t>;
303 alternative_t alternative{};
319 template <
size_t index>
322 static_assert(index <
alphabet_size,
"The alphabet_variant contains less alternatives than you are checking.");
323 return (
to_rank() >= partial_sum_sizes[index]) && (
to_rank() < partial_sum_sizes[index + 1]);
332 template <
size_t index>
335 return convert_impl<index, true>();
343 template <
size_t index>
346 return convert_impl<index, false>();
358 template <
typename alternative_t>
364 constexpr
size_t index = seqan3::list_traits::find<alternative_t, alternatives>;
365 return holds_alternative<index>();
374 template <
typename alternative_t>
380 constexpr
size_t index = seqan3::list_traits::find<alternative_t, alternatives>;
381 return convert_impl<index, true>();
389 template <
typename alternative_t>
395 constexpr
size_t index = seqan3::list_traits::find<alternative_t, alternatives>;
396 return convert_impl<index, false>();
422 template <
typename alphabet_variant_t,
typename indirect_alternative_type>
423 friend constexpr
auto operator==(alphabet_variant_t
const lhs, indirect_alternative_type
const rhs) noexcept
425 indirect_alternative_type,
427 alternative_types...>,
430 using alternative_predicate = detail::weakly_equality_comparable_with_<indirect_alternative_type>;
434 return lhs.template holds_alternative<alternative_t>() && (lhs.template convert_unsafely_to<alternative_t>() == rhs);
438 template <
typename alphabet_variant_t,
typename indirect_alternative_type>
439 friend constexpr
auto operator!=(alphabet_variant_t
const lhs, indirect_alternative_type
const rhs) noexcept
441 indirect_alternative_type,
443 alternative_types...>,
446 return !(lhs == rhs);
450 template <
typename alphabet_variant_t,
typename indirect_alternative_type,
typename =
void>
451 friend constexpr
auto operator==(indirect_alternative_type
const lhs, alphabet_variant_t
const rhs) noexcept
453 indirect_alternative_type,
455 alternative_types...>,
462 template <
typename alphabet_variant_t,
typename indirect_alternative_type,
typename =
void>
463 friend constexpr
auto operator!=(indirect_alternative_type
const lhs, alphabet_variant_t
const rhs) noexcept
465 indirect_alternative_type,
467 alternative_types...>,
481 return first_valid_char_table[
static_cast<index_t
>(chr)] <
sizeof...(alternative_types);
491 template <
size_t index,
bool throws>
492 constexpr
auto convert_impl() const noexcept(!throws) ->
seqan3::list_traits::
at<index, alternatives>
494 static_assert(index <
alphabet_size,
"The alphabet_variant contains less alternatives than you are checking.");
497 if constexpr (
throws)
499 if (!holds_alternative<index>())
515 static constexpr
std::array<
rank_type,
sizeof...(alternative_types) + 1> partial_sum_sizes = []() constexpr
517 constexpr
size_t N =
sizeof...(alternative_types) + 1;
520 for (
size_t i = 1u; i < N; ++i)
521 partial_sum[i] += partial_sum[i-1];
532 auto assign_rank_to_char = [](
auto alternative,
size_t rank) constexpr
537 auto assign_value_to_char = [assign_rank_to_char] (
auto alternative,
auto & value_to_char,
auto & value) constexpr
539 using alternative_t =
std::decay_t<decltype(alternative)>;
540 for (
size_t i = 0u; i < seqan3::alphabet_size<alternative_t>; ++i, ++value)
541 value_to_char[value] = assign_rank_to_char(alternative, i);
551 ((assign_value_to_char(alternative_types{}, value_to_char, value)),...);
553 return value_to_char;
560 template <
size_t index,
typename alternative_t>
562 requires (is_alternative<alternative_t>())
564 static constexpr
rank_type rank_by_index_(alternative_t const & alternative) noexcept
573 template <
typename alternative_t>
575 requires (is_alternative<alternative_t>())
577 static constexpr
rank_type rank_by_type_(alternative_t const & alternative) noexcept
579 constexpr
size_t index = seqan3::list_traits::find<alternative_t, alternatives>;
580 return rank_by_index_<index>(alternative);
586 static constexpr
auto first_valid_char_table
590 constexpr
size_t alternative_size =
sizeof...(alternative_types);
591 constexpr
size_t table_size = detail::size_in_values_v<char_type>;
592 using first_alphabet_t = detail::min_viable_uint_t<alternative_size>;
596 for (
size_t i = 0u; i < table_size; ++i)
602 #if defined(__cpp_lib_constexpr_algorithms) && __cpp_lib_constexpr_algorithms >= 201806L
604 auto found_it =
std::find(valid_chars.begin(), valid_chars.end(),
true);
605 lookup_table[i] = found_it - valid_chars.begin();
607 size_t found_index = 0u;
608 for (; found_index < valid_chars.size() && !valid_chars[found_index]; ++found_index);
609 lookup_table[i] = found_index;
620 constexpr
size_t alternative_size =
sizeof...(alternative_types);
621 constexpr
size_t table_size = detail::size_in_values_v<char_type>;
625 for (
size_t i = 0u; i < table_size; ++i)
632 char_to_rank[i] = first_valid_char_table[i] < alternative_size ? ranks[first_valid_char_table[i]] : 0;
646 return rank_to_char_table[rank];
658 return char_to_rank_table[
static_cast<index_t
>(chr)];
Provides seqan3::alphabet_base.
A CRTP-base that makes defining a custom alphabet easier.
Definition: alphabet_base.hpp:81
constexpr char_type to_char() const noexcept
Return the letter as a character of char_type.
Definition: alphabet_base.hpp:139
constexpr rank_type to_rank() const noexcept
Return the letter's numeric value (rank in the alphabet).
Definition: alphabet_base.hpp:185
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:104
static constexpr detail::min_viable_uint_t< size > alphabet_size
The size of the alphabet, i.e. the number of different values it can take.
Definition: alphabet_base.hpp:276
constexpr alphabet_variant< alternative_types... > & assign_rank(rank_type const c) noexcept
Assign from a numeric value.
Definition: alphabet_base.hpp:264
std::conditional_t< std::same_as< char, void >, char, char > char_type
The char representation; conditional needed to make semi alphabet definitions legal.
Definition: alphabet_base.hpp:96
A combined alphabet that can hold values of either of its alternatives.
Definition: alphabet_variant.hpp:131
static constexpr bool char_is_valid(char_type const chr) noexcept
Validate whether a character is valid in the combined alphabet.
Definition: alphabet_variant.hpp:478
static constexpr bool is_alternative() noexcept
Returns true if alternative_t is one of the given alternative types.
Definition: alphabet_variant.hpp:178
constexpr bool holds_alternative() const noexcept
Whether the variant alphabet currently holds a value of the given alternative.
Definition: alphabet_variant.hpp:320
constexpr friend auto operator==(alphabet_variant_t const lhs, indirect_alternative_type const rhs) noexcept -> std::enable_if_t< detail::variant_comparison_guard< alphabet_variant_t, indirect_alternative_type, false, alternative_types... >, bool >
(In-)Equality comparison against types comparable with alternatives but not convertible to the varian...
Definition: alphabet_variant.hpp:423
constexpr friend auto operator!=(indirect_alternative_type const lhs, alphabet_variant_t const rhs) noexcept -> std::enable_if_t< detail::variant_comparison_guard< alphabet_variant_t, indirect_alternative_type, true, alternative_types... >, bool >
(In-)Equality comparison against types comparable with alternatives but not convertible to the varian...
Definition: alphabet_variant.hpp:463
constexpr friend auto operator==(indirect_alternative_type const lhs, alphabet_variant_t const rhs) noexcept -> std::enable_if_t< detail::variant_comparison_guard< alphabet_variant_t, indirect_alternative_type, true, alternative_types... >, bool >
(In-)Equality comparison against types comparable with alternatives but not convertible to the varian...
Definition: alphabet_variant.hpp:451
constexpr auto convert_to() const
Convert to the specified alphabet (throws if holds_alternative() would be false).
Definition: alphabet_variant.hpp:333
constexpr friend auto operator!=(alphabet_variant_t const lhs, indirect_alternative_type const rhs) noexcept -> std::enable_if_t< detail::variant_comparison_guard< alphabet_variant_t, indirect_alternative_type, false, alternative_types... >, bool >
(In-)Equality comparison against types comparable with alternatives but not convertible to the varian...
Definition: alphabet_variant.hpp:439
constexpr alphabet_variant() noexcept=default
Defaulted.
constexpr alternative_t convert_to() const
Convert to the specified alphabet (throws if holds_alternative() would be false).
Definition: alphabet_variant.hpp:375
constexpr auto convert_unsafely_to() const noexcept
Convert to the specified alphabet (undefined behaviour if holds_alternative() would be false).
Definition: alphabet_variant.hpp:344
constexpr alternative_t convert_unsafely_to() const noexcept
Convert to the specified alphabet (undefined behaviour if holds_alternative() would be false).
Definition: alphabet_variant.hpp:390
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:523
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:384
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:291
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:155
decltype(detail::concat(lists_t{}...)) concat
Join two seqan3::type_list s into one.
Definition: traits.hpp:329
constexpr bool contains
Whether a type occurs in a type list or not.
Definition: traits.hpp:231
typename decltype(detail::at< idx >(list_t{}))::type at
Return the type at given index from the type list.
Definition: traits.hpp:260
constexpr ptrdiff_t find_if
Get the index of the first type in a pack that satisfies the given predicate.
Definition: traits.hpp:210
constexpr bool contains
Whether a type occurs in a pack or not.
Definition: traits.hpp:228
Resolves to std::is_assignable_v<t>.
Provides lazy template instantiation traits.
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
SeqAn specific customisations in the standard namespace.
Type that contains multiple types.
Definition: type_list.hpp:29
Provides traits for seqan3::type_list.