SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
record.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 
18 
19 namespace seqan3
20 {
21 
22 // ----------------------------------------------------------------------------
23 // enum field
24 // ----------------------------------------------------------------------------
25 
61 enum class field
62 {
63  // Fields used in multiple contexts ........................................
64  seq,
65  id,
66  qual,
67  seq_qual,
68  offset,
69 
70  // Fields unique to structure io ...........................................
71  bpp,
72  structure,
74  energy,
75  react,
76  react_err,
77  comment,
78 
79  // Fields unique to alignment io ...........................................
80  alignment,
81  ref_id,
82  ref_seq,
83  ref_offset,
84  header_ptr,
85 
86  flag,
87  mate,
88  mapq,
89  cigar,
90  tags,
91 
92  bit_score,
93  evalue,
94 
95  // User defined field aliases .. ...........................................
106 
107  // deprecated uppercase:
142 };
143 
144 // ----------------------------------------------------------------------------
145 // fields
146 // ----------------------------------------------------------------------------
147 
161 template <field ...fs>
162 struct fields
163 {
166  static constexpr std::array<field, sizeof...(fs)> as_array{fs...};
167 
169  static constexpr size_t npos = std::numeric_limits<size_t>::max();
170 
172  static constexpr size_t index_of(field f)
173  {
174  for (size_t i = 0; i < sizeof...(fs); ++i)
175  if (as_array[i] == f)
176  return i;
177  return npos;
178  }
179 
181  static constexpr bool contains(field f)
182  {
183  return index_of(f) != npos;
184  }
185 
186  static_assert([] () constexpr
187  {
188  for (size_t i = 0; i < as_array.size(); ++i)
189  for (size_t j = i + 1; j < as_array.size(); ++j)
190  if (as_array[i] == as_array[j])
191  return false;
192 
193  return true;
194  } (), "You may not include a field twice into fields<>.");
195 };
196 
197 // ----------------------------------------------------------------------------
198 // record
199 // ----------------------------------------------------------------------------
200 
221 template <typename field_types, typename field_ids>
222 struct record : detail::transfer_template_args_onto_t<field_types, std::tuple>
223 {
224 private:
226  template <typename t>
228  requires requires (t & v) { v.clear(); }
230  static constexpr void clear_element(t & v) noexcept(noexcept(v.clear()))
231  {
232  v.clear();
233  }
234 
236  template <typename t>
237  static constexpr void clear_element(t & v) noexcept(noexcept(std::declval<t &>() = t{}))
238  {
239  v = {};
240  }
241 
243  static constexpr auto expander = [] (auto & ...args) { (clear_element(args), ...); };
244 
245 public:
248 
252  record() = default;
253  record(record const &) = default;
254  record & operator=(record const &) = default;
255  record(record &&) = default;
256  record & operator=(record &&) = default;
257  ~record() = default;
258 
260  using base_type::base_type;
262 
263  static_assert(field_types::size() == field_ids::as_array.size(),
264  "You must give as many IDs as types to seqan3::record.");
265 
267  void clear() noexcept(noexcept(std::apply(expander, std::declval<record &>())))
268  {
269  std::apply(expander, *this);
270  }
271 
272 protected:
274 
276  template <field f>
278 
280  template <field f, typename tuple_t>
281  static decltype(auto) get_impl(field_constant<f>, tuple_t && record_as_tuple)
282  {
283  static_assert(field_ids::contains(f), "The record does not contain the field you wish to retrieve.");
284 #if SEQAN3_WORKAROUND_GCC_94967
285  // is_rvalue_reference_v can't be used, because tuple_t won't contain `&&` in the type due to reference
286  // collapsing
287  if constexpr (!std::is_lvalue_reference_v<tuple_t> && std::is_const_v<tuple_t>)
288  {
289  // A simple std::move(...) does not work, because it would mess up tuple_element types like `int const &`
290  using return_t = std::tuple_element_t<field_ids::index_of(f), tuple_t>;
291  return static_cast<return_t const &&>(std::get<field_ids::index_of(f)>(std::move(record_as_tuple)));
292  }
293  else
294  {
295  return std::get<field_ids::index_of(f)>(std::forward<tuple_t>(record_as_tuple));
296  }
297 #else // ^^^ workaround / no workaround vvv
298  return std::get<field_ids::index_of(f)>(std::forward<tuple_t>(record_as_tuple));
299 #endif // SEQAN3_WORKAROUND_GCC_94967
300  }
301 };
302 
303 } // namespace seqan3
304 
305 namespace std
306 {
307 
313 template <typename field_types, typename field_ids>
314 struct tuple_size<seqan3::record<field_types, field_ids>>
315  : tuple_size<typename seqan3::record<field_types, field_ids>::base_type>
316 {};
317 
323 template <size_t elem_no, typename field_types, typename field_ids>
324 struct tuple_element<elem_no, seqan3::record<field_types, field_ids>>
325  : tuple_element<elem_no, typename seqan3::record<field_types, field_ids>::base_type>
326 {};
327 
328 } // namespace std
329 
330 namespace seqan3
331 {
332 
340 template <field f, typename field_types, typename field_ids>
342 {
343  static_assert(field_ids::contains(f), "The record does not contain the field you wish to retrieve.");
344  return std::get<field_ids::index_of(f)>(r);
345 }
346 
348 template <field f, typename field_types, typename field_ids>
349 auto const & get(record<field_types, field_ids> const & r)
350 {
351  static_assert(field_ids::contains(f), "The record does not contain the field you wish to retrieve.");
352  return std::get<field_ids::index_of(f)>(r);
353 }
354 
356 template <field f, typename field_types, typename field_ids>
358 {
359  static_assert(field_ids::contains(f), "The record does not contain the field you wish to retrieve.");
360  return std::get<field_ids::index_of(f)>(std::move(r));
361 }
362 
364 template <field f, typename field_types, typename field_ids>
365 auto const && get(record<field_types, field_ids> const && r)
366 {
367  static_assert(field_ids::contains(f), "The record does not contain the field you wish to retrieve.");
368 #if SEQAN3_WORKAROUND_GCC_94967
369  // A simple std::move(...) does not work, because it would mess up tuple_element types like `int const &`
370  using return_t = std::tuple_element_t<field_ids::index_of(f), record<field_types, field_ids>>;
371  return static_cast<return_t const &&>(std::get<field_ids::index_of(f)>(std::move(r)));
372 #else // ^^^ workaround / no workaround vvv
373  return std::get<field_ids::index_of(f)>(std::move(r));
374 #endif // SEQAN3_WORKAROUND_GCC_94967
375 }
377 
378 } // namespace seqan3
T apply(T... args)
Provides type traits for working with templates.
typename transfer_template_args_onto< source_type, target_template >::type transfer_template_args_onto_t
Shortcut for seqan3::detail::transfer_template_args_onto (transformation_trait shortcut).
Definition: template_inspection.hpp:77
field
An enumerator for the fields used in file formats.
Definition: record.hpp:62
@ energy
Energy of a folded sequence, represented by one float number.
@ comment
Comment field of arbitrary content, usually a string.
@ CIGAR
Please use the field name in lower case.
@ structure
Fixed interactions, usually a string of structure alphabet characters.
@ bpp
Base pair probability matrix of interactions, usually a matrix of float numbers.
@ FLAG
Please use the field name in lower case.
@ REF_SEQ
Please use the field name in lower case.
@ OFFSET
Please use the field name in lower case.
@ react
Reactivity values of the sequence characters given in a vector of float numbers.
@ flag
The alignment flag (bit information), uint16_t value.
@ USER_DEFINED_6
Please use the field name in lower case.
@ TAGS
Please use the field name in lower case.
@ react_err
Reactivity error values given in a vector corresponding to seqan3::field::react.
@ QUAL
Please use the field name in lower case.
@ USER_DEFINED_8
Please use the field name in lower case.
@ MATE
Please use the field name in lower case.
@ ref_offset
Sequence (seqan3::field::ref_seq) relative start position (0-based), unsigned value.
@ ref_seq
The (reference) "sequence" information, usually a range of nucleotides or amino acids.
@ SEQ
Please use the field name in lower case.
@ alignment
The (pairwise) alignment stored in an object that models seqan3::detail::pairwise_alignment.
@ cigar
The cigar vector (std::vector<seqan3::cigar>) representing the alignment in SAM/BAM format.
@ mapq
The mapping quality of the seqan3::field::seq alignment, usually a Phred-scaled score.
@ user_defined_2
Identifier for user defined file formats and specialisations.
@ user_defined_5
Identifier for user defined file formats and specialisations.
@ STRUCTURE
Please use the field name in lower case.
@ USER_DEFINED_2
Please use the field name in lower case.
@ REACT_ERR
Please use the field name in lower case.
@ bit_score
The bit score (statistical significance indicator), unsigned value.
@ user_defined_0
Identifier for user defined file formats and specialisations.
@ user_defined_8
Identifier for user defined file formats and specialisations.
@ STRUCTURED_SEQ
Please use the field name in lower case.
@ user_defined_3
Identifier for user defined file formats and specialisations.
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
@ MAPQ
Please use the field name in lower case.
@ mate
The mate pair information given as a std::tuple of reference name, offset and template length.
@ SEQ_QUAL
Please use the field name in lower case.
@ header_ptr
A pointer to the seqan3::sam_file_header object storing header information.
@ user_defined_7
Identifier for user defined file formats and specialisations.
@ user_defined_4
Identifier for user defined file formats and specialisations.
@ ENERGY
Please use the field name in lower case.
@ ref_id
The identifier of the (reference) sequence that seqan3::field::seq was aligned to.
@ BIT_SCORE
Please use the field name in lower case.
@ REACT
Please use the field name in lower case.
@ structured_seq
Sequence and fixed interactions combined in one range.
@ ALIGNMENT
Please use the field name in lower case.
@ HEADER_PTR
Please use the field name in lower case.
@ evalue
The e-value (length normalized bit score), double value.
@ ID
Please use the field name in lower case.
@ id
The identifier, usually a string.
@ USER_DEFINED_1
Please use the field name in lower case.
@ REF_OFFSET
Please use the field name in lower case.
@ user_defined_6
Identifier for user defined file formats and specialisations.
@ USER_DEFINED_3
Please use the field name in lower case.
@ seq_qual
Sequence and qualities combined in one range.
@ tags
The optional tags in the SAM format, stored in a dictionary.
@ user_defined_1
Identifier for user defined file formats and specialisations.
@ user_defined_9
Identifier for user defined file formats and specialisations.
@ seq
The "sequence", usually a range of nucleotides or amino acids.
@ USER_DEFINED_9
Please use the field name in lower case.
@ USER_DEFINED_5
Please use the field name in lower case.
@ USER_DEFINED_7
Please use the field name in lower case.
@ qual
The qualities, usually in Phred score notation.
@ BPP
Please use the field name in lower case.
@ COMMENT
Please use the field name in lower case.
@ EVALUE
Please use the field name in lower case.
@ REF_ID
Please use the field name in lower case.
@ USER_DEFINED_4
Please use the field name in lower case.
@ USER_DEFINED_0
Please use the field name in lower case.
constexpr bool contains
Whether a type occurs in a type list or not.
Definition: traits.hpp:194
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:150
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:70
Subconcept definition for seqan3::tuple_like to test for std::tuple_size-interface.
T max(T... args)
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
SeqAn specific customisations in the standard namespace.
#define SEQAN3_DEPRECATED_310
Deprecation message for SeqAn 3.1.0 release.
Definition: platform.hpp:202
T size(T... args)
A class template that holds a choice of seqan3::field.
Definition: record.hpp:163
static constexpr std::array< field, sizeof...(fs)> as_array
The template parameters stored in an array for easy access.
Definition: record.hpp:166
static constexpr bool contains(field f)
Whether a field is contained in the parameter pack.
Definition: record.hpp:181
static constexpr size_t npos
Special value that indicates that index_of() failed.
Definition: record.hpp:169
static constexpr size_t index_of(field f)
Retrieve the position of field in the parameter pack.
Definition: record.hpp:172
The class template that file records are based on; behaves like an std::tuple.
Definition: record.hpp:223
auto & get(record< field_types, field_ids > &r)
Free function get() for seqan3::record based on seqan3::field.
Definition: record.hpp:341
auto && get(record< field_types, field_ids > &&r)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: record.hpp:357
record(record &&)=default
Defaulted.
record & operator=(record &&)=default
Defaulted.
static decltype(auto) get_impl(field_constant< f >, tuple_t &&record_as_tuple)
This is basically the seqan3::get<f>(static_cast<tuple>(record)) implementation.
Definition: record.hpp:281
static constexpr auto expander
A lambda function that expands a pack and calls clear_element on every argument in the pack.
Definition: record.hpp:243
void clear() noexcept(noexcept(std::apply(expander, std::declval< record & >())))
Clears containers that provide .clear() and (re-)initialises all other elements with = {}.
Definition: record.hpp:267
~record()=default
Defaulted.
detail::transfer_template_args_onto_t< field_types, std::tuple > base_type
A specialisation of std::tuple.
Definition: record.hpp:247
auto const & get(record< field_types, field_ids > const &r)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: record.hpp:349
record & operator=(record const &)=default
Defaulted.
record()=default
Defaulted.
auto const && get(record< field_types, field_ids > const &&r)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: record.hpp:365
static constexpr void clear_element(t &v) noexcept(noexcept(std::declval< t & >()=t{}))
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: record.hpp:237
static constexpr void clear_element(t &v) noexcept(noexcept(v.clear()))
Auxiliary functions for clear().
Definition: record.hpp:230
record(record const &)=default
Defaulted.