SeqAn3  3.0.3
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 <seqan3/std/type_traits>
16 
23 
24 // ============================================================================
25 // forwards
26 // ============================================================================
27 
28 namespace seqan3::custom
29 {
30 
47 template <typename t>
48 struct alphabet
49 {};
50 
52 template <typename t>
53 struct alphabet<t const> : alphabet<t>
54 {};
55 
56 template <typename t>
57 struct alphabet<t &> : alphabet<t>
58 {};
59 
60 template <typename t>
61 struct alphabet<t const &> : alphabet<t>
62 {};
64 
65 } // namespace seqan3::custom
66 
67 // ============================================================================
68 // to_rank()
69 // ============================================================================
70 
71 namespace seqan3::detail::adl_only
72 {
73 
75 template <typename ...args_t>
76 void to_rank(args_t ...) = delete;
77 
80 struct 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 
120 namespace seqan3
121 {
122 
164 inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
166 
169 template <typename semi_alphabet_type>
171  requires requires { { seqan3::to_rank(std::declval<semi_alphabet_type>()) }; }
173 using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
174 
175 } // namespace seqan3
176 
177 // ============================================================================
178 // assign_rank_to()
179 // ============================================================================
180 
181 namespace seqan3::detail::adl_only
182 {
183 
185 template <typename ...args_t>
186 void assign_rank_to(args_t ...) = delete;
187 
190 struct assign_rank_to_cpo : public detail::customisation_point_object<assign_rank_to_cpo, 2>
191 {
193  using base_t = detail::customisation_point_object<assign_rank_to_cpo, 2>;
195  using base_t::base_t;
196 
210  template <typename alphabet_t>
211  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
213  alphabet_t && alphabet)
214  (
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 SEQAN3_CPO_OVERLOAD(priority_tag<1>,
234  alphabet_t && alphabet)
235  (
236  /*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
237  );
238 
249  template <typename alphabet_t> // least priority
250  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
252  alphabet_t && alphabet)
253  (
254  /*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
255  );
256 };
257 
258 } // namespace seqan3::detail::adl_only
259 
260 namespace seqan3
261 {
262 
309 inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
311 } // namespace seqan3
312 
313 // ============================================================================
314 // to_char()
315 // ============================================================================
316 
317 namespace seqan3::detail::adl_only
318 {
319 
321 template <typename ...args_t>
322 void to_char(args_t ...) = delete;
323 
326 struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
327 {
329  using base_t = detail::customisation_point_object<to_char_cpo, 2>;
331  using base_t::base_t;
332 
337  template <typename alphabet_t>
338  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)
339  (
340  /*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
341  );
342 
347  template <typename alphabet_t>
348  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)
349  (
350  /*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
351  );
352 
357  template <typename alphabet_t>
358  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)
359  (
360  /*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
361  );
362 };
363 
364 } // namespace seqan3::detail::adl_only
365 
366 namespace seqan3
367 {
368 
411 inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
413 
419 template <typename alphabet_type>
421  requires requires (alphabet_type const a) { { seqan3::to_char(a) }; }
423 using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
424 
425 } // namespace seqan3
426 
427 // ============================================================================
428 // assign_char_to()
429 // ============================================================================
430 
431 namespace seqan3::detail::adl_only
432 {
433 
435 template <typename ...args_t>
436 void assign_char_to(args_t ...) = delete;
437 
440 struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
441 {
443  using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
445  using base_t::base_t;
446 
460  template <typename alphabet_t>
461  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
463  alphabet_t && alphabet)
464  (
465  /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
466  );
467 
481  template <typename alphabet_t>
482  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
484  alphabet_t && alphabet)
485  (
486  /*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
487  );
488 
499  template <typename alphabet_t> // least priority
500  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
502  alphabet_t && alphabet)
503  (
504  /*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
505  );
506 };
507 
508 } // namespace seqan3::detail::adl_only
509 
510 namespace seqan3
511 {
512 
559 inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
561 } // namespace seqan3
562 
563 // ============================================================================
564 // char_is_valid_for()
565 // ============================================================================
566 
567 namespace seqan3::detail::adl_only
568 {
569 
571 template <typename ...args_t>
572 void char_is_valid_for(args_t ...) = delete;
573 
578 template <typename alphabet_t>
579 struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
580 {
582  using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
584  using base_t::base_t;
585 
589  template <typename alphabet_type>
590  using alphabet_or_type_identity
594 
599  template <typename alphabet_type = alphabet_t>
600  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)
601  (
602  /*return*/ seqan3::custom::alphabet<alphabet_type>::char_is_valid(chr) == true /*;*/
603  );
604 
615  template <typename alphabet_type = alphabet_t>
616  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)
617  (
618  /*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
619  );
620 
625  template <typename alphabet_type = alphabet_t>
626  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)
627  (
628  /*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
629  );
630 
651  template <typename alphabet_type = alphabet_t>
652  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)
653  (
654  /*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
655  );
656 };
657 
658 } // namespace seqan3::detail::adl_only
659 
660 namespace seqan3
661 {
662 
711 template <typename alph_t>
713  requires requires { { to_char(std::declval<alph_t>()) }; } // to_char() is required by some defs
715 inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
717 } // namespace seqan3
718 
719 // ============================================================================
720 // assign_char_strictly_to()
721 // ============================================================================
722 
723 namespace seqan3::detail::adl_only
724 {
725 
728 struct assign_char_strictly_to_fn
729 {
731  template <typename alphabet_t>
732  constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
734  requires requires ()
735  {
736  SEQAN3_RETURN_TYPE_CONSTRAINT(seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet)),
737  std::convertible_to, alphabet_t);
738  SEQAN3_RETURN_TYPE_CONSTRAINT(seqan3::char_is_valid_for<alphabet_t>(chr), std::same_as, bool);
739  }
741  {
742  if (!seqan3::char_is_valid_for<alphabet_t>(chr))
743  throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
744 
745  return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
746  }
747 };
748 
749 } // namespace seqan3::detail::adl_only
750 
751 namespace seqan3
752 {
753 
779 inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
781 } // namespace seqan3
782 
783 // ============================================================================
784 // alphabet_size
785 // ============================================================================
786 
787 namespace seqan3::detail::adl_only
788 {
789 
791 template <typename ...args_t>
792 void alphabet_size(args_t ...) = delete;
793 
798 template <typename alphabet_t>
799 struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
800 {
802  using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
804  using base_t::base_t;
805 
809  template <typename alphabet_type>
810  using alphabet_or_type_identity
812  seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
815 
819  template <typename alphabet_type = alphabet_t>
820  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)
821  (
823  );
824 
833  template <typename alphabet_type = alphabet_t>
834  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)
835  (
836  /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
837  );
838 
842  template <typename alphabet_type = alphabet_t>
843  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)
844  (
846  );
847 };
848 
849 #if SEQAN3_WORKAROUND_GCC_89953
850 template <typename alph_t>
851  requires requires { { alphabet_size_cpo<alph_t>{} }; }
852 inline constexpr auto alphabet_size_obj = alphabet_size_cpo<alph_t>{};
853 #endif // SEQAN3_WORKAROUND_GCC_89953
854 
855 } // namespace seqan3::detail::adl_only
856 
857 namespace seqan3
858 {
859 
903 #if SEQAN3_WORKAROUND_GCC_89953
904 template <typename alph_t>
906  requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{} }; } &&
907  requires { { detail::adl_only::alphabet_size_obj<alph_t>() }; } // ICE workarounds
909 inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_obj<alph_t>();
910 #else // ^^^ workaround / no workaround vvv
911 template <typename alph_t>
913  requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{}() }; }
915 inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
916 #endif // SEQAN3_WORKAROUND_GCC_89953
917 
918 // ============================================================================
919 // semialphabet
920 // ============================================================================
921 
964 template <typename t>
965 SEQAN3_CONCEPT semialphabet =
966  std::totally_ordered<t> &&
967  std::copy_constructible<t> &&
968  std::is_nothrow_copy_constructible_v<t> &&
969  requires (t v)
970 {
971  { seqan3::alphabet_size<t> };
972  { seqan3::to_rank(v) };
973 };
975 
976 // ============================================================================
977 // writable_semialphabet
978 // ============================================================================
979 
1015 template <typename t>
1016 SEQAN3_CONCEPT writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r)
1017 {
1018  { seqan3::assign_rank_to(r, v) };
1019 };
1021 
1022 // ============================================================================
1023 // alphabet
1024 // ============================================================================
1025 
1054 template <typename t>
1055 SEQAN3_CONCEPT alphabet = semialphabet<t> && requires (t v)
1056 {
1057  { seqan3::to_char(v) };
1058 };
1060 
1061 // ============================================================================
1062 // writable_alphabet
1063 // ============================================================================
1064 
1102 template <typename t>
1103 SEQAN3_CONCEPT writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c)
1104 {
1105  { seqan3::assign_char_to(c, v) };
1106 };
1108 
1109 // ============================================================================
1110 // serialisation
1111 // ============================================================================
1112 
1134 template <cereal_output_archive archive_t, semialphabet alphabet_t>
1135 alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1136 {
1137  return to_rank(l);
1138 }
1139 
1153 template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1154 void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1155  wrapped_alphabet_t && l,
1156  alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1158 {
1159  assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1160 }
1165 } // namespace seqan3
1166 
1167 namespace seqan3::detail
1168 {
1169 // ============================================================================
1170 // constexpr_semialphabet
1171 // ============================================================================
1172 
1182 template <typename t>
1183 SEQAN3_CONCEPT constexpr_semialphabet = semialphabet<t> && requires
1184 {
1185  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1187 };
1189 
1190 // ============================================================================
1191 // writable_constexpr_semialphabet
1192 // ============================================================================
1193 
1204 template <typename t>
1205 SEQAN3_CONCEPT writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires
1206 {
1207  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1208  requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
1209 };
1211 
1212 // ============================================================================
1213 // constexpr_alphabet
1214 // ============================================================================
1215 
1226 template <typename t>
1227 SEQAN3_CONCEPT constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires
1228 {
1229  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1231 };
1233 
1234 // ============================================================================
1235 // writable_constexpr_alphabet
1236 // ============================================================================
1237 
1249 template <typename t>
1250 SEQAN3_CONCEPT writable_constexpr_alphabet =
1251  constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires
1252 {
1253  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1254  requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1255 };
1257 
1258 } // namespace seqan3::detail
Exceptions thrown by entities in the alphabet module.
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:113
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:523
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:384
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:164
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:858
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:291
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:396
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:667
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition: concept.hpp:731
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:155
#define SEQAN3_IS_CONSTEXPR(...)
Returns true if the expression passed to this macro can be evaluated at compile time,...
Definition: basic.hpp:28
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
#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.
Provides C++20 additions to the type_traits header.
Provides various type traits on generic types.