SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
alphabet/concept.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <type_traits>
13
20
21// ============================================================================
22// forwards
23// ============================================================================
24
25namespace seqan3::custom
26{
27
44template <typename t>
46{};
47
49template <typename t>
50struct alphabet<t const> : alphabet<t>
51{};
52
53template <typename t>
54struct alphabet<t &> : alphabet<t>
55{};
56
57template <typename t>
58struct alphabet<t const &> : alphabet<t>
59{};
61
62} // namespace seqan3::custom
63
64// ============================================================================
65// to_rank()
66// ============================================================================
67
68namespace seqan3::detail::adl_only
69{
70
72template <typename... args_t>
73void to_rank(args_t...) = delete;
74
77struct to_rank_cpo : public detail::customisation_point_object<to_rank_cpo, 2>
78{
80 using base_t = detail::customisation_point_object<to_rank_cpo, 2>;
82 using base_t::base_t;
83
88 template <typename alphabet_t>
89 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)(
90 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
91 );
92
97 template <typename alphabet_t>
98 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)(
99 /*return*/ to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
100 );
101
106 template <typename alphabet_t>
107 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)(
108 /*return*/ std::forward<alphabet_t>(alphabet).to_rank() /*;*/
109 );
110};
111
112} // namespace seqan3::detail::adl_only
113
114namespace seqan3
115{
116
158inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
160
166template <typename semi_alphabet_type>
167 requires requires {
168 { seqan3::to_rank(std::declval<semi_alphabet_type>()) };
169 }
170using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
171
172} // namespace seqan3
173
174// ============================================================================
175// assign_rank_to()
176// ============================================================================
177
178namespace seqan3::detail::adl_only
179{
180
182template <typename... args_t>
183void assign_rank_to(args_t...) = delete;
184
187struct assign_rank_to_cpo : public detail::customisation_point_object<assign_rank_to_cpo, 2>
188{
190 using base_t = detail::customisation_point_object<assign_rank_to_cpo, 2>;
192 using base_t::base_t;
193
207 template <typename alphabet_t>
208 static constexpr auto
209 SEQAN3_CPO_OVERLOAD(priority_tag<2>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
210 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_rank_to(rank, alphabet)) /*;*/
211 );
212
226 template <typename alphabet_t>
227 static constexpr auto
228 SEQAN3_CPO_OVERLOAD(priority_tag<1>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
229 /*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
230 );
231
242 template <typename alphabet_t> // least priority
243 static constexpr auto
244 SEQAN3_CPO_OVERLOAD(priority_tag<0>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
245 /*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
246 );
247};
248
249} // namespace seqan3::detail::adl_only
250
251namespace seqan3
252{
253
300inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
302} // namespace seqan3
303
304// ============================================================================
305// to_char()
306// ============================================================================
307
308namespace seqan3::detail::adl_only
309{
310
312template <typename... args_t>
313void to_char(args_t...) = delete;
314
317struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
318{
320 using base_t = detail::customisation_point_object<to_char_cpo, 2>;
322 using base_t::base_t;
323
328 template <typename alphabet_t>
329 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)(
330 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
331 );
332
337 template <typename alphabet_t>
338 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)(
339 /*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
340 );
341
346 template <typename alphabet_t>
347 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)(
348 /*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
349 );
350};
351
352} // namespace seqan3::detail::adl_only
353
354namespace seqan3
355{
356
399inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
401
407template <typename alphabet_type>
408 requires requires (alphabet_type const a) {
409 { seqan3::to_char(a) };
410 }
411using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
412
413} // namespace seqan3
414
415// ============================================================================
416// assign_char_to()
417// ============================================================================
418
419namespace seqan3::detail::adl_only
420{
421
423template <typename... args_t>
424void assign_char_to(args_t...) = delete;
425
428struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
429{
431 using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
433 using base_t::base_t;
434
448 template <typename alphabet_t>
449 static constexpr auto
450 SEQAN3_CPO_OVERLOAD(priority_tag<2>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
451 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
452 );
453
467 template <typename alphabet_t>
468 static constexpr auto
469 SEQAN3_CPO_OVERLOAD(priority_tag<1>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
470 /*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
471 );
472
483 template <typename alphabet_t> // least priority
484 static constexpr auto
485 SEQAN3_CPO_OVERLOAD(priority_tag<0>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
486 /*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
487 );
488};
489
490} // namespace seqan3::detail::adl_only
491
492namespace seqan3
493{
494
541inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
543} // namespace seqan3
544
545// ============================================================================
546// char_is_valid_for()
547// ============================================================================
548
549namespace seqan3::detail::adl_only
550{
551
553template <typename... args_t>
554void char_is_valid_for(args_t...) = delete;
555
560template <typename alphabet_t>
561struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
562{
564 using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
566 using base_t::base_t;
567
571 template <typename alphabet_type>
572 using alphabet_or_type_identity =
576
581 template <typename alphabet_type = alphabet_t>
582 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)(
584 );
585
596 template <typename alphabet_type = alphabet_t>
597 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)(
598 /*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
599 );
600
605 template <typename alphabet_type = alphabet_t>
606 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)(
607 /*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
608 );
609
630 template <typename alphabet_type = alphabet_t>
631 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)(
632 /*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
633 );
634};
635
636} // namespace seqan3::detail::adl_only
637
638namespace seqan3
639{
640
689template <typename alph_t>
690 requires requires {
691 { to_char(std::declval<alph_t>()) };
692 } // to_char() is required by some defs
693inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
695} // namespace seqan3
696
697// ============================================================================
698// assign_char_strictly_to()
699// ============================================================================
700
701namespace seqan3::detail::adl_only
702{
703
706struct assign_char_strictly_to_fn
707{
709 template <typename alphabet_t>
710 constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
711 requires requires () {
712 { seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet)) } -> std::convertible_to<alphabet_t>;
713 { seqan3::char_is_valid_for<alphabet_t>(chr) } -> std::same_as<bool>;
714 }
715 {
716 if (!seqan3::char_is_valid_for<alphabet_t>(chr))
717 throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
718
719 return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
720 }
722
723} // namespace seqan3::detail::adl_only
724
725namespace seqan3
726{
727
753inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
755} // namespace seqan3
756
757// ============================================================================
758// alphabet_size
759// ============================================================================
760
761namespace seqan3::detail::adl_only
762{
763
765template <typename... args_t>
766void alphabet_size(args_t...) = delete;
767
772template <typename alphabet_t>
773struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
774{
776 using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
778 using base_t::base_t;
779
783 template <typename alphabet_type>
784 using alphabet_or_type_identity =
786 && seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
789
793 template <typename alphabet_type = alphabet_t>
794 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)(
796 );
797
806 template <typename alphabet_type = alphabet_t>
807 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)(
808 /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
809 );
810
814 template <typename alphabet_type = alphabet_t>
815 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)(
817 );
818};
819
820} // namespace seqan3::detail::adl_only
821
822namespace seqan3
823{
824
868template <typename alph_t>
869 requires requires {
870 { detail::adl_only::alphabet_size_cpo<alph_t>{}() };
871 }
872inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
873
874// ============================================================================
875// semialphabet
876// ============================================================================
877
920template <typename t>
921concept semialphabet =
922 std::totally_ordered<t> && std::copy_constructible<t> && std::is_nothrow_copy_constructible_v<t> && requires (t v) {
923 { seqan3::alphabet_size<t> };
924 { seqan3::to_rank(v) };
925 };
927
928// ============================================================================
929// writable_semialphabet
930// ============================================================================
931
967template <typename t>
968concept writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r) {
969 { seqan3::assign_rank_to(r, v) };
970};
972
973// ============================================================================
974// alphabet
975// ============================================================================
976
1005template <typename t>
1006concept alphabet = semialphabet<t> && requires (t v) {
1007 { seqan3::to_char(v) };
1008};
1010
1011// ============================================================================
1012// writable_alphabet
1013// ============================================================================
1014
1052template <typename t>
1053concept writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c) {
1054 { seqan3::assign_char_to(c, v) };
1055};
1057
1058// ============================================================================
1059// serialisation
1060// ============================================================================
1061
1083template <cereal_output_archive archive_t, semialphabet alphabet_t>
1084alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1085{
1086 return to_rank(l);
1087}
1088
1102template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1103void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1104 wrapped_alphabet_t && l,
1105 alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1107{
1108 assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1109}
1114} // namespace seqan3
1115
1116namespace seqan3::detail
1117{
1118// ============================================================================
1119// constexpr_semialphabet
1120// ============================================================================
1121
1131template <typename t>
1132concept constexpr_semialphabet = semialphabet<t> && requires {
1133 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1134 requires SEQAN3_IS_CONSTEXPR(to_rank(std::remove_reference_t<t>{}));
1135};
1137
1138// ============================================================================
1139// writable_constexpr_semialphabet
1140// ============================================================================
1141
1152template <typename t>
1153concept writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires {
1154 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1155 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
1156};
1158
1159// ============================================================================
1160// constexpr_alphabet
1161// ============================================================================
1162
1173template <typename t>
1174concept constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires {
1175 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1176 requires SEQAN3_IS_CONSTEXPR(to_char(std::remove_reference_t<t>{}));
1177};
1179
1180// ============================================================================
1181// writable_constexpr_alphabet
1182// ============================================================================
1183
1195template <typename t>
1196concept writable_constexpr_alphabet =
1197 constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires {
1198 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1199 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1200 };
1202
1203} // namespace seqan3::detail
Exceptions thrown by entities in the alphabet module.
Provides various type traits on generic types.
Adaptions of concepts from the Cereal library.
Helper utilities for defining customisation point objects (CPOs).
#define SEQAN3_CPO_OVERLOAD(...)
A macro that helps to define a seqan3::detail::customisation_point_object.
Definition customisation_point.hpp:104
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition alphabet/concept.hpp:517
constexpr auto to_char
Return the char representation of an alphabet object.
Definition alphabet/concept.hpp:381
decltype(seqan3::to_rank(std::declval< semi_alphabet_type >())) alphabet_rank_t
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition alphabet/concept.hpp:164
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition alphabet/concept.hpp:834
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition alphabet/concept.hpp:288
decltype(seqan3::to_char(std::declval< alphabet_type const >())) alphabet_char_t
The char_type of the alphabet; defined as the return type of seqan3::to_char.
Definition alphabet/concept.hpp:393
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 alphabet/concept.hpp:661
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition alphabet/concept.hpp:721
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition alphabet/concept.hpp:152
The generic alphabet concept that covers most data types used in ranges.
The basis for seqan3::alphabet, but requires only rank interface (not char).
Refines seqan3::alphabet and adds assignability.
A refinement of seqan3::semialphabet that adds assignability.
A namespace for third party and standard library specialisations of SeqAn customisation points.
Definition char.hpp:39
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
A type that can be specialised to provide customisation point implementations so that third party typ...
Definition alphabet/concept.hpp:46
An exception typically thrown by seqan3::alphabet::assign_char_strict.
Definition alphabet/exception.hpp:27
Provides traits to inspect some information of a type, for example its name.
Provides concepts that do not have equivalents in C++20.
Hide me