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
15#include <array>
16#include <seqan3/std/concepts>
17#include <functional>
18#include <type_traits>
19
21
22namespace seqan3
23{
25// Forward declarations
26struct pipeable_config_element;
28}
29
30namespace seqan3::detail
31{
32
33// ----------------------------------------------------------------------------
34// compatibility_table
35// ----------------------------------------------------------------------------
36
42template <typename algorithm_id_type>
43inline 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
59struct config_id_accessor
60{
61private:
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
80public:
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
138template <typename config_t>
139SEQAN3_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
167template <typename config1_t, typename config2_t>
168SEQAN3_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
183namespace seqan3
184{
186// Forward declaration.
187template <detail::config_element ... configs_t>
188class configuration;
190
211template <typename config1_t, typename config2_t>
212inline constexpr bool is_config_element_combineable_v = detail::config_element_pipeable_with<config1_t, config2_t>;
213
215// Specialised for config2_t == seqan3::configuration
216template <typename config1_t, typename ...configs2_t>
217inline 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
221template <typename ...configs1_t, typename config2_t>
222inline 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
226template <typename ...configs1_t, typename ...configs2_t>
227inline 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> header from C++20's standard library.
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: cigar_operation_table.hpp:2
Provides type traits for working with templates.