18 #include <meta/meta.hpp>
30 namespace seqan3::detail
34 template <
typename tuple_derived_t,
typename rhs_t,
typename ... component_types>
35 inline constexpr
bool tuple_general_guard =
36 (!std::same_as<rhs_t, tuple_derived_t>) &&
37 (!std::same_as<rhs_t, alphabet_tuple_base<component_types...>>) &&
38 (!std::is_base_of_v<tuple_derived_t, rhs_t>) &&
39 (!(std::same_as<rhs_t, component_types> || ...)) &&
44 template <
typename lhs_t,
typename tuple_derived_t,
typename rhs_t,
typename ... component_types>
45 inline constexpr
bool tuple_eq_guard =
46 (instantiate_if_v<lazy<weakly_equality_comparable_with_trait, rhs_t, component_types>,
47 std::same_as<lhs_t, tuple_derived_t> &&
48 tuple_general_guard<tuple_derived_t, rhs_t, component_types...>
52 template <
typename lhs_t,
typename tuple_derived_t,
typename rhs_t,
typename ... component_types>
53 inline constexpr
bool tuple_order_guard =
54 (instantiate_if_v<lazy<weakly_ordered_with_trait, rhs_t, component_types>,
55 std::same_as<lhs_t, tuple_derived_t> &&
56 tuple_general_guard<lhs_t, tuple_derived_t, rhs_t, component_types...>
110 template <typename derived_type,
111 typename ...component_types>
113 requires (detail::writable_constexpr_semialphabet<component_types> && ...) &&
114 (
std::regular<component_types> && ...)
124 (1 * ... * alphabet_size<component_types>),
128 using component_list = meta::list<component_types...>;
131 template <
typename type>
132 static constexpr
bool is_component =
133 meta::in<component_list, type>::value;
136 template <
typename type>
137 static constexpr
bool is_unique_component =
138 is_component<type> &&
139 (meta::find_index<component_list, type>::value == meta::reverse_find_index<component_list, type>::value);
145 template <
typename alphabet_type,
size_t index>
146 class component_proxy :
public alphabet_proxy<component_proxy<alphabet_type, index>, alphabet_type>
158 constexpr
void on_update() noexcept
160 parent->assign_component_rank<index>(
to_rank());
165 using base_t::operator=;
170 component_proxy() =
delete;
172 constexpr component_proxy(component_proxy
const &) =
default;
173 constexpr component_proxy(component_proxy &&) =
default;
174 constexpr component_proxy & operator=(component_proxy
const &) =
default;
175 constexpr component_proxy & operator=(component_proxy &&) =
default;
176 ~component_proxy() =
default;
195 friend constexpr
bool operator==(derived_type
const lhs, component_proxy
const rhs) noexcept
197 return get<index>(lhs) ==
static_cast<alphabet_type
>(rhs);
201 friend constexpr
bool operator==(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
207 friend constexpr
bool operator!=(derived_type
const lhs, component_proxy
const rhs) noexcept
209 return get<index>(lhs) !=
static_cast<alphabet_type
>(rhs);
213 friend constexpr
bool operator!=(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
219 friend constexpr
bool operator<(derived_type
const lhs, component_proxy
const rhs) noexcept
221 return get<index>(lhs) <
static_cast<alphabet_type
>(rhs);
225 friend constexpr
bool operator<(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
231 friend constexpr
bool operator<=(derived_type
const lhs, component_proxy
const rhs) noexcept
233 return get<index>(lhs) <=
static_cast<alphabet_type
>(rhs);
237 friend constexpr
bool operator<=(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
243 friend constexpr
bool operator>(derived_type
const lhs, component_proxy
const rhs) noexcept
245 return get<index>(lhs) >
static_cast<alphabet_type
>(rhs);
249 friend constexpr
bool operator>(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
255 friend constexpr
bool operator>=(derived_type
const lhs, component_proxy
const rhs) noexcept
257 return get<index>(lhs) >=
static_cast<alphabet_type
>(rhs);
261 friend constexpr
bool operator>=(component_proxy<alphabet_type, index>
const lhs, derived_type
const rhs) noexcept
277 using base_t::base_t;
291 using base_t::assign_rank;
295 using seqan3_required_types = component_list;
298 using seqan3_recursive_required_types =
300 detail::transformation_trait_or_t<detail::recursive_required_types<component_types>,
304 static constexpr
bool seqan3_alphabet_tuple_base_specialisation =
true;
327 template <
typename component_type>
329 requires (!std::is_base_of_v<alphabet_tuple_base, component_type>) &&
330 is_unique_component<component_type>
334 get<component_type>(*
this) = alph;
350 template <
typename indirect_component_type>
352 requires ((detail::instantiate_if_v<
353 detail::lazy<std::is_convertible, indirect_component_type, component_types>,
354 detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>> || ...))
358 using component_type = meta::front<meta::find_if<component_list, detail::implicitly_convertible_from<indirect_component_type>>>;
359 component_type tmp(alph);
360 get<component_type>(*
this) = tmp;
364 template <
typename indirect_component_type>
365 requires ((!(detail::instantiate_if_v<
366 detail::lazy<std::is_convertible, indirect_component_type, component_types>,
367 detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>> || ...)) &&
368 (detail::instantiate_if_v<
369 detail::lazy<std::is_constructible, component_types, indirect_component_type>,
370 detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>> || ...))
371 constexpr explicit alphabet_tuple_base(indirect_component_type const alph) noexcept : alphabet_tuple_base{}
373 using component_type = meta::front<meta::find_if<component_list, detail::constructible_from<indirect_component_type>>>;
374 component_type tmp(alph);
375 get<component_type>(*
this) = tmp;
387 template <
typename component_type>
389 requires (!std::derived_from<component_type, alphabet_tuple_base>) &&
390 is_unique_component<component_type>
392 constexpr derived_type &
operator=(component_type
const alph) noexcept
394 get<component_type>(*
this) = alph;
395 return static_cast<derived_type &
>(*this);
407 template <
typename indirect_component_type>
409 requires ((!std::derived_from<indirect_component_type, alphabet_tuple_base>) &&
410 (!is_unique_component<indirect_component_type>) &&
411 (std::assignable_from<component_types, indirect_component_type> || ...))
413 constexpr derived_type & operator=(indirect_component_type const alph) noexcept
415 using component_type = meta::front<meta::find_if<component_list, detail::assignable_from<indirect_component_type>>>;
416 get<component_type>(*
this) = alph;
417 return static_cast<derived_type &
>(*this);
421 template <
typename indirect_component_type>
422 requires ((!std::derived_from<indirect_component_type, alphabet_tuple_base>) &&
423 (!is_unique_component<indirect_component_type>) &&
424 (!(std::assignable_from<component_types, indirect_component_type> || ...)) &&
425 (std::convertible_to<indirect_component_type, component_types> || ...))
426 constexpr derived_type & operator=(indirect_component_type const alph) noexcept
428 using component_type = meta::front<meta::find_if<component_list, detail::implicitly_convertible_from<indirect_component_type>>>;
429 component_type tmp(alph);
430 get<component_type>(*
this) = tmp;
431 return static_cast<derived_type &
>(*this);
434 template <
typename indirect_component_type>
435 requires ((!std::derived_from<indirect_component_type, alphabet_tuple_base>) &&
436 (!is_unique_component<indirect_component_type>) &&
437 (!(std::assignable_from<component_types, indirect_component_type> || ...)) &&
438 (!(std::convertible_to<indirect_component_type, component_types> || ...)) &&
439 (std::constructible_from<component_types, indirect_component_type> || ...))
440 constexpr derived_type & operator=(indirect_component_type const alph) noexcept
442 using component_type = meta::front<meta::find_if<component_list, detail::constructible_from<indirect_component_type>>>;
443 component_type tmp(alph);
444 get<component_type>(*
this) = tmp;
445 return static_cast<derived_type &
>(*this);
458 template <
size_t index>
461 static_assert(index <
sizeof...(component_types),
"Index out of range.");
463 using t = meta::at_c<component_list, index>;
468 return component_proxy<t, index>{val, l};
475 template <
typename type>
478 requires is_unique_component<type>
481 return get<meta::find_index<component_list, type>::value>(l);
488 template <
size_t index>
491 static_assert(index <
sizeof...(component_types),
"Index out of range.");
493 using t = meta::at_c<component_list, index>;
502 template <
typename type>
505 requires is_unique_component<type>
508 return get<meta::find_index<component_list, type>::value>(l);
513 template <
typename type>
514 constexpr
operator type() const noexcept
516 requires is_unique_component<type>
519 return get<type>(*
this);
538 template <
typename derived_type_t,
typename indirect_component_type>
539 friend constexpr
auto operator==(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
540 ->
std::enable_if_t<detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
543 using component_type = meta::front<meta::find_if<component_list, detail::weakly_equality_comparable_with_<indirect_component_type>>>;
544 return get<component_type>(lhs) == rhs;
548 template <
typename derived_type_t,
typename indirect_component_type>
549 friend constexpr
auto operator==(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
550 ->
std::enable_if_t<detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
557 template <
typename derived_type_t,
typename indirect_component_type>
558 friend constexpr
auto operator!=(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
559 ->
std::enable_if_t<detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
562 using component_type = meta::front<meta::find_if<component_list, detail::weakly_equality_comparable_with_<indirect_component_type>>>;
563 return get<component_type>(lhs) != rhs;
567 template <
typename derived_type_t,
typename indirect_component_type>
568 friend constexpr
auto operator!=(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
569 ->
std::enable_if_t<detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
576 template <
typename derived_type_t,
typename indirect_component_type>
577 friend constexpr
auto operator<(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
578 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
581 using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with_<indirect_component_type>>>;
582 return get<component_type>(lhs) < rhs;
586 template <
typename derived_type_t,
typename indirect_component_type>
587 friend constexpr
auto operator<(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
588 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
595 template <
typename derived_type_t,
typename indirect_component_type>
596 friend constexpr
auto operator<=(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
597 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
600 using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with_<indirect_component_type>>>;
601 return get<component_type>(lhs) <= rhs;
605 template <
typename derived_type_t,
typename indirect_component_type>
606 friend constexpr
auto operator<=(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
607 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
614 template <
typename derived_type_t,
typename indirect_component_type>
615 friend constexpr
auto operator>(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
616 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
619 using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with_<indirect_component_type>>>;
620 return get<component_type>(lhs) > rhs;
624 template <
typename derived_type_t,
typename indirect_component_type>
625 friend constexpr
auto operator>(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
626 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
633 template <
typename derived_type_t,
typename indirect_component_type>
634 friend constexpr
auto operator>=(derived_type_t
const lhs, indirect_component_type
const rhs) noexcept
635 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
638 using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with_<indirect_component_type>>>;
639 return get<component_type>(lhs) >= rhs;
643 template <
typename derived_type_t,
typename indirect_component_type>
644 friend constexpr
auto operator>=(indirect_component_type
const lhs, derived_type_t
const rhs) noexcept
645 ->
std::enable_if_t<detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
654 template <
size_t index>
655 constexpr rank_type to_component_rank() const noexcept
659 return rank_to_component_rank[index][
to_rank()];
663 return (
to_rank() / cummulative_alph_sizes[index]) %
669 template <
size_t index>
670 constexpr
void assign_component_rank(ptrdiff_t
const r) noexcept
672 assign_rank(
static_cast<ptrdiff_t
>(
to_rank()) +
673 ((r -
static_cast<ptrdiff_t
>(to_component_rank<index>())) *
674 static_cast<ptrdiff_t
>(cummulative_alph_sizes[index])));
686 meta::for_each(meta::reverse<component_list>{}, [&] (
auto alph) constexpr
707 return ((
seqan3::to_rank(components) * cummulative_alph_sizes[idx]) + ...);
712 list_traits::size<component_list>> rank_to_component_rank
717 list_traits::size<component_list>> ret{};
723 for (
size_t i = 0; i < list_traits::size<component_list>; ++i)
724 for (
size_t j = 0; j < static_cast<size_t>(
alphabet_size); ++j)
725 ret[i][j] = (j / cummulative_alph_sizes[i]) % alph_sizes[i];
743 template <std::
size_t i, seqan3::detail::alphabet_tuple_base_specialisation tuple_t>
744 struct tuple_element<i, tuple_t>
747 using type = meta::at_c<typename tuple_t::seqan3_required_types, i>;
755 template <seqan3::detail::alphabet_tuple_base_specialisation tuple_t>
756 struct tuple_size<tuple_t> :