SeqAn3  3.1.0-rc.1
The Modern C++ library for sequence analysis.
record.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 
15 #pragma once
16 
17 #include <seqan3/std/ranges>
18 
19 #include <seqan3/io/record.hpp>
23 
24 namespace seqan3::detail
25 {
26 
27 // ----------------------------------------------------------------------------
28 // Fields
29 // ----------------------------------------------------------------------------
30 
34 template <typename t>
35 SEQAN3_CONCEPT fields_specialisation = is_value_specialisation_of_v<t, fields>;
36 
37 // ----------------------------------------------------------------------------
38 // select_types_with_ids
39 // ----------------------------------------------------------------------------
40 
61 template <typename field_types,
62  typename field_types_as_ids,
63  typename selected_field_ids,
64  size_t field_no = 0,
65  typename ...return_types>
66 struct select_types_with_ids // unconstrained template is recursion anchor
67 {
69  using type = type_list<return_types...>;
70 };
71 
75 template <typename field_types,
76  typename field_types_as_ids,
77  typename selected_field_ids,
78  size_t field_no = 0,
79  typename ...return_types>
80 using select_types_with_ids_t = typename select_types_with_ids<field_types,
81  field_types_as_ids,
82  selected_field_ids,
83  field_no,
84  return_types...>::type;
86 template <typename field_types,
87  typename field_types_as_ids,
88  typename selected_field_ids,
89  size_t field_no,
90  typename ...return_types>
91  requires (field_no < selected_field_ids::as_array.size()) // perform recursion while not at end
92 struct select_types_with_ids<field_types, field_types_as_ids, selected_field_ids, field_no, return_types...>
93 {
94  static_assert(field_types_as_ids::contains(selected_field_ids::as_array[field_no]),
95  "You selected a field that was not in field_types_as_ids.");
96 
97  // call this type trait again, but increase index by one and append a type to the returned type list.
98  using type = select_types_with_ids_t<field_types,
99  field_types_as_ids,
100  selected_field_ids,
101  field_no + 1,
102  return_types ...,
103  list_traits::at<field_types_as_ids::index_of(
104  selected_field_ids::as_array[field_no]), field_types>>;
105 
106 };
108 
109 
110 // ----------------------------------------------------------------------------
111 // get_or_ignore
112 // ----------------------------------------------------------------------------
113 
116 template <field f, typename field_types, typename field_ids>
118 {
119  if constexpr (field_ids::contains(f))
120  return std::get<field_ids::index_of(f)>(r);
121  else
122  return std::ignore;
123 }
124 
126 template <field f, typename field_types, typename field_ids>
128 {
129  if constexpr (field_ids::contains(f))
130  return std::get<field_ids::index_of(f)>(r);
131  else
132  return std::ignore;
133 }
134 
136 template <size_t i, tuple_like tuple_t>
137 auto & get_or_ignore(tuple_t & t)
138 {
139  if constexpr (i < std::tuple_size_v<tuple_t>)
140  return std::get<i>(t);
141  else
142  return std::ignore;
143 }
144 
146 template <size_t i, tuple_like tuple_t>
147 auto const & get_or_ignore(tuple_t const & t)
148 {
149  if constexpr (i < std::tuple_size_v<tuple_t>)
150  return std::get<i>(t);
151  else
152  return std::ignore;
153 }
154 
155 // ----------------------------------------------------------------------------
156 // get_or
157 // ----------------------------------------------------------------------------
158 
161 template <field f, typename field_types, typename field_ids, typename or_type>
162 decltype(auto) get_or(record<field_types, field_ids> & r, or_type && or_value)
163 {
164  if constexpr (field_ids::contains(f))
165  return std::get<field_ids::index_of(f)>(r);
166  else
167  return std::forward<or_type>(or_value);
168 }
169 
171 template <field f, typename field_types, typename field_ids, typename or_type>
172 decltype(auto) get_or(record<field_types, field_ids> const & r, or_type && or_value)
173 {
174  if constexpr (field_ids::contains(f))
175  return std::get<field_ids::index_of(f)>(r);
176  else
177  return std::forward<or_type>(or_value);
178 }
179 
181 template <size_t i, typename or_type, typename ...types>
182 decltype(auto) get_or(std::tuple<types...> & t, or_type && or_value)
183 {
184  if constexpr (i < sizeof...(types))
185  return std::get<i>(t);
186  else
187  return std::forward<or_type>(or_value);
188 }
189 
191 template <size_t i, typename or_type, typename ...types>
192 decltype(auto) get_or(std::tuple<types...> const & t, or_type && or_value)
193 {
194  if constexpr (i < sizeof...(types))
195  return std::get<i>(t);
196  else
197  return std::forward<or_type>(or_value);
198 }
199 
200 // ----------------------------------------------------------------------------
201 // range_wrap_ignore
202 // ----------------------------------------------------------------------------
203 
206 template <std::ranges::input_range rng_t>
207 inline auto & range_wrap_ignore(rng_t & range)
208 {
209  return range;
210 }
211 
219 inline auto range_wrap_ignore(ignore_t const &)
220 {
221  return views::repeat(std::ignore);
222 }
223 
224 } // namespace seqan3::detail
auto & range_wrap_ignore(rng_t &range)
Pass through the reference to the argument in case the argument satisfies std::ranges::input_range.
Definition: record.hpp:207
decltype(auto) get_or(record< field_types, field_ids > &r, or_type &&or_value)
Access an element in a std::tuple or seqan3::record; return or_value if not contained.
Definition: record.hpp:162
SEQAN3_CONCEPT fields_specialisation
Auxiliary concept that checks whether a type is a specialisation of seqan3::fields.
Definition: record.hpp:35
auto & get_or_ignore(record< field_types, field_ids > &r)
Access an element in a std::tuple or seqan3::record; return reference to std::ignore if not contained...
Definition: record.hpp:117
constexpr bool contains
Whether a type occurs in a type list or not.
Definition: traits.hpp:231
typename decltype(detail::at< idx >(list_t{}))::type at
Return the type at given index from the type list.
Definition: traits.hpp:260
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
constexpr detail::repeat_fn repeat
A view factory that repeats a given value infinitely.
Definition: repeat.hpp:347
The internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
SeqAn specific customisations in the standard namespace.
Adaptations of concepts from the Ranges TS.
Provides the seqan3::record template and the seqan3::field enum.
Provides the seqan3::views::repeat.
Exposes a subset of types as a seqan3::type_list selected based on their IDs.
Definition: record.hpp:67
typename select_types_with_ids< field_types, field_types_as_ids, selected_field_ids, field_no, return_types... >::type select_types_with_ids_t
Shortcut for seqan3::select_types_with_ids (transformation_trait shortcut).
Definition: record.hpp:84
The class template that file records are based on; behaves like an std::tuple.
Definition: record.hpp:191
Type that contains multiple types.
Definition: type_list.hpp:29
Provides traits for seqan3::type_list.
Provides seqan3::tuple_like.