SeqAn3 3.2.0
The Modern C++ library for sequence analysis.
concept.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6// -----------------------------------------------------------------------------------------------------
7
13#pragma once
14
15#include <type_traits>
16
23
24// ============================================================================
25// forwards
26// ============================================================================
27
28namespace seqan3::custom
29{
30
47template <typename t>
49{};
50
52template <typename t>
53struct alphabet<t const> : alphabet<t>
54{};
55
56template <typename t>
57struct alphabet<t &> : alphabet<t>
58{};
59
60template <typename t>
61struct alphabet<t const &> : alphabet<t>
62{};
64
65} // namespace seqan3::custom
66
67// ============================================================================
68// to_rank()
69// ============================================================================
70
71namespace seqan3::detail::adl_only
72{
73
75template <typename... args_t>
76void to_rank(args_t...) = delete;
77
80struct to_rank_cpo : public detail::customisation_point_object<to_rank_cpo, 2>
81{
83 using base_t = detail::customisation_point_object<to_rank_cpo, 2>;
85 using base_t::base_t;
86
91 template <typename alphabet_t>
92 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)(
93 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
94 );
95
100 template <typename alphabet_t>
101 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)(
102 /*return*/ to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
103 );
104
109 template <typename alphabet_t>
110 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)(
111 /*return*/ std::forward<alphabet_t>(alphabet).to_rank() /*;*/
112 );
113};
114
115} // namespace seqan3::detail::adl_only
116
117namespace seqan3
118{
119
161inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
163
169template <typename semi_alphabet_type>
170 requires requires {
171 {
172 seqan3::to_rank(std::declval<semi_alphabet_type>())
173 };
174 }
175using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
176
177} // namespace seqan3
178
179// ============================================================================
180// assign_rank_to()
181// ============================================================================
182
183namespace seqan3::detail::adl_only
184{
185
187template <typename... args_t>
188void assign_rank_to(args_t...) = delete;
189
192struct assign_rank_to_cpo : public detail::customisation_point_object<assign_rank_to_cpo, 2>
193{
195 using base_t = detail::customisation_point_object<assign_rank_to_cpo, 2>;
197 using base_t::base_t;
198
212 template <typename alphabet_t>
213 static constexpr auto
214 SEQAN3_CPO_OVERLOAD(priority_tag<2>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
215 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_rank_to(rank, alphabet)) /*;*/
216 );
217
231 template <typename alphabet_t>
232 static constexpr auto
233 SEQAN3_CPO_OVERLOAD(priority_tag<1>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
234 /*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
235 );
236
247 template <typename alphabet_t> // least priority
248 static constexpr auto
249 SEQAN3_CPO_OVERLOAD(priority_tag<0>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
250 /*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
251 );
252};
253
254} // namespace seqan3::detail::adl_only
255
256namespace seqan3
257{
258
305inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
307} // namespace seqan3
308
309// ============================================================================
310// to_char()
311// ============================================================================
312
313namespace seqan3::detail::adl_only
314{
315
317template <typename... args_t>
318void to_char(args_t...) = delete;
319
322struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
323{
325 using base_t = detail::customisation_point_object<to_char_cpo, 2>;
327 using base_t::base_t;
328
333 template <typename alphabet_t>
334 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)(
335 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
336 );
337
342 template <typename alphabet_t>
343 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)(
344 /*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
345 );
346
351 template <typename alphabet_t>
352 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)(
353 /*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
354 );
355};
356
357} // namespace seqan3::detail::adl_only
358
359namespace seqan3
360{
361
404inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
406
412template <typename alphabet_type>
413 requires requires (alphabet_type const a) {
414 {
416 };
417 }
418using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
419
420} // namespace seqan3
421
422// ============================================================================
423// assign_char_to()
424// ============================================================================
425
426namespace seqan3::detail::adl_only
427{
428
430template <typename... args_t>
431void assign_char_to(args_t...) = delete;
432
435struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
436{
438 using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
440 using base_t::base_t;
441
455 template <typename alphabet_t>
456 static constexpr auto
457 SEQAN3_CPO_OVERLOAD(priority_tag<2>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
458 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
459 );
460
474 template <typename alphabet_t>
475 static constexpr auto
476 SEQAN3_CPO_OVERLOAD(priority_tag<1>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
477 /*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
478 );
479
490 template <typename alphabet_t> // least priority
491 static constexpr auto
492 SEQAN3_CPO_OVERLOAD(priority_tag<0>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
493 /*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
494 );
495};
496
497} // namespace seqan3::detail::adl_only
498
499namespace seqan3
500{
501
548inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
550} // namespace seqan3
551
552// ============================================================================
553// char_is_valid_for()
554// ============================================================================
555
556namespace seqan3::detail::adl_only
557{
558
560template <typename... args_t>
561void char_is_valid_for(args_t...) = delete;
562
567template <typename alphabet_t>
568struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
569{
571 using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
573 using base_t::base_t;
574
578 template <typename alphabet_type>
579 using alphabet_or_type_identity =
583
588 template <typename alphabet_type = alphabet_t>
589 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)(
591 );
592
603 template <typename alphabet_type = alphabet_t>
604 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)(
605 /*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
606 );
607
612 template <typename alphabet_type = alphabet_t>
613 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)(
614 /*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
615 );
616
637 template <typename alphabet_type = alphabet_t>
638 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)(
639 /*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
640 );
641};
642
643} // namespace seqan3::detail::adl_only
644
645namespace seqan3
646{
647
696template <typename alph_t>
697 requires requires {
698 {
699 to_char(std::declval<alph_t>())
700 };
701 } // to_char() is required by some defs
702inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
704} // namespace seqan3
705
706// ============================================================================
707// assign_char_strictly_to()
708// ============================================================================
709
710namespace seqan3::detail::adl_only
711{
712
715struct assign_char_strictly_to_fn
716{
718 template <typename alphabet_t>
719 constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
720 requires requires () {
721 {
722 seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet))
723 } -> std::convertible_to<alphabet_t>;
724 {
725 seqan3::char_is_valid_for<alphabet_t>(chr)
726 } -> std::same_as<bool>;
727 }
728 {
729 if (!seqan3::char_is_valid_for<alphabet_t>(chr))
730 throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
731
732 return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
733 }
735
736} // namespace seqan3::detail::adl_only
737
738namespace seqan3
739{
740
766inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
768} // namespace seqan3
769
770// ============================================================================
771// alphabet_size
772// ============================================================================
773
774namespace seqan3::detail::adl_only
775{
776
778template <typename... args_t>
779void alphabet_size(args_t...) = delete;
780
785template <typename alphabet_t>
786struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
787{
789 using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
791 using base_t::base_t;
792
796 template <typename alphabet_type>
797 using alphabet_or_type_identity =
799 && seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
802
806 template <typename alphabet_type = alphabet_t>
807 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)(
809 );
810
819 template <typename alphabet_type = alphabet_t>
820 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)(
821 /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
822 );
823
827 template <typename alphabet_type = alphabet_t>
828 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)(
830 );
831};
832
833} // namespace seqan3::detail::adl_only
834
835namespace seqan3
836{
837
881template <typename alph_t>
882 requires requires {
883 {
884 detail::adl_only::alphabet_size_cpo<alph_t>{}()
885 };
886 }
887inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
888
889// ============================================================================
890// semialphabet
891// ============================================================================
892
935template <typename t>
936concept semialphabet = std::totally_ordered<t> && std::copy_constructible<t> && std::is_nothrow_copy_constructible_v<t>
937 && requires (t v) {
938 {
939 seqan3::alphabet_size<t>
940 };
941 {
943 };
944 };
946
947// ============================================================================
948// writable_semialphabet
949// ============================================================================
950
986template <typename t>
987concept writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r) {
988 {
990 };
991 };
993
994// ============================================================================
995// alphabet
996// ============================================================================
997
1026template <typename t>
1027concept alphabet = semialphabet<t> && requires (t v) {
1028 {
1030 };
1031 };
1033
1034// ============================================================================
1035// writable_alphabet
1036// ============================================================================
1037
1075template <typename t>
1076concept writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c) {
1077 {
1079 };
1080 };
1082
1083// ============================================================================
1084// serialisation
1085// ============================================================================
1086
1108template <cereal_output_archive archive_t, semialphabet alphabet_t>
1109alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1110{
1111 return to_rank(l);
1112}
1113
1127template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1128void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1129 wrapped_alphabet_t && l,
1130 alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1132{
1133 assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1134}
1139} // namespace seqan3
1140
1141namespace seqan3::detail
1142{
1143// ============================================================================
1144// constexpr_semialphabet
1145// ============================================================================
1146
1156template <typename t>
1157concept constexpr_semialphabet =
1158 semialphabet<t> && requires {
1159 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1160 requires SEQAN3_IS_CONSTEXPR(to_rank(std::remove_reference_t<t>{}));
1161 };
1163
1164// ============================================================================
1165// writable_constexpr_semialphabet
1166// ============================================================================
1167
1178template <typename t>
1179concept writable_constexpr_semialphabet =
1180 constexpr_semialphabet<t> && writable_semialphabet<t>
1181 && requires {
1182 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1183 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
1184 };
1186
1187// ============================================================================
1188// constexpr_alphabet
1189// ============================================================================
1190
1201template <typename t>
1202concept constexpr_alphabet =
1203 constexpr_semialphabet<t> && alphabet<t> && requires {
1204 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1205 requires SEQAN3_IS_CONSTEXPR(to_char(std::remove_reference_t<t>{}));
1206 };
1208
1209// ============================================================================
1210// writable_constexpr_alphabet
1211// ============================================================================
1212
1224template <typename t>
1225concept writable_constexpr_alphabet =
1226 constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t>
1227 && requires {
1228 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1229 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1230 };
1232
1233} // 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:107
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:524
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:386
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: concept.hpp:169
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:849
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:293
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: concept.hpp:400
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:670
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition: concept.hpp:734
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:155
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:42
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
A type that can be specialised to provide customisation point implementations so that third party typ...
Definition: concept.hpp:49
An exception typically thrown by seqan3::alphabet::assign_char_strict.
Definition: exception.hpp:30
Provides traits to inspect some information of a type, for example its name.
Provides concepts that do not have equivalents in C++20.