SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
slice.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
13#pragma once
14
15#include <seqan3/std/concepts>
16#include <seqan3/std/iterator>
17#include <seqan3/std/ranges>
18#include <seqan3/std/span>
19#include <stdexcept>
21
25
26namespace seqan3::detail
27{
28
29// ============================================================================
30// slice_fn (adaptor definition)
31// ============================================================================
32
34struct slice_fn
35{
37 constexpr auto operator()(ptrdiff_t begin_pos, ptrdiff_t end_pos) const noexcept
38 {
39 return detail::adaptor_from_functor{*this, begin_pos, end_pos};
40 }
41
45 template <std::ranges::viewable_range urng_t>
46 constexpr auto operator()(urng_t && urange,
47 std::ranges::range_difference_t<urng_t> begin_pos,
48 std::ranges::range_difference_t<urng_t> end_pos) const
49 {
50 using position_t = std::ranges::range_difference_t<urng_t>;
51 if constexpr (std::ranges::sized_range<urng_t>)
52 {
53 position_t urange_size = static_cast<position_t>(std::ranges::size(urange));
54
55 begin_pos = std::min(begin_pos, urange_size);
56 end_pos = std::min(end_pos, urange_size);
57 }
58 position_t target_size = end_pos - begin_pos;
59
60 if (end_pos < begin_pos)
61 throw std::invalid_argument{"end_pos argument to seqan3::views::slice must be >= the begin_pos argument."};
62
63 // SEQAN3_WORKAROUND_GCC_100139 == 1 if std::views::{take, drop} does not type reduce (e.g. keep in type
64 // std::basic_string_view, std::span, std::ranges::subrange).
65 // See https://github.com/seqan/seqan3/pull/2540/files#r617575294
66#if SEQAN3_WORKAROUND_GCC_100139
67 // string_view
68 if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>, std::basic_string_view>)
69 {
70 return urange.substr(begin_pos, static_cast<size_t>(target_size));
71 }
72 // string const &
73 else if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>, std::basic_string> &&
74 std::is_const_v<std::remove_reference_t<urng_t>>)
75 {
76 return std::basic_string_view{std::ranges::data(urange) + begin_pos, static_cast<size_t>(target_size)};
77 }
78 // contiguous
79 else if constexpr (std::ranges::borrowed_range<urng_t> &&
80 std::ranges::contiguous_range<urng_t> &&
81 std::ranges::sized_range<urng_t>)
82 {
83 return std::span{std::ranges::data(urange) + begin_pos, static_cast<size_t>(target_size)};
84 }
85 // random_access
86 else if constexpr (std::ranges::borrowed_range<urng_t> &&
87 std::ranges::random_access_range<urng_t> &&
88 std::ranges::sized_range<urng_t>)
89 {
90 return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>
91 {
92 std::ranges::begin(urange) + begin_pos,
93 std::ranges::begin(urange) + end_pos,
94 static_cast<size_t>(target_size)
95 };
96 }
97 // std::views::drop
98 else
99 {
100 // urange | drop | take
101 return std::views::take(std::views::drop(std::forward<urng_t>(urange), begin_pos), target_size);
102 }
103#else // ^^^ workaround / no workaround vvv
104 // urange | type_reduce | drop | take
105 return std::views::take(std::views::drop(seqan3::views::type_reduce(std::forward<urng_t>(urange)),
106 begin_pos),
107 target_size);
108#endif // SEQAN3_WORKAROUND_GCC_100139
109 }
110};
111
112} // namespace seqan3::detail
113
114// ============================================================================
115// views::slice (adaptor instance definition)
116// ============================================================================
117
118namespace seqan3::views
119{
183inline constexpr auto slice = detail::slice_fn{};
184
185} // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
T begin(T... args)
The <concepts> header from C++20's standard library.
typename decltype(detail::split_after< i >(list_t{}))::first_type take
Return a seqan3::type_list of the first n types in the input type list.
Definition: traits.hpp:368
typename decltype(detail::split_after< i >(list_t{}))::second_type drop
Return a seqan3::type_list of the types in the input type list, except the first n.
Definition: traits.hpp:388
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:183
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:153
Provides exceptions used in the I/O module.
The <iterator> header from C++20's standard library.
T min(T... args)
The SeqAn namespace for views.
Definition: char_to.hpp:22
The <ranges> header from C++20's standard library.
Provides std::span from the C++20 standard library.
Provides seqan3::views::type_reduce.
The <type_traits> header from C++20's standard library.