SeqAn3 3.2.0
The Modern C++ library for sequence analysis.
slice.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2022, 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 <concepts>
16#include <iterator>
17#include <ranges>
18#include <span>
19#include <stdexcept>
20#include <type_traits>
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> && std::ranges::contiguous_range<urng_t>
80 && std::ranges::sized_range<urng_t>)
81 {
82 return std::span{std::ranges::data(urange) + begin_pos, static_cast<size_t>(target_size)};
83 }
84 // random_access
85 else if constexpr (std::ranges::borrowed_range<urng_t> && std::ranges::random_access_range<urng_t>
86 && std::ranges::sized_range<urng_t>)
87 {
88 return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>{
89 std::ranges::begin(urange) + begin_pos,
90 std::ranges::begin(urange) + end_pos,
91 static_cast<size_t>(target_size)};
92 }
93 // std::views::drop
94 else
95 {
96 // urange | drop | take
97 return std::views::take(std::views::drop(std::forward<urng_t>(urange), begin_pos), target_size);
98 }
99#else /*^^^ workaround / no workaround vvv*/
100 // urange | type_reduce | drop | take
101 return std::views::take(std::views::drop(seqan3::views::type_reduce(std::forward<urng_t>(urange)), begin_pos),
102 target_size);
103#endif // SEQAN3_WORKAROUND_GCC_100139
104 }
105};
106
107} // namespace seqan3::detail
108
109// ============================================================================
110// views::slice (adaptor instance definition)
111// ============================================================================
112
113namespace seqan3::views
114{
178inline constexpr auto slice = detail::slice_fn{};
179
180} // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
T begin(T... args)
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:377
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:395
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:146
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:178
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:150
Provides exceptions used in the I/O module.
T min(T... args)
The SeqAn namespace for views.
Definition: char_strictly_to.hpp:22
Provides seqan3::views::type_reduce.