SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
configuration.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 <tuple>
16 
17 #include <meta/meta.hpp>
18 
25 #include <seqan3/std/concepts>
26 
27 namespace seqan3
28 {
29 
31 // Forward declaration for friend declaration definitions below.
32 template <detail::config_element ... configs_t>
33 class configuration;
34 
35 template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
36 constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> && lhs,
37  pipeable_config_element<rhs_derived_t, rhs_value_t> && rhs)
38 {
39  return configuration{static_cast<lhs_derived_t &&>(lhs)}.push_back(static_cast<rhs_derived_t &&>(rhs));
40 }
41 
42 template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
43 constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> && lhs,
44  pipeable_config_element<rhs_derived_t, rhs_value_t> const & rhs)
45 {
46  return configuration{static_cast<lhs_derived_t &&>(lhs)}.push_back(static_cast<rhs_derived_t const &>(rhs));
47 }
48 
49 template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
50 constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> const & lhs,
51  pipeable_config_element<rhs_derived_t, rhs_value_t> && rhs)
52 {
53  return configuration{static_cast<lhs_derived_t const &>(lhs)}.push_back(static_cast<rhs_derived_t &&>(rhs));
54 }
55 
56 template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
57 constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> const & lhs,
58  pipeable_config_element<rhs_derived_t, rhs_value_t> const & rhs)
59 {
60  return configuration{static_cast<lhs_derived_t const &>(lhs)}.push_back(static_cast<rhs_derived_t const &>(rhs));
61 }
63 
64 // ----------------------------------------------------------------------------
65 // configuration
66 // ----------------------------------------------------------------------------
67 
80 template <detail::config_element ... configs_t>
81 class configuration : public std::tuple<configs_t...>
82 {
84  template <detail::config_element ... _configs_t>
85  friend class configuration;
86 public:
89  using base_type = std::tuple<configs_t...>;
90 
92 
95  constexpr configuration() = default;
96  constexpr configuration(configuration const &) = default;
97  constexpr configuration(configuration &&) = default;
98  constexpr configuration & operator=(configuration const &) = default;
99  constexpr configuration & operator=(configuration &&) = default;
100  ~configuration() = default;
101 
105  template <typename derived_t, typename value_t>
107  base_type{static_cast<derived_t &&>(std::move(elem))}
108  {}
109 
113  template <typename derived_t, typename value_t>
115  base_type{static_cast<derived_t const &>(elem)}
116  {}
118 
123  constexpr size_t size() const noexcept
125  {
126  return std::tuple_size_v<base_type>;
127  }
128 
155  template <typename query_t, typename default_t>
156  constexpr decltype(auto) value_or(default_t && default_value) & noexcept
157  {
158  if constexpr (exists<query_t>())
159  {
160  return get<query_t>(*this).value;
161  }
162  else
163  {
164  using ret_type = remove_rvalue_reference_t<decltype(default_value)>;
165  return static_cast<ret_type>(default_value);
166  }
167  }
168 
170  template <typename query_t, typename default_t>
171  constexpr decltype(auto) value_or(default_t && default_value) const & noexcept
172  {
173  if constexpr (exists<query_t>())
174  {
175  return get<query_t>(*this).value;
176  }
177  else
178  {
179  using ret_type = remove_rvalue_reference_t<decltype(default_value)>;
180  return static_cast<ret_type>(default_value);
181  }
182  }
183 
185  template <typename query_t, typename default_t>
186  constexpr decltype(auto) value_or(default_t && default_value) && noexcept
187  {
188  if constexpr (exists<query_t>())
189  {
190  return get<query_t>(std::move(*this)).value;
191  }
192  else
193  {
194  using ret_type = remove_rvalue_reference_t<decltype(default_value)>;
195  return static_cast<ret_type>(default_value);
196  }
197  }
198 
200  template <typename query_t, typename default_t>
201  constexpr decltype(auto) value_or(default_t && default_value) const && noexcept
202  {
203  if constexpr (exists<query_t>())
204  {
205  return get<query_t>(std::move(*this)).value;
206  }
207  else
208  {
209  using ret_type = remove_rvalue_reference_t<decltype(default_value)>;
210  return static_cast<ret_type>(default_value);
211  }
212  }
213 
215  template <template <typename ...> typename query_t, typename default_t>
216  constexpr decltype(auto) value_or(default_t && default_value) & noexcept
217  {
218  if constexpr (exists<query_t>())
219  {
220  return get<query_t>(*this).value;
221  }
222  else
223  {
224  using ret_type = remove_rvalue_reference_t<decltype(default_value)>;
225  return static_cast<ret_type>(default_value);
226  }
227  }
228 
230  template <template <typename ...> typename query_t, typename default_t>
231  constexpr decltype(auto) value_or(default_t && default_value) const & noexcept
232  {
233  if constexpr (exists<query_t>())
234  {
235  return get<query_t>(*this).value;
236  }
237  else
238  {
239  using ret_type = remove_rvalue_reference_t<decltype(default_value)>;
240  return static_cast<ret_type>(default_value);
241  }
242  }
243 
245  template <template <typename ...> typename query_t, typename default_t>
246  constexpr decltype(auto) value_or(default_t && default_value) && noexcept
247  {
248  if constexpr (exists<query_t>())
249  {
250  return get<query_t>(std::move(*this)).value;
251  }
252  else
253  {
254  using ret_type = remove_rvalue_reference_t<decltype(default_value)>;
255  return static_cast<ret_type>(default_value);
256  }
257  }
258 
260  template <template <typename ...> typename query_t, typename default_t>
261  constexpr decltype(auto) value_or(default_t && default_value) const && noexcept
262  {
263  if constexpr (exists<query_t>())
264  {
265  return get<query_t>(std::move(*this)).value;
266  }
267  else
268  {
269  using ret_type = remove_rvalue_reference_t<decltype(default_value)>;
270  return static_cast<ret_type>(default_value);
271  }
272  }
273 
275  template <typename query_t>
276  static constexpr bool exists() noexcept
277  {
278  return pack_traits::contains<query_t, configs_t...>;
279  }
281  template <template <typename ...> typename query_t>
282  static constexpr bool exists() noexcept
283  {
284  return (pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...> > -1);
285  }
287 
300  template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
303 
305  template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
308 
310  template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
311  friend constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> const & lhs,
313 
315  template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
316  friend constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> const & lhs,
318 
326  template <typename rhs_derived_t, typename rhs_value_t>
327  friend constexpr auto operator|(configuration && lhs,
329  {
330  return std::move(lhs).push_back(static_cast<rhs_derived_t &&>(rhs));
331  }
332 
334  template <typename rhs_derived_t, typename rhs_value_t>
335  friend constexpr auto operator|(configuration const & lhs,
337  {
338  return lhs.push_back(static_cast<rhs_derived_t &&>(rhs));
339  }
340 
342  template <typename rhs_derived_t, typename rhs_value_t>
343  friend constexpr auto operator|(configuration && lhs,
345  {
346  return std::move(lhs).push_back(static_cast<rhs_derived_t const &>(rhs));
347  }
348 
350  template <typename rhs_derived_t, typename rhs_value_t>
351  friend constexpr auto operator|(configuration const & lhs,
353  {
354  return lhs.push_back(static_cast<rhs_derived_t const &>(rhs));
355  }
356 
363  template <typename ...rhs_configs_t>
364  friend constexpr auto operator|(configuration && lhs,
366  {
367  using lhs_base_t = typename configuration::base_type;
368  using rhs_base_t = typename configuration<rhs_configs_t...>::base_type;
369 
370  return make_configuration(std::tuple_cat(static_cast<lhs_base_t>(std::move(lhs)),
371  static_cast<rhs_base_t>(std::move(rhs))));
372  }
373 
375  template <typename ...rhs_configs_t>
376  friend constexpr auto operator|(configuration const & lhs,
378  {
379  using lhs_base_t = typename configuration::base_type;
380  using rhs_base_t = typename configuration<rhs_configs_t...>::base_type;
381 
382  return make_configuration(std::tuple_cat(static_cast<lhs_base_t>(lhs),
383  static_cast<rhs_base_t>(std::move(rhs))));
384  }
385 
387  template <typename ...rhs_configs_t>
388  friend constexpr auto operator|(configuration && lhs,
390  {
391  using lhs_base_t = typename configuration::base_type;
392  using rhs_base_t = typename configuration<rhs_configs_t...>::base_type;
393 
394  return make_configuration(std::tuple_cat(static_cast<lhs_base_t>(std::move(lhs)),
395  static_cast<rhs_base_t>(rhs)));
396  }
397 
399  template <typename ...rhs_configs_t>
400  friend constexpr auto operator|(configuration const & lhs,
402  {
403  using lhs_base_t = typename configuration::base_type;
404  using rhs_base_t = typename configuration<rhs_configs_t...>::base_type;
405 
406  return make_configuration(std::tuple_cat(static_cast<lhs_base_t>(lhs),
407  static_cast<rhs_base_t>(rhs)));
408  }
410 
411 private:
412 
416  template <typename ..._configs_t>
418  explicit constexpr configuration(std::tuple<_configs_t...> const & cfg) : base_type{cfg}
419  {}
420 
422  template <typename ..._configs_t>
423  explicit constexpr configuration(std::tuple<_configs_t...> && cfg) : base_type{std::move(cfg)}
424  {}
426 
433  template <typename tuple_t>
435  requires detail::is_type_specialisation_of_v<tuple_t, std::tuple> &&
436  std::tuple_size_v<remove_cvref_t<tuple_t>> > 0
438  static constexpr auto make_configuration(tuple_t && tpl)
439  {
440  auto make_config = [](auto && tpl)
441  {
442  auto impl = [](auto & impl_ref, auto && config, auto && head, auto && tail)
443  {
444  if constexpr (std::tuple_size_v<remove_cvref_t<decltype(tail)>> == 0)
445  {
446  return std::forward<decltype(config)>(config).push_back(std::get<0>(std::forward<decltype(head)>(head)));
447  }
448  else
449  {
450  auto [_head, _tail] = tuple_split<1>(std::forward<decltype(tail)>(tail));
451  auto tmp = std::forward<decltype(config)>(config).push_back(
452  std::get<0>(std::forward<decltype(head)>(head)));
453  return impl_ref(impl_ref, std::move(tmp), std::move(_head), std::move(_tail));
454  }
455  };
456  auto [head, tail] = tuple_split<1>(std::forward<decltype(tpl)>(tpl));
457  return impl(impl, configuration<>{}, std::move(head), std::move(tail));
458  };
459  return make_config(std::forward<tuple_t>(tpl));
460  }
461 
488  template <detail::config_element config_element_t>
489  constexpr auto push_back(config_element_t elem) const &
490  {
491  static_assert(detail::is_configuration_valid_v<remove_cvref_t<config_element_t>,
492  configs_t...>,
493  "Configuration error: The passed element cannot be combined with one or more elements in the "
494  "current configuration.");
495 
497  std::tuple_cat(static_cast<base_type>(*this),
498  std::tuple{std::move(elem)})};
499  }
500 
502  template <detail::config_element config_element_t>
503  constexpr auto push_back(config_element_t elem) &&
504  {
505  static_assert(detail::is_configuration_valid_v<remove_cvref_t<config_element_t>,
506  configs_t...>,
507  "Configuration error: The passed element cannot be combined with one or more elements in the "
508  "current configuration.");
509 
511  std::tuple_cat(std::move(static_cast<base_type>(*this)),
512  std::tuple{std::move(elem)})};
513  }
515 };
516 
524 template <typename derived_t, typename value_t>
525 configuration(pipeable_config_element<derived_t, value_t> &&) -> configuration<remove_cvref_t<derived_t>>;
526 
530 template <typename derived_t, typename value_t>
531 configuration(pipeable_config_element<derived_t, value_t> const &) -> configuration<remove_cvref_t<derived_t>>;
533 
565 template <template <typename ...> class query_t, typename ...configs_t>
566 constexpr auto & get(configuration<configs_t...> & config) noexcept
567 {
568  constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
569  static_assert(pos > -1, "Access error: The requested type is not contained.");
570 
571  return get<pos>(config);
572 }
573 
575 template <template <typename ...> class query_t, typename ...configs_t>
576 constexpr auto const & get(configuration<configs_t...> const & config) noexcept
577 {
578  constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
579  static_assert(pos > -1, "Access error: The requested type is not contained.");
580 
581  return get<pos>(config);
582 }
583 
585 template <template <typename ...> class query_t, typename ...configs_t>
586 constexpr auto && get(configuration<configs_t...> && config) noexcept
587 {
588  constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
589  static_assert(pos > -1, "Access error: The requested type is not contained.");
590 
591  return get<pos>(std::move(config));
592 }
593 
595 template <template <typename ...> class query_t, typename ...configs_t>
596 constexpr auto const && get(configuration<configs_t...> const && config) noexcept
597 {
598  constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
599  static_assert(pos > -1, "Access error: The requested type is not contained.");
600 
601  // TODO: change after GCC-7 bug with const && version of get in std::tuple is fixed.
602  // return get<pos>(std::move(config));
603  return std::move(get<pos>(config));
604 }
606 
607 } // namespace seqan3::detail
608 
609 namespace std
610 {
612 
618 template <seqan3::detail::config_element ... configs_t>
619 struct tuple_size<seqan3::configuration<configs_t...>>
620 {
622  static constexpr size_t value = std::tuple_size_v<typename seqan3::configuration<configs_t...>::base_type>;
623 };
624 
630 template <size_t pos, seqan3::detail::config_element ... configs_t>
631 struct tuple_element<pos, seqan3::configuration<configs_t...>>
632 {
634  using type = std::tuple_element_t<pos, typename seqan3::configuration<configs_t...>::base_type>;
635 };
637 } //namespace std
seqan3::remove_cvref_t
std::remove_cv_t< std::remove_reference_t< t > > remove_cvref_t
Return the input type with const, volatile and references removed (type trait).
Definition: basic.hpp:35
seqan3::configuration::configuration
constexpr configuration(pipeable_config_element< derived_t, value_t > const &elem)
Constructs a configuration from a single configuration element.
Definition: configuration.hpp:114
seqan3::configuration::operator|
constexpr friend auto operator|(configuration const &lhs, pipeable_config_element< rhs_derived_t, rhs_value_t > &&rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:335
seqan3::views::move
const auto move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
tuple
pipeable_config_element.hpp
Provides seqan3::pipeable_config_element.
seqan3::configuration::exists
static constexpr bool exists() noexcept
Checks if the given type exists in the tuple.
Definition: configuration.hpp:276
seqan3::configuration::operator|
constexpr friend auto operator|(configuration &&lhs, pipeable_config_element< rhs_derived_t, rhs_value_t > const &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:343
seqan3::pack_traits::contains
constexpr bool contains
Whether a type occurs in a pack or not.
Definition: traits.hpp:193
seqan3::operator|
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1023
concepts
The Concepts library.
concept.hpp
Provides concepts for the configuration classes.
seqan3::configuration
Collection of elements to configure an algorithm.
Definition: configuration.hpp:81
tuple_utility.hpp
Provides utility functions for tuple like interfaces.
std::forward
T forward(T... args)
seqan3::configuration::size
constexpr size_t size() const noexcept
Returns the number of contained config elements.
Definition: configuration.hpp:124
seqan3::configuration::operator|
constexpr friend auto operator|(configuration &&lhs, pipeable_config_element< rhs_derived_t, rhs_value_t > &&rhs)
Combines a seqan3::configuration with a seqan3::pipeable_config_element.
Definition: configuration.hpp:327
seqan3::remove_rvalue_reference_t
typename remove_rvalue_reference< t >::type remove_rvalue_reference_t
Return the input type with && removed, but lvalue references preserved (transformation_trait shortcut...
Definition: basic.hpp:58
seqan3
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:36
seqan3::pack_traits::find_if
constexpr ptrdiff_t find_if
Get the index of the first type in a pack that satisfies the given predicate.
Definition: traits.hpp:175
seqan3::pipeable_config_element
Adds pipe interface to configuration elements.
Definition: pipeable_config_element.hpp:30
seqan3::configuration::value_or
constexpr decltype(auto) value_or(default_t &&default_value) &noexcept
Returns the contained value if *this has a value, otherwise returns default_value.
Definition: configuration.hpp:156
seqan3::configuration::operator|
constexpr friend auto operator|(configuration &&lhs, configuration< rhs_configs_t... > const &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:388
seqan3::configuration::operator|
constexpr friend auto operator|(configuration &&lhs, configuration< rhs_configs_t... > &&rhs)
Combines two seqan3::configuration objects.
Definition: configuration.hpp:364
seqan3::configuration::~configuration
~configuration()=default
Defaulted.
seqan3::configuration::configuration
constexpr configuration()=default
Defaulted.
seqan3::configuration::operator=
constexpr configuration & operator=(configuration const &)=default
Defaulted.
seqan3::configuration::operator|
constexpr friend auto operator|(configuration const &lhs, configuration< rhs_configs_t... > const &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:400
std::remove_reference_t
seqan3::configuration::operator|
constexpr friend auto operator|(pipeable_config_element< lhs_derived_t, lhs_value_t > &&lhs, pipeable_config_element< rhs_derived_t, rhs_value_t > &&rhs)
Combines two seqan3::pipeable_config_element objects to a seqan3::configuration.
configuration_utility.hpp
Provides functionality to access get function by enum values.
std
SeqAn specific customisations in the standard namespace.
seqan3::configuration::get
constexpr auto & get(configuration< configs_t... > &config) noexcept
Returns the stored element.
Definition: configuration.hpp:566
std::tuple_cat
T tuple_cat(T... args)
traits.hpp
Provides traits for seqan3::type_list.
seqan3::configuration::operator|
constexpr friend auto operator|(configuration const &lhs, pipeable_config_element< rhs_derived_t, rhs_value_t > const &rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:351
seqan3::get
constexpr const auto & 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:576
seqan3::configuration::operator|
constexpr friend auto operator|(configuration const &lhs, configuration< rhs_configs_t... > &&rhs)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:376
std::tuple_size_v
T tuple_size_v
seqan3::configuration::configuration
constexpr configuration(pipeable_config_element< derived_t, value_t > &&elem)
Constructs a configuration from a single configuration element.
Definition: configuration.hpp:106
type_list.hpp
Provides seqan3::type_list.