SeqAn3  3.0.3
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 
25 namespace seqan3::detail
26 {
27 
33 template <typename t>
34 SEQAN3_CONCEPT arithmetic_or_simd = arithmetic<t> || simd_concept<t>;
36 
43 template <typename t>
44 SEQAN3_CONCEPT tracedirections_or_simd = std::same_as<std::remove_cvref_t<t>, trace_directions> || simd_concept<t>;
46 
58 template <typename t>
59 SEQAN3_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 
77 template <typename t>
78 SEQAN3_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 
96 template <typename t>
97 SEQAN3_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 
117 template <typename tuple_t>
119  requires (affine_score_cell<tuple_t> || affine_score_and_trace_cell<tuple_t>)
121 class affine_cell_proxy : public tuple_t
122 {
123 private:
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 
131 public:
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 
387 private:
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 
437 namespace std
438 {
440 template <typename tuple_t>
442  requires (seqan3::detail::affine_score_cell<tuple_t> || seqan3::detail::affine_score_and_trace_cell<tuple_t>)
444 struct tuple_size<seqan3::detail::affine_cell_proxy<tuple_t>> : public tuple_size<tuple_t>
445 {};
446 
447 template <size_t index, typename tuple_t>
449  requires (seqan3::detail::affine_score_cell<tuple_t> || seqan3::detail::affine_score_and_trace_cell<tuple_t>)
451 struct tuple_element<index, seqan3::detail::affine_cell_proxy<tuple_t>> : public tuple_element<index, tuple_t>
452 {};
454 } // namespace std
The Concepts library.
Provides seqan3::detail::empty_type.
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
T forward(T... args)
constexpr auto get
A view calling get on each element in a range.
Definition: elements.hpp:114
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:74
A type that satisfies std::is_arithmetic_v<t>.
Whether a type behaves like a tuple.
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
SeqAn specific customisations in the standard namespace.
Provides the declaration of seqan3::detail::trace_directions.
Provides seqan3::simd::simd_concept.
Provides seqan3::tuple_like.