SeqAn3  3.1.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 <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.
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
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.