23 #include <meta/meta.hpp>
32 namespace seqan3::detail
35 #if SEQAN3_WORKAROUND_GCC7_AND_8_CONCEPT_ISSUES
37 SEQAN3_CONCEPT variant_guard_pseudoalphabet = requires { requires seqan3::alphabet_size<t> > 0; };
41 template <
typename other_t,
typename ... alternative_types>
42 inline constexpr
bool variant_general_guard =
43 (!std::same_as<other_t, alphabet_variant<alternative_types...>>) &&
45 (!(std::same_as<other_t, alternative_types> || ...)) &&
47 #if SEQAN3_WORKAROUND_GCC7_AND_8_CONCEPT_ISSUES
48 && variant_guard_pseudoalphabet<other_t>
53 template <
typename lhs_t,
typename rhs_t,
bool lhs_rhs_switched,
typename ... alternative_types>
54 inline constexpr
bool variant_comparison_guard =
55 (instantiate_if_v<lazy<weakly_equality_comparable_with_trait, rhs_t, alternative_types>,
56 (std::same_as<lhs_t, alphabet_variant<alternative_types...>>) &&
57 (variant_general_guard<rhs_t, alternative_types...>) &&
58 !(lhs_rhs_switched && is_type_specialisation_of_v<rhs_t, alphabet_variant>)
122 template <
typename ...alternative_types>
124 requires (detail::writable_constexpr_alphabet<alternative_types> && ...) &&
125 (std::regular<alternative_types> && ...) &&
126 (
sizeof...(alternative_types) >= 2)
130 (static_cast<size_t>(alphabet_size<alternative_types>) + ...),
137 (
static_cast<size_t>(alphabet_size<alternative_types>) + ...),
143 using alternatives = meta::list<alternative_types...>;
145 static_assert(std::same_as<alternatives, meta::unique<alternatives>>,
146 "All types in a alphabet_variant must be distinct.");
158 using seqan3_required_types =
type_list<alternative_types...>;
161 using seqan3_recursive_required_types =
163 detail::transformation_trait_or_t<detail::recursive_required_types<alternative_types>,
171 template <
typename alternative_t>
174 return detail::type_in_pack_v<alternative_t, alternative_types...>;
193 template <typename alternative_t>
198 detail::transformation_trait_or_t<detail::recursive_required_types<alternative_t>,
type_list<>>>) &&
222 template <
typename indirect_alternative_t>
224 requires ((detail::instantiate_if_v<
225 detail::lazy<std::is_convertible, indirect_alternative_t, alternative_types>,
226 detail::variant_general_guard<indirect_alternative_t, alternative_types...>> || ...))
233 detail::implicitly_convertible_from<indirect_alternative_t>>>(rhs)));
250 template <
typename indirect_alternative_t>
252 requires ((!(detail::instantiate_if_v<
253 detail::lazy<std::is_convertible, indirect_alternative_t, alternative_types>,
254 detail::variant_general_guard<indirect_alternative_t, alternative_types...>> || ...)) &&
255 (detail::instantiate_if_v<
256 detail::lazy<std::is_constructible, alternative_types, indirect_alternative_t>,
257 detail::variant_general_guard<indirect_alternative_t, alternative_types...>> || ...))
262 detail::constructible_from<indirect_alternative_t>>>(rhs)));
274 template <
typename indirect_alternative_t>
276 requires (detail::variant_general_guard<indirect_alternative_t, alternative_types...> &&
281 using alternative_t = meta::front<meta::find_if<alternatives, detail::assignable_from<indirect_alternative_t>>>;
282 alternative_t alternative{};
294 template <
size_t index>
297 static_assert(index <
alphabet_size,
"The alphabet_variant contains less alternatives than you are checking.");
298 return (
to_rank() >= partial_sum_sizes[index]) && (
to_rank() < partial_sum_sizes[index + 1]);
305 template <
size_t index>
308 return convert_impl<index, true>();
314 template <
size_t index>
317 return convert_impl<index, false>();
327 template <
typename alternative_t>
333 constexpr
size_t index = meta::find_index<alternatives, alternative_t>::value;
334 return is_alternative<index>();
341 template <
typename alternative_t>
347 constexpr
size_t index = meta::find_index<alternatives, alternative_t>::value;
348 return convert_impl<index, true>();
354 template <
typename alternative_t>
360 constexpr
size_t index = meta::find_index<alternatives, alternative_t>::value;
361 return convert_impl<index, false>();
385 template <
typename alphabet_variant_t,
typename indirect_alternative_type>
386 friend constexpr
auto operator==(alphabet_variant_t
const lhs, indirect_alternative_type
const rhs) noexcept
388 indirect_alternative_type,
390 alternative_types...>,
393 using alternative_t =
395 detail::weakly_equality_comparable_with_<indirect_alternative_type>>>;
396 return lhs.template is_alternative<alternative_t>() && (lhs.template convert_unsafely_to<alternative_t>() == rhs);
400 template <
typename alphabet_variant_t,
typename indirect_alternative_type>
401 friend constexpr
auto operator!=(alphabet_variant_t
const lhs, indirect_alternative_type
const rhs) noexcept
403 indirect_alternative_type,
405 alternative_types...>,
408 return !(lhs == rhs);
412 template <
typename alphabet_variant_t,
typename indirect_alternative_type,
typename =
void>
413 friend constexpr
auto operator==(indirect_alternative_type
const lhs, alphabet_variant_t
const rhs) noexcept
415 indirect_alternative_type,
417 alternative_types...>,
424 template <
typename alphabet_variant_t,
typename indirect_alternative_type,
typename =
void>
425 friend constexpr
auto operator!=(indirect_alternative_type
const lhs, alphabet_variant_t
const rhs) noexcept
427 indirect_alternative_type,
429 alternative_types...>,
439 bool is_valid{
false};
441 meta::for_each(alternatives{}, [&] (
auto && alt)
457 template <
size_t index,
bool throws>
458 constexpr
auto convert_impl() const noexcept(!throws) -> meta::at_c<alternatives, index>
460 static_assert(index <
alphabet_size,
"The alphabet_variant contains less alternatives than you are checking.");
461 using alternative_t = meta::at_c<alternatives, index>;
463 if constexpr (
throws)
465 if (!is_alternative<index>())
481 static constexpr
std::array<
rank_type,
sizeof...(alternative_types) + 1> partial_sum_sizes = []() constexpr
483 constexpr
size_t N =
sizeof...(alternative_types) + 1;
486 for (
size_t i = 1u; i < N; ++i)
487 partial_sum[i] += partial_sum[i-1];
504 auto assign_rank_to_char = [](
auto alternative,
size_t rank) constexpr
509 auto assign_value_to_char = [assign_rank_to_char] (
auto alternative,
auto & value_to_char,
auto & value) constexpr
511 using alternative_t =
std::decay_t<decltype(alternative)>;
512 for (
size_t i = 0u; i < seqan3::alphabet_size<alternative_t>; ++i, ++value)
513 value_to_char[value] = assign_rank_to_char(alternative, i);
523 ((assign_value_to_char(alternative_types{}, value_to_char, value)),...);
525 return value_to_char;
532 template <
size_t index,
typename alternative_t>
534 requires (holds_alternative<alternative_t>())
536 static constexpr
rank_type rank_by_index_(alternative_t const & alternative) noexcept
545 template <
typename alternative_t>
547 requires (holds_alternative<alternative_t>())
549 static constexpr
rank_type rank_by_type_(alternative_t const & alternative) noexcept
551 constexpr
size_t index = meta::find_index<alternatives, alternative_t>::value;
552 return rank_by_index_<index>(alternative);
564 constexpr
size_t table_size = detail::size_in_values_v<char_type>;
568 for (
size_t i = 0u; i < table_size; ++i)
571 bool there_was_no_valid_representation{
true};
573 meta::for_each(alternatives{}, [&] (
auto && alt)
577 if (there_was_no_valid_representation && char_is_valid_for<alt_type>(chr))
579 there_was_no_valid_representation =
false;
584 if (there_was_no_valid_representation)
585 char_to_rank[i] = rank_by_type_(
assign_char_to(chr, meta::front<alternatives>{}));
Provides seqan3::alphabet_base.
A CRTP-base that makes defining a custom alphabet easier.
Definition: alphabet_base.hpp:54
constexpr char_type to_char() const noexcept
Return the letter as a character of char_type.
Definition: alphabet_base.hpp:96
constexpr rank_type to_rank() const noexcept
Return the letter's numeric value (rank in the alphabet).
Definition: alphabet_base.hpp:118
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:64
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:176
constexpr alphabet_variant< alternative_types... > & assign_rank(rank_type const c) noexcept
Assign from a numeric value.
Definition: alphabet_base.hpp:167
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:62
A combined alphabet that can hold values of either of its alternatives.
Definition: alphabet_variant.hpp:133
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:437
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:386
constexpr bool is_alternative() const noexcept
Whether the variant alphabet currently holds a value of the given alternative.
Definition: alphabet_variant.hpp:295
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:425
static constexpr bool holds_alternative() noexcept
Returns true if alternative_t is one of the given alternative types.
Definition: alphabet_variant.hpp:172
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:413
constexpr auto convert_to() const
Convert to the specified alphabet (throws if is_alternative() would be false).
Definition: alphabet_variant.hpp:306
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:401
constexpr alphabet_variant() noexcept=default
Defaulted.
constexpr alternative_t convert_to() const
Convert to the specified alphabet (throws if is_alternative() would be false).
Definition: alphabet_variant.hpp:342
constexpr auto convert_unsafely_to() const noexcept
Convert to the specified alphabet (undefined behaviour if is_alternative() would be false).
Definition: alphabet_variant.hpp:315
constexpr alternative_t convert_unsafely_to() const noexcept
Convert to the specified alphabet (undefined behaviour if is_alternative() would be false).
Definition: alphabet_variant.hpp:355
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:417
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:321
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:239
constexpr auto char_is_valid_for
Returns whether a character is in the valid set of a seqan3::alphabet (usually implies a bijective ma...
Definition: concept.hpp:522
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:143
meta::list< types... > type_list
Type that contains multiple types, an alias for meta::list.
Definition: type_list.hpp:31
decltype(detail::concat(lists_t{}...)) concat
Join two seqan3::type_list s into one.
Definition: traits.hpp:592
constexpr bool contains
Whether a type occurs in a type list or not.
Definition: traits.hpp:495
typename decltype(detail::front< pack_t... >())::type front
Return the first type from the type pack.
Definition: traits.hpp:240
constexpr ptrdiff_t find_if
Get the index of the first type in a pack that satisfies the given predicate.
Definition: traits.hpp:175
constexpr bool contains
Whether a type occurs in a pack or not.
Definition: traits.hpp:193
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.
typename remove_cvref< t >::type remove_cvref_t
Return the input type with const, volatile and references removed (transformation_trait shortcut).
Definition: type_traits:56
Provides unary type traits on a set of types, usually provided as template argument pack.
Provides traits for seqan3::type_list.
Provides utility functions for tuple like interfaces.