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-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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/concepts>
16 #include <functional>
17 #include <type_traits>
18 
19 #include <meta/meta.hpp>
20 
22 
23 namespace seqan3
24 {
26 // Forward declarations
27 template <typename derived_t, typename value_t = void>
28 struct pipeable_config_element;
30 }
31 
32 namespace seqan3::detail
33 {
34 
35 // ----------------------------------------------------------------------------
36 // compatibility_table
37 // ----------------------------------------------------------------------------
38 
44 template <typename algorithm_id_type>
46 
47 // ----------------------------------------------------------------------------
48 // Concept config_element
49 // ----------------------------------------------------------------------------
50 
51 #if SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
61 struct config_id_accessor
62 {
63 private:
65  template <typename config_t>
66  static constexpr int32_t as_int = static_cast<int32_t>(std::remove_cvref_t<config_t>::id);
67 
69  template <typename config_t>
70  static constexpr auto has_id_member(int) -> decltype((static_cast<void>(config_t::id), true))
71  {
72  return true;
73  }
74 
76  template <typename config_t>
77  static constexpr bool has_id_member(...)
78  {
79  return false;
80  }
81 
82 public:
84  template <typename config_t>
85  using id_type = std::remove_cvref_t<decltype(config_t::id)>;
86 
97  template <typename config1_t, typename config2_t>
98  static constexpr auto is_compatible()
99  {
100  if constexpr (has_id_member<config1_t>(0) && has_id_member<config2_t>(0)) // needed for gcc <= 9
101  {
102  using config1_id_t = id_type<config1_t>;
103  using config2_id_t = id_type<config2_t>;
104 
105  if constexpr (std::same_as<config1_id_t, config2_id_t>)
106  return std::bool_constant<compatibility_table<config1_id_t>[as_int<config1_t>][as_int<config2_t>]>{};
107  else
108  return std::false_type{};
109  }
110  else
111  {
112  return std::false_type{};
113  }
114  }
115 
117  template <typename config_t>
118  static constexpr bool has_id = has_id_member<config_t>(0);
119 };
120 #endif // SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
121 
140 template <typename config_t>
141 SEQAN3_CONCEPT config_element = requires
142 {
143  requires std::is_base_of_v<seqan3::pipeable_config_element<config_t>, config_t>;
144  requires std::semiregular<config_t>;
145 #if SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
146  requires config_id_accessor::has_id<config_t>;
147 #else // ^^^ workaround / no workaround vvv
148  { config_t::id };
149 #endif // SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
150 };
152 
169 template <typename config1_t, typename config2_t>
170 SEQAN3_CONCEPT config_element_pipeable_with =
173 #if SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
174  std::same_as<config_id_accessor::id_type<config1_t>, config_id_accessor::id_type<config2_t>> &&
175  decltype(config_id_accessor::is_compatible<config1_t, config2_t>())::value;
176 #else // ^^^ workaround / no workaround vvv
177  std::same_as<std::remove_cvref_t<decltype(config1_t::id)>, std::remove_cvref_t<decltype(config2_t::id)>> &&
178  compatibility_table<std::remove_cvref_t<decltype(config1_t::id)>>[static_cast<int32_t>(config1_t::id)]
179  [static_cast<int32_t>(config2_t::id)];
180 #endif // SEQAN3_WORKAROUND_GCC_PIPEABLE_CONFIG_CONCEPT
182 
183 } // namespace seqan3::detail
184 
185 namespace seqan3
186 {
188 // Forward declaration.
189 template <detail::config_element ... configs_t>
190 class configuration;
192 
213 template <typename config1_t, typename config2_t>
214 inline constexpr bool is_config_element_combineable_v = detail::config_element_pipeable_with<config1_t, config2_t>;
215 
217 // Specialised for config2_t == seqan3::configuration
218 template <typename config1_t, typename ...configs2_t>
219 inline constexpr bool is_config_element_combineable_v<config1_t, configuration<configs2_t...>> =
220  (detail::config_element_pipeable_with<config1_t, configs2_t> && ...);
221 
222 // Specialised for config1_t == seqan3::configuration
223 template <typename ...configs1_t, typename config2_t>
224 inline constexpr bool is_config_element_combineable_v<configuration<configs1_t...>, config2_t> =
225  (detail::config_element_pipeable_with<configs1_t, config2_t> && ...);
226 
227 // Specialised for config1_t == seqan3::configuration && config2_t == seqan3::configuration
228 template <typename ...configs1_t, typename ...configs2_t>
229 inline constexpr bool is_config_element_combineable_v<configuration<configs1_t...>, configuration<configs2_t...>> =
230  (is_config_element_combineable_v<configs1_t, configuration<configs2_t...>> && ...);
232 
233 } // namespace seqan3
Collection of elements to configure an algorithm.
Definition: configuration.hpp:46
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:214
constexpr std::array< std::array< void *, 0 >, 0 > compatibility_table
Declaration of algorithm specific compatibility table.
Definition: concept.hpp:45
Concept to check if one configuration element can be combined with another configuration element.
Concept for an algorithm configuration element.
The internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29