SeqAn3 3.2.0-rc.1
The Modern C++ library for sequence analysis.
concept.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2021, 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
22
23// ============================================================================
24// forwards
25// ============================================================================
26
27namespace seqan3::custom
28{
29
46template <typename t>
48{};
49
51template <typename t>
52struct alphabet<t const> : alphabet<t>
53{};
54
55template <typename t>
56struct alphabet<t &> : alphabet<t>
57{};
58
59template <typename t>
60struct alphabet<t const &> : alphabet<t>
61{};
63
64} // namespace seqan3::custom
65
66// ============================================================================
67// to_rank()
68// ============================================================================
69
70namespace seqan3::detail::adl_only
71{
72
74template <typename ...args_t>
75void to_rank(args_t ...) = delete;
76
79struct to_rank_cpo : public detail::customisation_point_object<to_rank_cpo, 2>
80{
82 using base_t = detail::customisation_point_object<to_rank_cpo, 2>;
84 using base_t::base_t;
85
90 template <typename alphabet_t>
91 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)
92 (
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 (
103 /*return*/ to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
104 );
105
110 template <typename alphabet_t>
111 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)
112 (
113 /*return*/ std::forward<alphabet_t>(alphabet).to_rank() /*;*/
114 );
115};
116
117} // namespace seqan3::detail::adl_only
118
119namespace seqan3
120{
121
163inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
165
171template <typename semi_alphabet_type>
173 requires requires { { seqan3::to_rank(std::declval<semi_alphabet_type>()) }; }
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 SEQAN3_CPO_OVERLOAD(priority_tag<2>,
215 alphabet_t && alphabet)
216 (
217 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_rank_to(rank, alphabet)) /*;*/
218 );
219
233 template <typename alphabet_t>
234 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
236 alphabet_t && alphabet)
237 (
238 /*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
239 );
240
251 template <typename alphabet_t> // least priority
252 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
254 alphabet_t && alphabet)
255 (
256 /*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
257 );
258};
259
260} // namespace seqan3::detail::adl_only
261
262namespace seqan3
263{
264
311inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
313} // namespace seqan3
314
315// ============================================================================
316// to_char()
317// ============================================================================
318
319namespace seqan3::detail::adl_only
320{
321
323template <typename ...args_t>
324void to_char(args_t ...) = delete;
325
328struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
329{
331 using base_t = detail::customisation_point_object<to_char_cpo, 2>;
333 using base_t::base_t;
334
339 template <typename alphabet_t>
340 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)
341 (
342 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
343 );
344
349 template <typename alphabet_t>
350 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)
351 (
352 /*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
353 );
354
359 template <typename alphabet_t>
360 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)
361 (
362 /*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
363 );
364};
365
366} // namespace seqan3::detail::adl_only
367
368namespace seqan3
369{
370
413inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
415
421template <typename alphabet_type>
423 requires requires (alphabet_type const a) { { seqan3::to_char(a) }; }
425using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
426
427} // namespace seqan3
428
429// ============================================================================
430// assign_char_to()
431// ============================================================================
432
433namespace seqan3::detail::adl_only
434{
435
437template <typename ...args_t>
438void assign_char_to(args_t ...) = delete;
439
442struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
443{
445 using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
447 using base_t::base_t;
448
462 template <typename alphabet_t>
463 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
465 alphabet_t && alphabet)
466 (
467 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
468 );
469
483 template <typename alphabet_t>
484 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
486 alphabet_t && alphabet)
487 (
488 /*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
489 );
490
501 template <typename alphabet_t> // least priority
502 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
504 alphabet_t && alphabet)
505 (
506 /*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
507 );
508};
509
510} // namespace seqan3::detail::adl_only
511
512namespace seqan3
513{
514
561inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
563} // namespace seqan3
564
565// ============================================================================
566// char_is_valid_for()
567// ============================================================================
568
569namespace seqan3::detail::adl_only
570{
571
573template <typename ...args_t>
574void char_is_valid_for(args_t ...) = delete;
575
580template <typename alphabet_t>
581struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
582{
584 using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
586 using base_t::base_t;
587
591 template <typename alphabet_type>
592 using alphabet_or_type_identity
596
601 template <typename alphabet_type = alphabet_t>
602 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)
603 (
605 );
606
617 template <typename alphabet_type = alphabet_t>
618 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)
619 (
620 /*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
621 );
622
627 template <typename alphabet_type = alphabet_t>
628 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)
629 (
630 /*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
631 );
632
653 template <typename alphabet_type = alphabet_t>
654 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)
655 (
656 /*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
657 );
658};
659
660} // namespace seqan3::detail::adl_only
661
662namespace seqan3
663{
664
713template <typename alph_t>
715 requires requires { { to_char(std::declval<alph_t>()) }; } // to_char() is required by some defs
717inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
719} // namespace seqan3
720
721// ============================================================================
722// assign_char_strictly_to()
723// ============================================================================
724
725namespace seqan3::detail::adl_only
726{
727
730struct assign_char_strictly_to_fn
731{
733 template <typename alphabet_t>
734 constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
736 requires requires ()
737 {
738 {seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet))} -> std::convertible_to<alphabet_t>;
739 {seqan3::char_is_valid_for<alphabet_t>(chr)} -> std::same_as<bool>;
740 }
742 {
743 if (!seqan3::char_is_valid_for<alphabet_t>(chr))
744 throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
745
746 return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
747 }
748};
749
750} // namespace seqan3::detail::adl_only
751
752namespace seqan3
753{
754
780inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
782} // namespace seqan3
783
784// ============================================================================
785// alphabet_size
786// ============================================================================
787
788namespace seqan3::detail::adl_only
789{
790
792template <typename ...args_t>
793void alphabet_size(args_t ...) = delete;
794
799template <typename alphabet_t>
800struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
801{
803 using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
805 using base_t::base_t;
806
810 template <typename alphabet_type>
811 using alphabet_or_type_identity
813 seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
816
820 template <typename alphabet_type = alphabet_t>
821 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)
822 (
824 );
825
834 template <typename alphabet_type = alphabet_t>
835 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)
836 (
837 /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
838 );
839
843 template <typename alphabet_type = alphabet_t>
844 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)
847 );
848};
849
850} // namespace seqan3::detail::adl_only
852namespace seqan3
853{
854
898template <typename alph_t>
900 requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{}() }; }
902inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
903
904// ============================================================================
905// semialphabet
906// ============================================================================
907
950template <typename t>
951concept semialphabet =
952 std::totally_ordered<t> &&
953 std::copy_constructible<t> &&
954 std::is_nothrow_copy_constructible_v<t> &&
955 requires (t v)
956{
957 { seqan3::alphabet_size<t> };
958 { seqan3::to_rank(v) };
959};
961
962// ============================================================================
963// writable_semialphabet
964// ============================================================================
965
1001template <typename t>
1002concept writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r)
1003{
1004 { seqan3::assign_rank_to(r, v) };
1005};
1007
1008// ============================================================================
1009// alphabet
1010// ============================================================================
1011
1040template <typename t>
1041concept alphabet = semialphabet<t> && requires (t v)
1042{
1043 { seqan3::to_char(v) };
1044};
1046
1047// ============================================================================
1048// writable_alphabet
1049// ============================================================================
1050
1088template <typename t>
1089concept writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c)
1090{
1091 { seqan3::assign_char_to(c, v) };
1092};
1094
1095// ============================================================================
1096// serialisation
1097// ============================================================================
1098
1120template <cereal_output_archive archive_t, semialphabet alphabet_t>
1121alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1122{
1123 return to_rank(l);
1124}
1125
1139template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1140void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1141 wrapped_alphabet_t && l,
1142 alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1144{
1145 assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1146}
1151} // namespace seqan3
1152
1153namespace seqan3::detail
1154{
1155// ============================================================================
1156// constexpr_semialphabet
1157// ============================================================================
1158
1168template <typename t>
1169concept constexpr_semialphabet = semialphabet<t> && requires
1170{
1171 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1172 requires SEQAN3_IS_CONSTEXPR(to_rank(std::remove_reference_t<t>{}));
1173};
1175
1176// ============================================================================
1177// writable_constexpr_semialphabet
1178// ============================================================================
1179
1190template <typename t>
1191concept writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires
1192{
1193 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1194 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
1195};
1197
1198// ============================================================================
1199// constexpr_alphabet
1200// ============================================================================
1201
1212template <typename t>
1213concept constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires
1214{
1215 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1216 requires SEQAN3_IS_CONSTEXPR(to_char(std::remove_reference_t<t>{}));
1217};
1219
1220// ============================================================================
1221// writable_constexpr_alphabet
1222// ============================================================================
1223
1235template <typename t>
1236concept writable_constexpr_alphabet =
1237 constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires
1238{
1239 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1240 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1241};
1243
1244} // 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:102
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:525
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:166
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:845
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:398
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:669
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition: concept.hpp:732
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:154
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:44
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:48
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.