SeqAn3
record.hpp
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
42 #pragma once
43 
44 #include <range/v3/view/repeat.hpp>
45 
47 #include <seqan3/io/record.hpp>
48 #include <seqan3/std/ranges>
49 
50 namespace seqan3::detail
51 {
52 
53 // ----------------------------------------------------------------------------
54 // fields_concept
55 // ----------------------------------------------------------------------------
56 
61 template <typename t>
62 concept fields_concept = is_value_specialisation_of_v<t, fields>;
63 
64 // ----------------------------------------------------------------------------
65 // select_types_with_ids
66 // ----------------------------------------------------------------------------
67 
94 template <typename field_types,
95  typename field_types_as_ids,
96  typename selected_field_ids,
97  size_t field_no = 0,
98  typename ... return_types>
99 struct select_types_with_ids // unconstrained template is recursion anchor
100 {
102  using type = type_list<return_types...>;
103 };
104 
109 template <typename field_types,
110  typename field_types_as_ids,
111  typename selected_field_ids,
112  size_t field_no = 0,
113  typename ... return_types>
114 using select_types_with_ids_t = typename select_types_with_ids<field_types,
115  field_types_as_ids,
116  selected_field_ids,
117  field_no,
118  return_types...>::type;
120 template <typename field_types,
121  typename field_types_as_ids,
122  typename selected_field_ids,
123  size_t field_no,
124  typename ... return_types>
125  requires field_no < selected_field_ids::as_array.size() // perform recursion while not at end
126 struct select_types_with_ids<field_types, field_types_as_ids, selected_field_ids, field_no, return_types...>
127 {
128  static_assert(field_types_as_ids::contains(selected_field_ids::as_array[field_no]),
129  "You selected a field that was not in field_types_as_ids.");
130 
131  // call this metafunction again, but increase index by one and append a type to the returned type list.
132  using type = select_types_with_ids_t<field_types,
133  field_types_as_ids,
134  selected_field_ids,
135  field_no + 1,
136  return_types ...,
137  meta::at_c<field_types,
138  field_types_as_ids::index_of(selected_field_ids::as_array[field_no])>>;
139 
140 };
142 
143 
144 // ----------------------------------------------------------------------------
145 // get_or_ignore
146 // ----------------------------------------------------------------------------
147 
151 template <field f, typename field_types, typename field_ids>
153 auto & get_or_ignore(record<field_types, field_ids> & r)
154 {
155  if constexpr (field_ids::contains(f))
156  return std::get<field_ids::index_of(f)>(r);
157  else
158  return std::ignore;
159 }
160 
162 template <field f, typename field_types, typename field_ids>
163 auto const & get_or_ignore(record<field_types, field_ids> const & r)
164 {
165  if constexpr (field_ids::contains(f))
166  return std::get<field_ids::index_of(f)>(r);
167  else
168  return std::ignore;
169 }
170 
172 template <size_t i, typename ... types>
173 auto & get_or_ignore(std::tuple<types...> & t)
174 {
175  if constexpr (i < sizeof...(types))
176  return std::get<i>(t);
177  else
178  return std::ignore;
179 }
180 
182 template <size_t i, typename ... types>
183 auto const & get_or_ignore(std::tuple<types...> const & t)
184 {
185  if constexpr (i < sizeof...(types))
186  return std::get<i>(t);
187  else
188  return std::ignore;
189 }
191 
192 
193 // ----------------------------------------------------------------------------
194 // get_or
195 // ----------------------------------------------------------------------------
196 
200 template <field f, typename field_types, typename field_ids, typename or_type>
202 decltype(auto) get_or(record<field_types, field_ids> & r, or_type && or_value)
203 {
204  if constexpr (field_ids::contains(f))
205  return std::get<field_ids::index_of(f)>(r);
206  else
207  return std::forward<or_type>(or_value);
208 }
209 
211 template <field f, typename field_types, typename field_ids, typename or_type>
212 decltype(auto) get_or(record<field_types, field_ids> const & r, or_type && or_value)
213 {
214  if constexpr (field_ids::contains(f))
215  return std::get<field_ids::index_of(f)>(r);
216  else
217  return std::forward<or_type>(or_value);
218 }
219 
221 template <size_t i, typename or_type, typename ... types>
222 decltype(auto) get_or(std::tuple<types...> & t, or_type && or_value)
223 {
224  if constexpr (i < sizeof...(types))
225  return std::get<i>(t);
226  else
227  return std::forward<or_type>(or_value);
228 }
229 
231 template <size_t i, typename or_type, typename ... types>
232 decltype(auto) get_or(std::tuple<types...> const & t, or_type && or_value)
233 {
234  if constexpr (i < sizeof...(types))
235  return std::get<i>(t);
236  else
237  return std::forward<or_type>(or_value);
238 }
240 
241 // ----------------------------------------------------------------------------
242 // range_wrap_ignore
243 // ----------------------------------------------------------------------------
244 
246 template <std::ranges::InputRange rng_t>
247 inline auto & range_wrap_ignore(rng_t & range)
248 {
249  return range;
250 }
251 
258 inline auto range_wrap_ignore(ignore_t const &)
259 {
260  return ranges::view::repeat(std::ignore);
261 }
262 
263 } // namespace seqan3::detail
The class template that file records are based on; behaves like an std::tuple.
Definition: record.hpp:208
Provides the seqan3::record template and the seqan3::field enum.
Adaptations of concepts from the Ranges TS.
Definition: aligned_sequence_concept.hpp:288
Provides various metafunctions on generic types.
meta::list< types... > type_list
Type that contains multiple types, an alias for meta::list.
Definition: type_list.hpp:54