SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
affine_cell_proxy.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/concepts>
16#include <tuple>
17#include <type_traits>
18
24
25namespace seqan3::detail
26{
27
33template <typename t>
34SEQAN3_CONCEPT arithmetic_or_simd = arithmetic<t> || simd_concept<t>;
36
43template <typename t>
44SEQAN3_CONCEPT tracedirections_or_simd = std::same_as<std::remove_cvref_t<t>, trace_directions> || simd_concept<t>;
46
58template <typename t>
59SEQAN3_CONCEPT affine_score_cell = tuple_like<t> &&
60 std::tuple_size_v<t> == 3 &&
61 arithmetic_or_simd<std::remove_reference_t<std::tuple_element_t<0, t>>> &&
62 arithmetic_or_simd<std::remove_reference_t<std::tuple_element_t<1, t>>> &&
63 arithmetic_or_simd<std::remove_reference_t<std::tuple_element_t<2, t>>>;
65
77template <typename t>
78SEQAN3_CONCEPT affine_trace_cell = tuple_like<t> &&
79 std::tuple_size_v<t> == 3 &&
80 tracedirections_or_simd<std::remove_reference_t<std::tuple_element_t<0, t>>> &&
81 tracedirections_or_simd<std::remove_reference_t<std::tuple_element_t<1, t>>> &&
82 tracedirections_or_simd<std::remove_reference_t<std::tuple_element_t<2, t>>>;
84
96template <typename t>
97SEQAN3_CONCEPT affine_score_and_trace_cell = tuple_like<t> &&
98 std::tuple_size_v<t> == 2 &&
99 affine_score_cell<std::tuple_element_t<0, t>> &&
100 affine_trace_cell<std::tuple_element_t<1, t>>;
102
117template <typename tuple_t>
119 requires (affine_score_cell<tuple_t> || affine_score_and_trace_cell<tuple_t>)
121class affine_cell_proxy : public tuple_t
122{
123private:
125 using score_cell_type = std::conditional_t<affine_score_cell<tuple_t>, tuple_t, std::tuple_element_t<0, tuple_t>>;
128 std::tuple_element_t<1, tuple_t>,
129 empty_type>;
130
131public:
135 affine_cell_proxy() = default;
136 affine_cell_proxy(affine_cell_proxy const &) = default;
137 affine_cell_proxy(affine_cell_proxy &&) = default;
138 affine_cell_proxy & operator=(affine_cell_proxy const &) = default;
139 affine_cell_proxy & operator=(affine_cell_proxy &&) = default;
140 ~affine_cell_proxy() = default;
141
142 // Inherit the base class's constructor to enable element-wise initialisation (direct and converting constructor).
143 using tuple_t::tuple_t;
144
146 template <typename other_tuple_t>
148 requires std::constructible_from<tuple_t, other_tuple_t &&>
150 explicit affine_cell_proxy(other_tuple_t && other) :
151 tuple_t{std::forward<other_tuple_t>(other)}
152 {}
153
155 template <typename other_tuple_t>
157 requires std::constructible_from<tuple_t, other_tuple_t const &>
159 explicit affine_cell_proxy(affine_cell_proxy<other_tuple_t> const & other) :
160 tuple_t{static_cast<other_tuple_t const &>(other)}
161 {}
162
164 template <typename other_tuple_t>
166 requires std::constructible_from<tuple_t, other_tuple_t>
168 explicit affine_cell_proxy(affine_cell_proxy<other_tuple_t> && other) :
169 tuple_t{static_cast<other_tuple_t &&>(std::move(other))}
170 {}
171
173 template <typename other_tuple_t>
175 requires std::assignable_from<tuple_t &, other_tuple_t &&>
177 affine_cell_proxy & operator=(other_tuple_t && other)
178 {
179 as_base() = std::forward<other_tuple_t>(other);
180 return *this;
181 }
182
184 template <typename other_tuple_t>
186 requires std::assignable_from<tuple_t &, other_tuple_t const &>
188 affine_cell_proxy & operator=(affine_cell_proxy<other_tuple_t> const & other)
189 {
190 as_base() = static_cast<other_tuple_t const &>(other);
191 return *this;
192 }
193
195 template <typename other_tuple_t>
197 requires std::assignable_from<tuple_t &, other_tuple_t>
199 affine_cell_proxy & operator=(affine_cell_proxy<other_tuple_t> && other)
200 {
201 as_base() = static_cast<other_tuple_t &&>(std::move(other));
202 return *this;
203 }
205
211 decltype(auto) best_score() & noexcept { return get_score_impl<0>(*this); }
213 decltype(auto) best_score() const & noexcept { return get_score_impl<0>(*this); }
215 decltype(auto) best_score() && noexcept { return get_score_impl<0>(std::move(*this)); }
217 decltype(auto) best_score() const && noexcept
218 {
219#if SEQAN3_WORKAROUND_GCC_94967
220 // A simple std::move(...) does not work, because it would mess up tuple_element types like `int const &`
221 using return_t = std::tuple_element_t<0, score_cell_type>;
222 return static_cast<return_t const &&>(get_score_impl<0>(std::move(*this)));
223#else // ^^^ workaround / no workaround vvv
224 return get_score_impl<0>(std::move(*this));
225#endif // SEQAN3_WORKAROUND_GCC_94967
226 }
227
229 decltype(auto) horizontal_score() & noexcept { return get_score_impl<1>(*this); }
231 decltype(auto) horizontal_score() const & noexcept { return get_score_impl<1>(*this); }
233 decltype(auto) horizontal_score() && noexcept { return get_score_impl<1>(std::move(*this)); }
235 decltype(auto) horizontal_score() const && noexcept
236 {
237#if SEQAN3_WORKAROUND_GCC_94967
238 // A simple std::move(...) does not work, because it would mess up tuple_element types like `int const &`
239 using return_t = std::tuple_element_t<1, score_cell_type>;
240 return static_cast<return_t const &&>(get_score_impl<1>(std::move(*this)));
241#else // ^^^ workaround / no workaround vvv
242 return get_score_impl<1>(std::move(*this));
243#endif // SEQAN3_WORKAROUND_GCC_94967
244 }
245
247 decltype(auto) vertical_score() & noexcept { return get_score_impl<2>(*this); }
249 decltype(auto) vertical_score() const & noexcept { return get_score_impl<2>(*this); }
251 decltype(auto) vertical_score() && noexcept { return get_score_impl<2>(std::move(*this)); }
253 decltype(auto) vertical_score() const && noexcept
254 {
255#if SEQAN3_WORKAROUND_GCC_94967
256 // A simple std::move(...) does not work, because it would mess up tuple_element types like `int const &`
257 using return_t = std::tuple_element_t<2, score_cell_type>;
258 return static_cast<return_t const &&>(get_score_impl<2>(std::move(*this)));
259#else // ^^^ workaround / no workaround vvv
260 return get_score_impl<2>(std::move(*this));
261#endif // SEQAN3_WORKAROUND_GCC_94967
262 }
264
270 decltype(auto) best_trace() & noexcept
272 requires affine_score_and_trace_cell<tuple_t>
274 {
275 return get_trace_impl<0>(*this);
276 }
278 decltype(auto) best_trace() const & noexcept
280 requires affine_score_and_trace_cell<tuple_t>
282 {
283 return get_trace_impl<0>(*this);
284 }
286 decltype(auto) best_trace() && noexcept
288 requires affine_score_and_trace_cell<tuple_t>
290 {
291 return get_trace_impl<0>(std::move(*this));
292 }
294 decltype(auto) best_trace() const && noexcept
296 requires affine_score_and_trace_cell<tuple_t>
298 {
299#if SEQAN3_WORKAROUND_GCC_94967
300 // A simple std::move(...) does not work, because it would mess up tuple_element types like `int const &`
301 using return_t = std::tuple_element_t<0, trace_cell_type>;
302 return static_cast<return_t const &&>(get_trace_impl<0>(std::move(*this)));
303#else // ^^^ workaround / no workaround vvv
304 return get_trace_impl<0>(std::move(*this));
305#endif // SEQAN3_WORKAROUND_GCC_94967
306 }
307
309 decltype(auto) horizontal_trace() & noexcept
311 requires affine_score_and_trace_cell<tuple_t>
313 {
314 return get_trace_impl<1>(*this);
315 }
317 decltype(auto) horizontal_trace() const & noexcept
319 requires affine_score_and_trace_cell<tuple_t>
321 {
322 return get_trace_impl<1>(*this);
323 }
325 decltype(auto) horizontal_trace() && noexcept
327 requires affine_score_and_trace_cell<tuple_t>
329 {
330 return get_trace_impl<1>(std::move(*this));
331 }
333 decltype(auto) horizontal_trace() const && noexcept
335 requires affine_score_and_trace_cell<tuple_t>
337 {
338#if SEQAN3_WORKAROUND_GCC_94967
339 // A simple std::move(...) does not work, because it would mess up tuple_element types like `int const &`
340 using return_t = std::tuple_element_t<1, trace_cell_type>;
341 return static_cast<return_t const &&>(get_trace_impl<1>(std::move(*this)));
342#else // ^^^ workaround / no workaround vvv
343 return get_trace_impl<1>(std::move(*this));
344#endif // SEQAN3_WORKAROUND_GCC_94967
345 }
346
348 decltype(auto) vertical_trace() & noexcept
350 requires affine_score_and_trace_cell<tuple_t>
352 {
353 return get_trace_impl<2>(*this);
354 }
356 decltype(auto) vertical_trace() const & noexcept
358 requires affine_score_and_trace_cell<tuple_t>
360 {
361 return get_trace_impl<2>(*this);
362 }
364 decltype(auto) vertical_trace() && noexcept
366 requires affine_score_and_trace_cell<tuple_t>
368 {
369 return get_trace_impl<2>(std::move(*this));
370 }
372 decltype(auto) vertical_trace() const && noexcept
374 requires affine_score_and_trace_cell<tuple_t>
376 {
377#if SEQAN3_WORKAROUND_GCC_94967
378 // A simple std::move(...) does not work, because it would mess up tuple_element types like `int const &`
379 using return_t = std::tuple_element_t<2, trace_cell_type>;
380 return static_cast<return_t const &&>(get_trace_impl<2>(std::move(*this)));
381#else // ^^^ workaround / no workaround vvv
382 return get_trace_impl<2>(std::move(*this));
383#endif // SEQAN3_WORKAROUND_GCC_94967
384 }
386
387private:
396 template <size_t index, typename this_t>
398 requires (index < 3)
400 static constexpr decltype(auto) get_score_impl(this_t && me) noexcept
401 {
402 using std::get;
403
404 if constexpr (affine_score_cell<tuple_t>)
405 return get<index>(std::forward<this_t>(me));
406 else
407 return get<index>(get<0>(std::forward<this_t>(me)));
408 }
409
418 template <size_t index, typename this_t>
420 requires (index < 3 && affine_score_and_trace_cell<tuple_t>)
422 static constexpr decltype(auto) get_trace_impl(this_t && me) noexcept
423 {
424 using std::get;
425
426 return get<index>(get<1>(std::forward<this_t>(me)));
427 }
428
430 tuple_t & as_base() & noexcept
431 {
432 return static_cast<tuple_t &>(*this);
433 }
434};
435} // namespace seqan3::detail
436
437namespace std
438{
440template <typename tuple_t>
442 requires (seqan3::detail::affine_score_cell<tuple_t> || seqan3::detail::affine_score_and_trace_cell<tuple_t>)
444struct tuple_size<seqan3::detail::affine_cell_proxy<tuple_t>> : public tuple_size<tuple_t>
445{};
446
447template <size_t index, typename tuple_t>
449 requires (seqan3::detail::affine_score_cell<tuple_t> || seqan3::detail::affine_score_and_trace_cell<tuple_t>)
451struct tuple_element<index, seqan3::detail::affine_cell_proxy<tuple_t>> : public tuple_element<index, tuple_t>
452{};
454} // namespace std
The <concepts> header from C++20's standard library.
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
Provides seqan3::detail::empty_type.
T forward(T... args)
A type that satisfies std::is_arithmetic_v<t>.
Whether a type behaves like a tuple.
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:429
SeqAn specific customisations in the standard namespace.
Provides the declaration of seqan3::detail::trace_directions.
Provides seqan3::simd::simd_concept.
Provides seqan3::tuple_like.