18 #include <meta/meta.hpp>
34 namespace seqan3::detail
38 template <
typename tuple_derived_t,
typename rhs_t,
typename ... component_types>
39 inline constexpr
bool tuple_general_guard =
41 (!
std::same_as<rhs_t, alphabet_tuple_base<component_types...>>) &&
42 (!std::is_base_of_v<tuple_derived_t, rhs_t>) &&
48 template <
typename lhs_t,
typename tuple_derived_t,
typename rhs_t,
typename ... component_types>
49 inline constexpr
bool tuple_eq_guard =
50 (instantiate_if_v<lazy<weakly_equality_comparable_with_trait, rhs_t, component_types>,
52 tuple_general_guard<tuple_derived_t, rhs_t, component_types...>
56 template <
typename lhs_t,
typename tuple_derived_t,
typename rhs_t,
typename ... component_types>
57 inline constexpr
bool tuple_order_guard =
58 (instantiate_if_v<lazy<weakly_ordered_with_trait, rhs_t, component_types>,
60 tuple_general_guard<lhs_t, tuple_derived_t, rhs_t, component_types...>
114 template <typename derived_type,
115 typename ...component_types>
117 requires (detail::writable_constexpr_semialphabet<component_types> && ...) &&
128 (1 * ... * alphabet_size<component_types>),
132 using component_list = meta::list<component_types...>;
135 template <
typename type>
136 static constexpr
bool is_component =
137 meta::in<component_list, type>::value;
140 template <
typename type>
141 static constexpr
bool is_unique_component =
142 is_component<type> &&
143 (meta::find_index<component_list, type>::value == meta::reverse_find_index<component_list, type>::value);
149 template <
typename alphabet_type,
size_t index>
150 class component_proxy :
public alphabet_proxy<component_proxy<alphabet_type, index>, alphabet_type>
162 constexpr
void on_update() noexcept
164 parent->assign_component_rank<index>(
to_rank());
169 using base_t::operator=;
174 component_proxy() =
delete;
176 constexpr component_proxy(component_proxy
const &) =
default;
177 constexpr component_proxy(component_proxy &&) =
default;
178 constexpr component_proxy & operator=(component_proxy
const &) =
default;
179 constexpr component_proxy & operator=(component_proxy &&) =
default;
180 ~component_proxy() =
default;
199 friend constexpr
bool operator==(derived_type
const lhs, component_proxy
const rhs) noexcept
201 return get<index>(lhs) == static_cast<alphabet_type>(rhs);
205 friend constexpr
bool operator==(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
211 friend constexpr
bool operator!=(derived_type
const lhs, component_proxy
const rhs) noexcept
213 return get<index>(lhs) != static_cast<alphabet_type>(rhs);
217 friend constexpr
bool operator!=(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
223 friend constexpr
bool operator<(derived_type
const lhs, component_proxy
const rhs) noexcept
225 return get<index>(lhs) < static_cast<alphabet_type>(rhs);
229 friend constexpr
bool operator<(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
235 friend constexpr
bool operator<=(derived_type
const lhs, component_proxy
const rhs) noexcept
237 return get<index>(lhs) <= static_cast<alphabet_type>(rhs);
241 friend constexpr
bool operator<=(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
247 friend constexpr
bool operator>(derived_type
const lhs, component_proxy
const rhs) noexcept
249 return get<index>(lhs) > static_cast<alphabet_type>(rhs);
253 friend constexpr
bool operator>(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
259 friend constexpr
bool operator>=(derived_type
const lhs, component_proxy
const rhs) noexcept
261 return get<index>(lhs) >= static_cast<alphabet_type>(rhs);
265 friend constexpr
bool operator>=(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
281 using base_t::base_t;
295 using base_t::assign_rank;
299 using seqan3_required_types = component_list;
302 using seqan3_recursive_required_types =
304 detail::transformation_trait_or_t<detail::recursive_required_types<component_types>,
308 static constexpr
bool seqan3_alphabet_tuple_base_specialisation =
true;
331 template <
typename component_type>
333 requires (!std::is_base_of_v<alphabet_tuple_base, component_type>) &&
334 is_unique_component<component_type>
338 get<component_type>(*
this) = alph;
354 template <
typename indirect_component_type>
356 requires ((detail::instantiate_if_v<
357 detail::lazy<std::is_convertible, indirect_component_type, component_types>,
358 detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>> || ...))
362 using component_type = meta::front<meta::find_if<component_list, detail::implicitly_convertible_from<indirect_component_type>>>;
363 component_type tmp(alph);
364 get<component_type>(*
this) = tmp;
368 template <
typename indirect_component_type>
369 requires ((!(detail::instantiate_if_v<
370 detail::lazy<std::is_convertible, indirect_component_type, component_types>,
371 detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>> || ...)) &&
372 (detail::instantiate_if_v<
373 detail::lazy<std::is_constructible, component_types, indirect_component_type>,
374 detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>> || ...))
375 constexpr explicit alphabet_tuple_base(indirect_component_type const alph) noexcept : alphabet_tuple_base{}
377 using component_type = meta::front<meta::find_if<component_list, detail::constructible_from<indirect_component_type>>>;
378 component_type tmp(alph);
379 get<component_type>(*
this) = tmp;
391 template <
typename component_type>
394 is_unique_component<component_type>
396 constexpr derived_type &
operator=(component_type
const alph) noexcept
398 get<component_type>(*
this) = alph;
399 return static_cast<derived_type &>(*
this);
411 template <
typename indirect_component_type>
414 (!is_unique_component<indirect_component_type>) &&
417 constexpr derived_type & operator=(indirect_component_type const alph) noexcept
419 using component_type = meta::front<meta::find_if<component_list, detail::assignable_from<indirect_component_type>>>;
420 get<component_type>(*
this) = alph;
421 return static_cast<derived_type &>(*
this);
425 template <
typename indirect_component_type>
427 (!is_unique_component<indirect_component_type>) &&
430 constexpr derived_type & operator=(indirect_component_type const alph) noexcept
432 using component_type = meta::front<meta::find_if<component_list, detail::implicitly_convertible_from<indirect_component_type>>>;
433 component_type tmp(alph);
434 get<component_type>(*
this) = tmp;
435 return static_cast<derived_type &>(*
this);
438 template <
typename indirect_component_type>
440 (!is_unique_component<indirect_component_type>) &&
444 constexpr derived_type & operator=(indirect_component_type const alph) noexcept
446 using component_type = meta::front<meta::find_if<component_list, detail::constructible_from<indirect_component_type>>>;
447 component_type tmp(alph);
448 get<component_type>(*
this) = tmp;
449 return static_cast<derived_type &>(*
this);
462 template <
size_t index>
465 static_assert(index <
sizeof...(component_types),
"Index out of range.");
467 using t = meta::at_c<component_list, index>;
472 return component_proxy<t, index>{val, l};
479 template <
typename type>
482 requires is_unique_component<type>
485 return get<meta::find_index<component_list, type>::value>(l);
492 template <
size_t index>
495 static_assert(index <
sizeof...(component_types),
"Index out of range.");
497 using t = meta::at_c<component_list, index>;
506 template <
typename type>
509 requires is_unique_component<type>
512 return get<meta::find_index<component_list, type>::value>(l);
517 template <
typename type>
518 constexpr
operator type() const noexcept
520 requires is_unique_component<type>
523 return get<type>(*
this);
542 template <
typename derived_type_t,
typename indirect_component_type>
543 friend constexpr
auto operator==(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
544 ->
std::enable_if_t<detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
547 using component_type = meta::front<meta::find_if<component_list, detail::weakly_equality_comparable_with_<indirect_component_type>>>;
548 return get<component_type>(lhs) == rhs;
552 template <
typename derived_type_t,
typename indirect_component_type>
553 friend constexpr
auto operator==(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
554 ->
std::enable_if_t<detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
561 template <
typename derived_type_t,
typename indirect_component_type>
562 friend constexpr
auto operator!=(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
563 ->
std::enable_if_t<detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
566 using component_type = meta::front<meta::find_if<component_list, detail::weakly_equality_comparable_with_<indirect_component_type>>>;
567 return get<component_type>(lhs) != rhs;
571 template <
typename derived_type_t,
typename indirect_component_type>
572 friend constexpr
auto operator!=(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
573 ->
std::enable_if_t<detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
580 template <
typename derived_type_t,
typename indirect_component_type>
581 friend constexpr
auto operator<(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
582 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
585 using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with_<indirect_component_type>>>;
586 return get<component_type>(lhs) < rhs;
590 template <
typename derived_type_t,
typename indirect_component_type>
591 friend constexpr
auto operator<(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
592 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
599 template <
typename derived_type_t,
typename indirect_component_type>
600 friend constexpr
auto operator<=(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
601 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
604 using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with_<indirect_component_type>>>;
605 return get<component_type>(lhs) <= rhs;
609 template <
typename derived_type_t,
typename indirect_component_type>
610 friend constexpr
auto operator<=(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
611 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
618 template <
typename derived_type_t,
typename indirect_component_type>
619 friend constexpr
auto operator>(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
620 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
623 using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with_<indirect_component_type>>>;
624 return get<component_type>(lhs) > rhs;
628 template <
typename derived_type_t,
typename indirect_component_type>
629 friend constexpr
auto operator>(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
630 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
637 template <
typename derived_type_t,
typename indirect_component_type>
638 friend constexpr
auto operator>=(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
639 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
642 using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with_<indirect_component_type>>>;
643 return get<component_type>(lhs) >= rhs;
647 template <
typename derived_type_t,
typename indirect_component_type>
648 friend constexpr
auto operator>=(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
649 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
658 template <
size_t index>
659 constexpr rank_type to_component_rank() const noexcept
663 return rank_to_component_rank[index][
to_rank()];
667 return (
to_rank() / cummulative_alph_sizes[index]) %
673 template <
size_t index>
674 constexpr
void assign_component_rank(ptrdiff_t
const r) noexcept
676 assign_rank(static_cast<ptrdiff_t>(
to_rank()) +
677 ((r - static_cast<ptrdiff_t>(to_component_rank<index>())) *
678 static_cast<ptrdiff_t>(cummulative_alph_sizes[index])));
690 meta::for_each(meta::reverse<component_list>{}, [&] (
auto alph) constexpr
711 return ((
seqan3::to_rank(components) * cummulative_alph_sizes[idx]) + ...);
716 list_traits::size<component_list>> rank_to_component_rank
721 list_traits::size<component_list>> ret{};
727 for (
size_t i = 0; i < list_traits::size<component_list>; ++i)
728 for (
size_t j = 0; j < static_cast<size_t>(
alphabet_size); ++j)
729 ret[i][j] = (j / cummulative_alph_sizes[i]) % alph_sizes[i];
747 template <std::
size_t i, seqan3::detail::alphabet_tuple_base_specialisation tuple_t>
748 struct tuple_element<i, tuple_t>
751 using type = meta::at_c<typename tuple_t::seqan3_required_types, i>;
759 template <seqan3::detail::alphabet_tuple_base_specialisation tuple_t>
760 struct tuple_size<tuple_t> :