SeqAn3 3.1.0
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
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 (
94 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
95 );
96
101 template <typename alphabet_t>
102 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)
103 (
104 /*return*/ to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
105 );
106
111 template <typename alphabet_t>
112 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)
113 (
114 /*return*/ std::forward<alphabet_t>(alphabet).to_rank() /*;*/
115 );
116};
117
118} // namespace seqan3::detail::adl_only
119
120namespace seqan3
121{
122
164inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
166
172template <typename semi_alphabet_type>
174 requires requires { { seqan3::to_rank(std::declval<semi_alphabet_type>()) }; }
176using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
177
178} // namespace seqan3
179
180// ============================================================================
181// assign_rank_to()
182// ============================================================================
183
184namespace seqan3::detail::adl_only
185{
186
188template <typename ...args_t>
189void assign_rank_to(args_t ...) = delete;
190
193struct assign_rank_to_cpo : public detail::customisation_point_object<assign_rank_to_cpo, 2>
194{
196 using base_t = detail::customisation_point_object<assign_rank_to_cpo, 2>;
198 using base_t::base_t;
199
213 template <typename alphabet_t>
214 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
216 alphabet_t && alphabet)
217 (
218 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_rank_to(rank, alphabet)) /*;*/
219 );
220
234 template <typename alphabet_t>
235 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
237 alphabet_t && alphabet)
238 (
239 /*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
240 );
241
252 template <typename alphabet_t> // least priority
253 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
255 alphabet_t && alphabet)
256 (
257 /*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
258 );
259};
260
261} // namespace seqan3::detail::adl_only
262
263namespace seqan3
264{
265
312inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
314} // namespace seqan3
315
316// ============================================================================
317// to_char()
318// ============================================================================
319
320namespace seqan3::detail::adl_only
321{
322
324template <typename ...args_t>
325void to_char(args_t ...) = delete;
326
329struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
330{
332 using base_t = detail::customisation_point_object<to_char_cpo, 2>;
334 using base_t::base_t;
335
340 template <typename alphabet_t>
341 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)
342 (
343 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
344 );
345
350 template <typename alphabet_t>
351 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)
352 (
353 /*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
354 );
355
360 template <typename alphabet_t>
361 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)
362 (
363 /*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
364 );
365};
366
367} // namespace seqan3::detail::adl_only
368
369namespace seqan3
370{
371
414inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
416
422template <typename alphabet_type>
424 requires requires (alphabet_type const a) { { seqan3::to_char(a) }; }
426using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
427
428} // namespace seqan3
429
430// ============================================================================
431// assign_char_to()
432// ============================================================================
433
434namespace seqan3::detail::adl_only
435{
436
438template <typename ...args_t>
439void assign_char_to(args_t ...) = delete;
440
443struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
444{
446 using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
448 using base_t::base_t;
449
463 template <typename alphabet_t>
464 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
466 alphabet_t && alphabet)
467 (
468 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
469 );
470
484 template <typename alphabet_t>
485 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
487 alphabet_t && alphabet)
488 (
489 /*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
490 );
491
502 template <typename alphabet_t> // least priority
503 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
505 alphabet_t && alphabet)
506 (
507 /*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
508 );
509};
510
511} // namespace seqan3::detail::adl_only
512
513namespace seqan3
514{
515
562inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
564} // namespace seqan3
565
566// ============================================================================
567// char_is_valid_for()
568// ============================================================================
569
570namespace seqan3::detail::adl_only
571{
572
574template <typename ...args_t>
575void char_is_valid_for(args_t ...) = delete;
576
581template <typename alphabet_t>
582struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
583{
585 using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
587 using base_t::base_t;
588
592 template <typename alphabet_type>
593 using alphabet_or_type_identity
597
602 template <typename alphabet_type = alphabet_t>
603 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)
604 (
606 );
607
618 template <typename alphabet_type = alphabet_t>
619 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)
620 (
621 /*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
622 );
623
628 template <typename alphabet_type = alphabet_t>
629 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)
630 (
631 /*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
632 );
633
654 template <typename alphabet_type = alphabet_t>
655 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)
656 (
657 /*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
658 );
659};
660
661} // namespace seqan3::detail::adl_only
662
663namespace seqan3
664{
665
714template <typename alph_t>
716 requires requires { { to_char(std::declval<alph_t>()) }; } // to_char() is required by some defs
718inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
720} // namespace seqan3
721
722// ============================================================================
723// assign_char_strictly_to()
724// ============================================================================
725
726namespace seqan3::detail::adl_only
727{
728
731struct assign_char_strictly_to_fn
732{
734 template <typename alphabet_t>
735 constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
737 requires requires ()
738 {
739 SEQAN3_RETURN_TYPE_CONSTRAINT(seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet)),
740 std::convertible_to, alphabet_t);
741 SEQAN3_RETURN_TYPE_CONSTRAINT(seqan3::char_is_valid_for<alphabet_t>(chr), std::same_as, bool);
742 }
744 {
745 if (!seqan3::char_is_valid_for<alphabet_t>(chr))
746 throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
747
748 return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
749 }
750};
751
752} // namespace seqan3::detail::adl_only
753
754namespace seqan3
755{
756
782inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
784} // namespace seqan3
785
786// ============================================================================
787// alphabet_size
788// ============================================================================
789
790namespace seqan3::detail::adl_only
791{
792
794template <typename ...args_t>
795void alphabet_size(args_t ...) = delete;
796
801template <typename alphabet_t>
802struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
803{
805 using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
807 using base_t::base_t;
808
812 template <typename alphabet_type>
813 using alphabet_or_type_identity
815 seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
818
822 template <typename alphabet_type = alphabet_t>
823 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)
824 (
826 );
827
836 template <typename alphabet_type = alphabet_t>
837 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)
838 (
839 /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
840 );
841
845 template <typename alphabet_type = alphabet_t>
846 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)
847 (
849 );
850};
851
852#if SEQAN3_WORKAROUND_GCC_89953
853template <typename alph_t>
854 requires requires { { alphabet_size_cpo<alph_t>{} }; }
855inline constexpr auto alphabet_size_obj = alphabet_size_cpo<alph_t>{};
856#endif // SEQAN3_WORKAROUND_GCC_89953
857
858} // namespace seqan3::detail::adl_only
859
860namespace seqan3
862
906#if SEQAN3_WORKAROUND_GCC_89953
907template <typename alph_t>
909 requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{} }; } &&
910 requires { { detail::adl_only::alphabet_size_obj<alph_t>() }; } // ICE workarounds
912inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_obj<alph_t>();
913#else // ^^^ workaround / no workaround vvv
914template <typename alph_t>
916 requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{}() }; }
918inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
919#endif // SEQAN3_WORKAROUND_GCC_89953
920
921// ============================================================================
922// semialphabet
923// ============================================================================
924
967template <typename t>
968SEQAN3_CONCEPT semialphabet =
969 std::totally_ordered<t> &&
970 std::copy_constructible<t> &&
971 std::is_nothrow_copy_constructible_v<t> &&
972 requires (t v)
973{
974 { seqan3::alphabet_size<t> };
975 { seqan3::to_rank(v) };
976};
978
979// ============================================================================
980// writable_semialphabet
981// ============================================================================
982
1018template <typename t>
1019SEQAN3_CONCEPT writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r)
1020{
1021 { seqan3::assign_rank_to(r, v) };
1022};
1024
1025// ============================================================================
1026// alphabet
1027// ============================================================================
1028
1057template <typename t>
1058SEQAN3_CONCEPT alphabet = semialphabet<t> && requires (t v)
1059{
1060 { seqan3::to_char(v) };
1061};
1063
1064// ============================================================================
1065// writable_alphabet
1066// ============================================================================
1067
1105template <typename t>
1106SEQAN3_CONCEPT writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c)
1107{
1108 { seqan3::assign_char_to(c, v) };
1109};
1111
1112// ============================================================================
1113// serialisation
1114// ============================================================================
1115
1137template <cereal_output_archive archive_t, semialphabet alphabet_t>
1138alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1139{
1140 return to_rank(l);
1141}
1142
1156template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1157void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1158 wrapped_alphabet_t && l,
1159 alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1161{
1162 assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1163}
1168} // namespace seqan3
1169
1170namespace seqan3::detail
1171{
1172// ============================================================================
1173// constexpr_semialphabet
1174// ============================================================================
1175
1185template <typename t>
1186SEQAN3_CONCEPT constexpr_semialphabet = semialphabet<t> && requires
1187{
1188 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1189 requires SEQAN3_IS_CONSTEXPR(to_rank(std::remove_reference_t<t>{}));
1190};
1192
1193// ============================================================================
1194// writable_constexpr_semialphabet
1195// ============================================================================
1196
1207template <typename t>
1208SEQAN3_CONCEPT writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires
1209{
1210 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1211 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
1212};
1214
1215// ============================================================================
1216// constexpr_alphabet
1217// ============================================================================
1218
1229template <typename t>
1230SEQAN3_CONCEPT constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires
1231{
1232 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1233 requires SEQAN3_IS_CONSTEXPR(to_char(std::remove_reference_t<t>{}));
1234};
1236
1237// ============================================================================
1238// writable_constexpr_alphabet
1239// ============================================================================
1240
1252template <typename t>
1253SEQAN3_CONCEPT writable_constexpr_alphabet =
1254 constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires
1255{
1256 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1257 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1258};
1260
1261} // 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.
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
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:526
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:387
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:167
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:861
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:294
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:399
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:44
The main SeqAn3 namespace.
Definition: cigar_operation_table.hpp:2
#define SEQAN3_RETURN_TYPE_CONSTRAINT(expression, concept_name,...)
Same as writing {expression} -> concept_name<type1[, ...]> in a concept definition.
Definition: platform.hpp:57
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.
The <type_traits> header from C++20's standard library.