SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
configuration.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, 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 
26 #include <seqan3/std/concepts>
27 
28 namespace seqan3
29 {
30 
32 // Forward declaration for friend declaration definitions below.
33 template <detail::ConfigElement ... configs_t>
34 class configuration;
35 
36 template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
37 constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> && lhs,
38  pipeable_config_element<rhs_derived_t, rhs_value_t> && rhs)
39 {
40  return configuration{static_cast<lhs_derived_t &&>(lhs)}.push_back(static_cast<rhs_derived_t &&>(rhs));
41 }
42 
43 template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
44 constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> && lhs,
45  pipeable_config_element<rhs_derived_t, rhs_value_t> const & rhs)
46 {
47  return configuration{static_cast<lhs_derived_t &&>(lhs)}.push_back(static_cast<rhs_derived_t const &>(rhs));
48 }
49 
50 template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
51 constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> const & lhs,
52  pipeable_config_element<rhs_derived_t, rhs_value_t> && rhs)
53 {
54  return configuration{static_cast<lhs_derived_t const &>(lhs)}.push_back(static_cast<rhs_derived_t &&>(rhs));
55 }
56 
57 template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
58 constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> const & lhs,
59  pipeable_config_element<rhs_derived_t, rhs_value_t> const & rhs)
60 {
61  return configuration{static_cast<lhs_derived_t const &>(lhs)}.push_back(static_cast<rhs_derived_t const &>(rhs));
62 }
64 
65 // ----------------------------------------------------------------------------
66 // configuration
67 // ----------------------------------------------------------------------------
68 
81 template <detail::ConfigElement ... configs_t>
82 class configuration : public std::tuple<configs_t...>
83 {
85  template <detail::ConfigElement ... _configs_t>
86  friend class configuration;
87 public:
90  using base_type = std::tuple<configs_t...>;
91 
93 
96  constexpr configuration() = default;
97  constexpr configuration(configuration const &) = default;
98  constexpr configuration(configuration &&) = default;
99  constexpr configuration & operator=(configuration const &) = default;
100  constexpr configuration & operator=(configuration &&) = default;
101  ~configuration() = default;
102 
106  template <typename derived_t, typename value_t>
108  base_type{static_cast<derived_t &&>(std::move(elem))}
109  {}
110 
114  template <typename derived_t, typename value_t>
116  base_type{static_cast<derived_t const &>(elem)}
117  {}
119 
124  constexpr size_t size() const noexcept
126  {
127  return std::tuple_size_v<base_type>;
128  }
129 
156  template <typename query_t, typename default_t>
157  constexpr decltype(auto) value_or(default_t && default_value) & noexcept
158  {
159  if constexpr (exists<query_t>())
160  {
161  return get<query_t>(*this).value;
162  }
163  else
164  {
166  return static_cast<ret_type>(default_value);
167  }
168  }
169 
171  template <typename query_t, typename default_t>
172  constexpr decltype(auto) value_or(default_t && default_value) const & noexcept
173  {
174  if constexpr (exists<query_t>())
175  {
176  return get<query_t>(*this).value;
177  }
178  else
179  {
181  return static_cast<ret_type>(default_value);
182  }
183  }
184 
186  template <typename query_t, typename default_t>
187  constexpr decltype(auto) value_or(default_t && default_value) && noexcept
188  {
189  if constexpr (exists<query_t>())
190  {
191  return get<query_t>(std::move(*this)).value;
192  }
193  else
194  {
196  return static_cast<ret_type>(default_value);
197  }
198  }
199 
201  template <typename query_t, typename default_t>
202  constexpr decltype(auto) value_or(default_t && default_value) const && noexcept
203  {
204  if constexpr (exists<query_t>())
205  {
206  return get<query_t>(std::move(*this)).value;
207  }
208  else
209  {
211  return static_cast<ret_type>(default_value);
212  }
213  }
214 
216  template <template <typename...> typename query_t, typename default_t>
217  constexpr decltype(auto) value_or(default_t && default_value) & noexcept
218  {
219  if constexpr (exists<query_t>())
220  {
221  return get<query_t>(*this).value;
222  }
223  else
224  {
226  return static_cast<ret_type>(default_value);
227  }
228  }
229 
231  template <template <typename...> typename query_t, typename default_t>
232  constexpr decltype(auto) value_or(default_t && default_value) const & noexcept
233  {
234  if constexpr (exists<query_t>())
235  {
236  return get<query_t>(*this).value;
237  }
238  else
239  {
241  return static_cast<ret_type>(default_value);
242  }
243  }
244 
246  template <template <typename...> typename query_t, typename default_t>
247  constexpr decltype(auto) value_or(default_t && default_value) && noexcept
248  {
249  if constexpr (exists<query_t>())
250  {
251  return get<query_t>(std::move(*this)).value;
252  }
253  else
254  {
256  return static_cast<ret_type>(default_value);
257  }
258  }
259 
261  template <template <typename...> typename query_t, typename default_t>
262  constexpr decltype(auto) value_or(default_t && default_value) const && noexcept
263  {
264  if constexpr (exists<query_t>())
265  {
266  return get<query_t>(std::move(*this)).value;
267  }
268  else
269  {
271  return static_cast<ret_type>(default_value);
272  }
273  }
274 
276  template <typename query_t>
277  static constexpr bool exists() noexcept
278  {
279  return !meta::empty<meta::find<type_list<configs_t...>, query_t>>::value;
280  }
282  template <template <typename...> typename query_t>
283  static constexpr bool exists() noexcept
284  {
285  return !meta::empty<meta::find_if<type_list<configs_t...>, detail::is_same_configuration_f<query_t>>>::value;
286  }
288 
301  template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
304 
306  template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
309 
311  template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
312  friend constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> const & lhs,
314 
316  template <typename lhs_derived_t, typename lhs_value_t, typename rhs_derived_t, typename rhs_value_t>
317  friend constexpr auto operator|(pipeable_config_element<lhs_derived_t, lhs_value_t> const & lhs,
319 
327  template <typename rhs_derived_t, typename rhs_value_t>
328  friend constexpr auto operator|(configuration && lhs,
330  {
331  return std::move(lhs).push_back(static_cast<rhs_derived_t &&>(rhs));
332  }
333 
335  template <typename rhs_derived_t, typename rhs_value_t>
336  friend constexpr auto operator|(configuration const & lhs,
338  {
339  return lhs.push_back(static_cast<rhs_derived_t &&>(rhs));
340  }
341 
343  template <typename rhs_derived_t, typename rhs_value_t>
344  friend constexpr auto operator|(configuration && lhs,
346  {
347  return std::move(lhs).push_back(static_cast<rhs_derived_t const &>(rhs));
348  }
349 
351  template <typename rhs_derived_t, typename rhs_value_t>
352  friend constexpr auto operator|(configuration const & lhs,
354  {
355  return lhs.push_back(static_cast<rhs_derived_t const &>(rhs));
356  }
357 
364  template <typename ...rhs_configs_t>
365  friend constexpr auto operator|(configuration && lhs,
367  {
368  using lhs_base_t = typename configuration::base_type;
369  using rhs_base_t = typename configuration<rhs_configs_t...>::base_type;
370 
371  return make_configuration(std::tuple_cat(static_cast<lhs_base_t>(std::move(lhs)),
372  static_cast<rhs_base_t>(std::move(rhs))));
373  }
374 
376  template <typename ...rhs_configs_t>
377  friend constexpr auto operator|(configuration const & lhs,
379  {
380  using lhs_base_t = typename configuration::base_type;
381  using rhs_base_t = typename configuration<rhs_configs_t...>::base_type;
382 
383  return make_configuration(std::tuple_cat(static_cast<lhs_base_t>(lhs),
384  static_cast<rhs_base_t>(std::move(rhs))));
385  }
386 
388  template <typename ...rhs_configs_t>
389  friend constexpr auto operator|(configuration && lhs,
391  {
392  using lhs_base_t = typename configuration::base_type;
393  using rhs_base_t = typename configuration<rhs_configs_t...>::base_type;
394 
395  return make_configuration(std::tuple_cat(static_cast<lhs_base_t>(std::move(lhs)),
396  static_cast<rhs_base_t>(rhs)));
397  }
398 
400  template <typename ...rhs_configs_t>
401  friend constexpr auto operator|(configuration const & lhs,
403  {
404  using lhs_base_t = typename configuration::base_type;
405  using rhs_base_t = typename configuration<rhs_configs_t...>::base_type;
406 
407  return make_configuration(std::tuple_cat(static_cast<lhs_base_t>(lhs),
408  static_cast<rhs_base_t>(rhs)));
409  }
411 
412 private:
413 
417  template <typename ... _configs_t>
419  explicit constexpr configuration(std::tuple<_configs_t...> const & cfg) : base_type{cfg}
420  {}
421 
423  template <typename ... _configs_t>
424  explicit constexpr configuration(std::tuple<_configs_t...> && cfg) : base_type{std::move(cfg)}
425  {}
427 
434  template <typename tuple_t>
436  requires detail::is_type_specialisation_of_v<tuple_t, std::tuple> &&
437  std::tuple_size_v<remove_cvref_t<tuple_t>> > 0
439  static constexpr auto make_configuration(tuple_t && tpl)
440  {
441  auto make_config = [](auto && tpl)
442  {
443  auto impl = [](auto & impl_ref, auto && config, auto && head, auto && tail)
444  {
445  if constexpr (std::tuple_size_v<remove_cvref_t<decltype(tail)>> == 0)
446  {
447  return std::forward<decltype(config)>(config).push_back(std::get<0>(std::forward<decltype(head)>(head)));
448  }
449  else
450  {
451  auto [_head, _tail] = tuple_split<1>(std::forward<decltype(tail)>(tail));
452  auto tmp = std::forward<decltype(config)>(config).push_back(
453  std::get<0>(std::forward<decltype(head)>(head)));
454  return impl_ref(impl_ref, std::move(tmp), std::move(_head), std::move(_tail));
455  }
456  };
457  auto [head, tail] = tuple_split<1>(std::forward<decltype(tpl)>(tpl));
458  return impl(impl, configuration<>{}, std::move(head), std::move(tail));
459  };
460  return make_config(std::forward<tuple_t>(tpl));
461  }
462 
489  template <detail::ConfigElement config_element_t>
490  constexpr auto push_back(config_element_t elem) const &
491  {
492  static_assert(detail::is_configuration_valid_v<remove_cvref_t<config_element_t>,
493  configs_t...>,
494  "Configuration error: The passed element cannot be combined with one or more elements in the "
495  "current configuration.");
496 
498  std::tuple_cat(static_cast<base_type>(*this),
499  std::tuple{std::move(elem)})};
500  }
501 
503  template <detail::ConfigElement config_element_t>
504  constexpr auto push_back(config_element_t elem) &&
505  {
506  static_assert(detail::is_configuration_valid_v<remove_cvref_t<config_element_t>,
507  configs_t...>,
508  "Configuration error: The passed element cannot be combined with one or more elements in the "
509  "current configuration.");
510 
512  std::tuple_cat(std::move(static_cast<base_type>(*this)),
513  std::tuple{std::move(elem)})};
514  }
516 };
517 
525 template <typename derived_t, typename value_t>
526 configuration(pipeable_config_element<derived_t, value_t> &&) -> configuration<remove_cvref_t<derived_t>>;
527 
531 template <typename derived_t, typename value_t>
532 configuration(pipeable_config_element<derived_t, value_t> const &) -> configuration<remove_cvref_t<derived_t>>;
534 
566 template <template <typename ...> class query_t, typename ...configs_t>
567 constexpr auto & get(configuration<configs_t...> & config) noexcept
568 {
569  using _tail = meta::find_if<type_list<configs_t...>, detail::is_same_configuration_f<query_t>>;
570  static_assert(!meta::empty<_tail>::value, "Access error: The requested type is not contained.");
571 
572  constexpr size_t pos = sizeof...(configs_t) - meta::size<_tail>::value;
573  return get<pos>(config);
574 }
575 
577 template <template <typename ...> class query_t, typename ...configs_t>
578 constexpr auto const & get(configuration<configs_t...> const & config) noexcept
579 {
580  using _tail = meta::find_if<type_list<configs_t...>, detail::is_same_configuration_f<query_t>>;
581  static_assert(!meta::empty<_tail>::value, "Access error: The requested type is not contained.");
582 
583  constexpr size_t pos = sizeof...(configs_t) - meta::size<_tail>::value;
584  return get<pos>(config);
585 }
586 
588 template <template <typename ...> class query_t, typename ...configs_t>
589 constexpr auto && get(configuration<configs_t...> && config) noexcept
590 {
591  using _tail = meta::find_if<type_list<configs_t...>, detail::is_same_configuration_f<query_t>>;
592  static_assert(!meta::empty<_tail>::value, "Access error: The requested type is not contained.");
593 
594  constexpr size_t pos = sizeof...(configs_t) - meta::size<_tail>::value;
595  return get<pos>(std::move(config));
596 }
597 
599 template <template <typename ...> class query_t, typename ...configs_t>
600 constexpr auto const && get(configuration<configs_t...> const && config) noexcept
601 {
602  using _tail = meta::find_if<type_list<configs_t...>, detail::is_same_configuration_f<query_t>>;
603  static_assert(!meta::empty<_tail>::value, "Access error: The requested type is not contained.");
604 
605  constexpr size_t pos = sizeof...(configs_t) - meta::size<_tail>::value;
606  // TODO: change after GCC-7 bug with const && version of get in std::tuple is fixed.
607  // return get<pos>(std::move(config));
608  return std::move(get<pos>(config));
609 }
611 
612 } // namespace seqan3::detail
613 
614 namespace std
615 {
617 
623 template <seqan3::detail::ConfigElement ... configs_t>
624 struct tuple_size<seqan3::configuration<configs_t...>>
625 {
627  static constexpr size_t value = std::tuple_size_v<typename seqan3::configuration<configs_t...>::base_type>;
628 };
629 
635 template <size_t pos, seqan3::detail::ConfigElement ... configs_t>
636 struct tuple_element<pos, seqan3::configuration<configs_t...>>
637 {
639  using type = std::tuple_element_t<pos, typename seqan3::configuration<configs_t...>::base_type>;
640 };
642 } //namespace std
Provides concepts for the configuration classes.
friend constexpr 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.
friend constexpr auto operator|(configuration &&lhs, configuration< rhs_configs_t... > &&rhs)
Combines two seqan3::configuration objects.
Definition: configuration.hpp:365
decltype(auto) constexpr value_or(default_t &&default_value) &noexcept
Returns the contained value if *this has a value, otherwise returns default_value.
Definition: configuration.hpp:157
Provides functionality to access get function by enum values.
typename remove_rvalue_reference< t >::type remove_rvalue_reference_t
Return the input type with && removed, but lvalue references preserved (TransformationTrait shortcut)...
Definition: basic.hpp:58
friend constexpr auto operator|(configuration const &lhs, pipeable_config_element< rhs_derived_t, rhs_value_t > &&rhs)
Definition: configuration.hpp:336
friend constexpr auto operator|(configuration const &lhs, configuration< rhs_configs_t... > const &rhs)
Definition: configuration.hpp:401
Provides seqan3::type_list and auxiliary type traits.
Adds pipe interface to configuration elements.
Definition: pipeable_config_element.hpp:30
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
friend constexpr auto operator|(configuration &&lhs, pipeable_config_element< rhs_derived_t, rhs_value_t > const &rhs)
Definition: configuration.hpp:344
static constexpr bool exists() noexcept
Checks if the given type exists in the tuple.
Definition: configuration.hpp:277
SeqAn specific customisations in the standard namespace.
constexpr configuration(pipeable_config_element< derived_t, value_t > const &elem)
Constructs a configuration from a single configuration element.
Definition: configuration.hpp:115
The main SeqAn3 namespace.
constexpr size_t size() const noexcept
Returns the number of contained config elements.
Definition: configuration.hpp:125
friend constexpr auto operator|(configuration const &lhs, configuration< rhs_configs_t... > &&rhs)
Definition: configuration.hpp:377
Provides seqan3::type_list and auxiliary type traits.
The Concepts library.
constexpr configuration & operator=(configuration const &)=default
Defaulted.
Provides seqan3::pipeable_config_element.
friend constexpr auto operator|(configuration &&lhs, configuration< rhs_configs_t... > const &rhs)
Definition: configuration.hpp:389
Provides utility functions for tuple like interfaces.
friend constexpr auto operator|(configuration const &lhs, pipeable_config_element< rhs_derived_t, rhs_value_t > const &rhs)
Definition: configuration.hpp:352
~configuration()=default
Defaulted.
T tuple_size_v
friend constexpr 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:328
T tuple_cat(T... args)
constexpr configuration()=default
Defaulted.
Provides various type traits on generic types.
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:889
meta::list< types... > type_list
Type that contains multiple types, an alias for meta::list.
Definition: type_list.hpp:27
::ranges::empty empty
Alias for ranges::empty. Checks whether a range is empty.
Definition: ranges:194
Collection of elements to configure an algorithm.
Definition: configuration.hpp:82
T forward(T... args)
constexpr configuration(pipeable_config_element< derived_t, value_t > &&elem)
Constructs a configuration from a single configuration element.
Definition: configuration.hpp:107