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 <array>
16 #include <seqan3/std/concepts>
17 #include <functional>
18 #include <type_traits>
19 
21 
22 namespace seqan3
23 {
25 // Forward declarations
26 struct pipeable_config_element;
28 }
29 
30 namespace seqan3::detail
31 {
32 
33 // ----------------------------------------------------------------------------
34 // compatibility_table
35 // ----------------------------------------------------------------------------
36 
42 template <typename algorithm_id_type>
43 inline constexpr std::array<std::array<void *, 0>, 0> compatibility_table{};
44 
45 // ----------------------------------------------------------------------------
46 // Concept config_element
47 // ----------------------------------------------------------------------------
48 
49 #if SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
59 struct config_id_accessor
60 {
61 private:
63  template <typename config_t>
64  static constexpr int32_t as_int = static_cast<int32_t>(std::remove_cvref_t<config_t>::id);
65 
67  template <typename config_t>
68  static constexpr auto has_id_member(int) -> decltype((static_cast<void>(config_t::id), true))
69  {
70  return true;
71  }
72 
74  template <typename config_t>
75  static constexpr bool has_id_member(...)
76  {
77  return false;
78  }
79 
80 public:
82  template <typename config_t>
83  using id_type = std::remove_cvref_t<decltype(config_t::id)>;
84 
95  template <typename config1_t, typename config2_t>
96  static constexpr auto is_compatible()
97  {
98  if constexpr (has_id_member<config1_t>(0) && has_id_member<config2_t>(0)) // needed for gcc <= 9
99  {
100  using config1_id_t = id_type<config1_t>;
101  using config2_id_t = id_type<config2_t>;
102 
103  if constexpr (std::same_as<config1_id_t, config2_id_t>)
104  return std::bool_constant<compatibility_table<config1_id_t>[as_int<config1_t>][as_int<config2_t>]>{};
105  else
106  return std::false_type{};
107  }
108  else
109  {
110  return std::false_type{};
111  }
112  }
113 
115  template <typename config_t>
116  static constexpr bool has_id = has_id_member<config_t>(0);
117 };
118 #endif // SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
119 
138 template <typename config_t>
139 SEQAN3_CONCEPT config_element = requires
140 {
141  requires std::is_base_of_v<seqan3::pipeable_config_element, config_t>;
142  requires std::semiregular<config_t>;
143 #if SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
144  requires config_id_accessor::has_id<config_t>;
145 #else // ^^^ workaround / no workaround vvv
146  { config_t::id };
147 #endif // SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
148 };
150 
167 template <typename config1_t, typename config2_t>
168 SEQAN3_CONCEPT config_element_pipeable_with =
169  config_element<config1_t> &&
170  config_element<config2_t> &&
171 #if SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
172  std::same_as<config_id_accessor::id_type<config1_t>, config_id_accessor::id_type<config2_t>> &&
173  decltype(config_id_accessor::is_compatible<config1_t, config2_t>())::value;
174 #else // ^^^ workaround / no workaround vvv
175  std::same_as<std::remove_cvref_t<decltype(config1_t::id)>, std::remove_cvref_t<decltype(config2_t::id)>> &&
176  compatibility_table<std::remove_cvref_t<decltype(config1_t::id)>>[static_cast<int32_t>(config1_t::id)]
177  [static_cast<int32_t>(config2_t::id)];
178 #endif // SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
180 
181 } // namespace seqan3::detail
182 
183 namespace seqan3
184 {
186 // Forward declaration.
187 template <detail::config_element ... configs_t>
188 class configuration;
190 
211 template <typename config1_t, typename config2_t>
212 inline constexpr bool is_config_element_combineable_v = detail::config_element_pipeable_with<config1_t, config2_t>;
213 
215 // Specialised for config2_t == seqan3::configuration
216 template <typename config1_t, typename ...configs2_t>
217 inline constexpr bool is_config_element_combineable_v<config1_t, configuration<configs2_t...>> =
218  (detail::config_element_pipeable_with<config1_t, configs2_t> && ...);
219 
220 // Specialised for config1_t == seqan3::configuration
221 template <typename ...configs1_t, typename config2_t>
222 inline constexpr bool is_config_element_combineable_v<configuration<configs1_t...>, config2_t> =
223  (detail::config_element_pipeable_with<configs1_t, config2_t> && ...);
224 
225 // Specialised for config1_t == seqan3::configuration && config2_t == seqan3::configuration
226 template <typename ...configs1_t, typename ...configs2_t>
227 inline constexpr bool is_config_element_combineable_v<configuration<configs1_t...>, configuration<configs2_t...>> =
228  (is_config_element_combineable_v<configs1_t, configuration<configs2_t...>> && ...);
230 
231 } // namespace seqan3
Collection of elements to configure an algorithm.
Definition: configuration.hpp:45
The Concepts library.
Provides type traits for working with templates.
constexpr bool is_config_element_combineable_v
Helper variable template to test if a configuration element is combineable with another configuration...
Definition: concept.hpp:212
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29