28namespace bio::alphabet::detail
32template <
typename other_t,
typename... alternative_types>
33concept variant_general_guard =
34 !meta::one_of<other_t, variant<alternative_types...>, alternative_types...> &&
100template <
typename... alternative_types>
101 requires((detail::writable_constexpr_alphabet<alternative_types> && ...) &&
102 (std::regular<alternative_types> && ...) && (
sizeof...(alternative_types) >= 2))
107 using base_t =
base<
variant<alternative_types...>, (
static_cast<size_t>(size<alternative_types>) + ...),
char>;
109 static_assert((std::is_same_v<char_t<alternative_types>,
char> && ...),
110 "The variant is currently only tested for alphabets with char_type char. "
111 "Contact us on GitHub if you have a different use case: https://github.com/biocpp/biocpp-core .");
119 static_assert(((meta::list_traits::count<alternative_types, alternatives> == 1) && ... &&
true),
120 "All types in a variant must be distinct.");
126 using base_t::alphabet_size;
127 using base_t::assign_rank;
128 using base_t::to_char;
129 using base_t::to_rank;
150 template <
typename alternative_t>
153 return meta::detail::pack_traits::contains<alternative_t, alternative_types...>;
173 template <typename alternative_t>
174 requires(is_alternative<alternative_t>())
175 constexpr
variant(alternative_t const alternative) noexcept
177 assign_rank(rank_by_type_(alternative));
197 template <
typename indirect_alternative_t>
198 requires(detail::variant_general_guard<indirect_alternative_t, alternative_types...> &&
199 (std::is_convertible_v<indirect_alternative_t, alternative_types> || ...))
200 constexpr variant(indirect_alternative_t
const rhs)
noexcept
202 using alternative_predicate = detail::implicitly_convertible_from<indirect_alternative_t>;
203 constexpr auto alternative_position =
204 meta::list_traits::find_if<alternative_predicate::template invoke, alternatives>;
206 assign_rank(rank_by_type_(alternative_t(rhs)));
224 template <
typename indirect_alternative_t>
225 requires(detail::variant_general_guard<indirect_alternative_t, alternative_types...> &&
226 !(std::is_convertible_v<indirect_alternative_t, alternative_types> || ...) &&
227 (std::is_constructible_v<alternative_types, indirect_alternative_t> || ...))
228 constexpr explicit variant(indirect_alternative_t
const rhs)
noexcept
230 using alternative_predicate = detail::constructible_from<indirect_alternative_t>;
231 constexpr auto alternative_position =
232 meta::list_traits::find_if<alternative_predicate::template invoke, alternatives>;
234 assign_rank(rank_by_type_(alternative_t(rhs)));
247 template <
typename indirect_alternative_t>
248 requires(detail::variant_general_guard<indirect_alternative_t, alternative_types...> &&
250 constexpr variant &
operator=(indirect_alternative_t
const & rhs)
noexcept
252 using alternative_predicate = detail::assignable_from<indirect_alternative_t>;
253 constexpr auto alternative_position =
254 meta::list_traits::find_if<alternative_predicate::template invoke, alternatives>;
256 alternative_t alternative{};
258 assign_rank(rank_by_type_(alternative));
271 template <
size_t index>
274 static_assert(index < alphabet_size,
"The variant contains less alternatives than you are checking.");
275 return (
to_rank() >= partial_sum_sizes[index]) && (
to_rank() < partial_sum_sizes[index + 1]);
283 template <
size_t index>
286 return convert_impl<index, true>();
293 template <
size_t index>
296 return convert_impl<index, false>();
307 template <
typename alternative_t>
309 requires(is_alternative<alternative_t>())
311 constexpr size_t index = meta::list_traits::find<alternative_t, alternatives>;
312 return holds_alternative<index>();
320 template <
typename alternative_t>
322 requires(is_alternative<alternative_t>())
324 constexpr size_t index = meta::list_traits::find<alternative_t, alternatives>;
325 return convert_impl<index, true>();
332 template <
typename alternative_t>
334 requires(is_alternative<alternative_t>())
336 constexpr size_t index = meta::list_traits::find<alternative_t, alternatives>;
337 return convert_impl<index, false>();
362 template <std::same_as<variant> variant_t,
typename indirect_alternative_type>
363 requires((detail::variant_general_guard<indirect_alternative_type, alternative_types...>) &&
365 friend constexpr bool operator==(variant_t
const lhs, indirect_alternative_type
const rhs)
noexcept
367 using alternative_predicate = detail::weakly_equality_comparable_with_<indirect_alternative_type>;
368 constexpr auto alternative_position =
369 meta::list_traits::find_if<alternative_predicate::template invoke, alternatives>;
371 return lhs.template holds_alternative<alternative_t>() &&
372 (lhs.template convert_unsafely_to<alternative_t>() == rhs);
382 return first_valid_char_table[
static_cast<index_t
>(chr)] <
sizeof...(alternative_types);
392 template <
size_t index,
bool throws>
393 constexpr auto convert_impl() const noexcept(!throws) -> meta::list_traits::at<index, alternatives>
395 static_assert(index < alphabet_size,
"The variant contains less alternatives than you are checking.");
398 if constexpr (
throws)
400 if (!holds_alternative<index>())
416 static constexpr std::array<rank_type,
sizeof...(alternative_types) + 1> partial_sum_sizes = []()
constexpr
418 constexpr size_t N =
sizeof...(alternative_types) + 1;
421 for (
size_t i = 1u; i < N; ++i)
422 partial_sum[i] += partial_sum[i - 1];
438 auto assign_rank_to_char = [](
auto alternative,
size_t rank)
constexpr
441 auto assign_value_to_char =
442 [assign_rank_to_char](
auto alternative,
auto & value_to_char,
auto & value)
constexpr
444 using alternative_t =
std::decay_t<
decltype(alternative)>;
445 for (
size_t i = 0u; i < bio::alphabet::size<alternative_t>; ++i, ++value)
446 value_to_char[value] = assign_rank_to_char(alternative, i);
456 ((assign_value_to_char(alternative_types{}, value_to_char, value)), ...);
458 return value_to_char;
465 template <
size_t index,
typename alternative_t>
466 requires(is_alternative<alternative_t>())
467 static constexpr rank_type rank_by_index_(alternative_t
const & alternative)
noexcept
476 template <
typename alternative_t>
477 requires(is_alternative<alternative_t>())
478 static constexpr rank_type rank_by_type_(alternative_t
const & alternative)
noexcept
480 constexpr size_t index = meta::list_traits::find<alternative_t, alternatives>;
481 return rank_by_index_<index>(alternative);
487 static constexpr auto first_valid_char_table = []()
constexpr
489 constexpr size_t alternative_size =
sizeof...(alternative_types);
490 constexpr size_t table_size = meta::detail::size_in_values_v<char_type>;
491 using first_alphabet_t = meta::detail::min_viable_uint_t<alternative_size>;
495 for (
size_t i = 0u; i < table_size; ++i)
497 char_type chr =
static_cast<char_type
>(i);
501 auto found_it =
std::find(valid_chars.begin(), valid_chars.end(),
true);
502 lookup_table[i] = found_it - valid_chars.begin();
516 constexpr size_t alternative_size =
sizeof...(alternative_types);
517 constexpr size_t table_size = meta::detail::size_in_values_v<char_type>;
521 for (
size_t i = 0u; i < table_size; ++i)
523 char_type chr =
static_cast<char_type
>(i);
528 char_to_rank[i] = first_valid_char_table[i] < alternative_size ? ranks[first_valid_char_table[i]] : 0;
Provides implementation detail for bio::alphabet::variant and bio::alphabet::tuple_base.
Provides bio::alphabet::base.
A CRTP-base that makes defining a custom alphabet easier.
Definition: base.hpp:55
A combined alphabet that can hold values of either of its alternatives..
Definition: variant.hpp:104
static constexpr bool is_alternative() noexcept
Returns true if alternative_t is one of the given alternative types.
Definition: variant.hpp:151
constexpr alternative_t convert_unsafely_to() const noexcept
Convert to the specified alphabet (undefined behaviour if holds_alternative() would be false).
Definition: variant.hpp:333
constexpr auto convert_unsafely_to() const noexcept
Convert to the specified alphabet (undefined behaviour if holds_alternative() would be false).
Definition: variant.hpp:294
constexpr variant() noexcept=default
Defaulted.
constexpr variant(indirect_alternative_t const rhs) noexcept
Constructor for arguments implicitly convertible to an alternative.
Definition: variant.hpp:200
static constexpr bool char_is_valid(char_type const chr) noexcept
Validate whether a character is valid in the combined alphabet.
Definition: variant.hpp:379
constexpr bool holds_alternative() const noexcept
Whether the variant alphabet currently holds a value of the given alternative.
Definition: variant.hpp:308
constexpr variant(indirect_alternative_t const rhs) noexcept
Constructor for arguments explicitly (but not implicitly) convertible to an alternative.
Definition: variant.hpp:228
constexpr bool holds_alternative() const noexcept
Whether the variant alphabet currently holds a value of the given alternative.
Definition: variant.hpp:272
constexpr auto convert_to() const
Convert to the specified alphabet (throws if holds_alternative() would be false).
Definition: variant.hpp:284
constexpr alternative_t convert_to() const
Convert to the specified alphabet (throws if holds_alternative() would be false).
Definition: variant.hpp:321
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:192
constexpr auto assign_char_to
Assign a char to an alphabet object.
Definition: concept.hpp:260
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:70
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:138
typename transformation_trait_or< type_t, default_t >::type transformation_trait_or_t
Helper type of bio::meta::transformation_trait_or (transformation_trait shortcut).
Definition: transformation_trait_or.hpp:53
The alphabet module's namespace.
Definition: aa10li.hpp:23
Provides traits for meta::type_list.