Skip to content

Commit

Permalink
[FEATURE] seqan3::ranges::to
Browse files Browse the repository at this point in the history
  • Loading branch information
SGSSGene authored and eseiler committed Jun 7, 2022
1 parent 4490315 commit 53b2bcf
Show file tree
Hide file tree
Showing 33 changed files with 511 additions and 111 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ If possible, provide tooling that performs the changes, e.g. a shell-script.
entire program. Formerly, this variable was specific to each translation unit
([\#2752](https://github.com/seqan/seqan3/pull/2752)).

#### Range
* Replaced `seqan3::views::to` (implemented via range-v3) with `seqan3::ranges::to` (implemented in SeqAn3).
`seqan3::ranges::to` provides a subset of C++23's `std::ranges::to` and will be replaced with the STL-equivalent
in a future version ([\#2969](https://github.com/seqan/seqan3/pull/2969)).

# 3.1.0

## New features
Expand Down
7 changes: 5 additions & 2 deletions doc/tutorial/04_alphabet/alphabet_gc_content.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ int main(int argc, char * argv[])
sequence.push_back(seqan3::assign_char_to(c, seqan3::dna5{}));

// Optional: use views for the conversion. Views will be introduced in the next chapter.
//std::vector<seqan3::dna5> sequence = input | seqan3::views::char_to<seqan3::dna5> | seqan3::views::to<std::vector>;
// std::vector<seqan3::dna5> sequence = input
// | seqan3::views::char_to<seqan3::dna5>
// | seqan3::ranges::to<std::vector>();

// Initialise an array with count values for dna5 symbols.
std::array<size_t, seqan3::dna5::alphabet_size> count{}; // default initialised with zeroes
Expand All @@ -56,5 +58,6 @@ void alternatively()
{
std::string input{};
// if something changes in here, please update above:
std::vector<seqan3::dna5> sequence = input | seqan3::views::char_to<seqan3::dna5> | seqan3::views::to<std::vector>;
std::vector<seqan3::dna5> sequence =
input | seqan3::views::char_to<seqan3::dna5> | seqan3::ranges::to<std::vector>();
}
39 changes: 39 additions & 0 deletions doc/tutorial/05_ranges/to.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <deque>
#include <forward_list>
#include <list>
#include <vector>

#include <seqan3/utility/range/to.hpp>

int main()
{
auto lst = std::views::iota(1, 10); // some range over the numbers 1-10

// convert range to vector using pipe syntax
auto vec0 = lst | seqan3::ranges::to<std::vector<int>>();
static_assert(std::same_as<decltype(vec0), std::vector<int>>);

// convert range to vector but auto deducing the element type
auto vec1 = lst | seqan3::ranges::to<std::vector>();
static_assert(std::same_as<decltype(vec1), std::vector<int>>);

// convert range to vector using function call syntax
auto vec2 = seqan3::ranges::to<std::vector<int>>(lst);
static_assert(std::same_as<decltype(vec2), std::vector<int>>);

// using function call syntax and auto deducing element type
auto vec3 = seqan3::ranges::to<std::vector>(lst);
static_assert(std::same_as<decltype(vec3), std::vector<int>>);

// convert nested ranges into nested containers
auto nested_lst = std::list<std::forward_list<int>>{{1, 2, 3}, {4, 5, 6, 7}};
auto vec4 = nested_lst | seqan3::ranges::to<std::vector<std::vector<int>>>();
static_assert(std::same_as<decltype(vec4), std::vector<std::vector<int>>>);

// different supported container types
auto vec5 = lst | seqan3::ranges::to<std::list>();
static_assert(std::same_as<decltype(vec5), std::list<int>>);

auto vec6 = lst | seqan3::ranges::to<std::deque>();
static_assert(std::same_as<decltype(vec6), std::deque<int>>);
}
6 changes: 3 additions & 3 deletions include/seqan3/io/sam_file/format_sam.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
#include <seqan3/io/views/detail/istreambuf_view.hpp>
#include <seqan3/io/views/detail/take_until_view.hpp>
#include <seqan3/utility/detail/type_name_as_string.hpp>
#include <seqan3/utility/range/to.hpp>
#include <seqan3/utility/tuple/concept.hpp>
#include <seqan3/utility/views/slice.hpp>
#include <seqan3/utility/views/to.hpp>

namespace seqan3
{
Expand Down Expand Up @@ -323,7 +323,7 @@ inline void format_sam::read_sequence_record(stream_type & stream,
throw parse_error{"The id information must not be empty."};

if (options.truncate_ids)
id = id | detail::take_until_and_consume(is_space) | views::to<id_type>;
id = id | detail::take_until_and_consume(is_space) | ranges::to<id_type>();
}

//!\copydoc sequence_file_output_format::write_sequence_record
Expand Down Expand Up @@ -1063,7 +1063,7 @@ inline void format_sam::read_sam_dict_field(stream_view_type && stream_view, sam
}
case 'Z': // string
{
target[tag] = stream_view | views::to<std::string>;
target[tag] = stream_view | ranges::to<std::string>();
break;
}
case 'H':
Expand Down
4 changes: 2 additions & 2 deletions include/seqan3/io/structure_file/format_vienna.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#include <seqan3/io/views/detail/take_until_view.hpp>
#include <seqan3/utility/char_operations/predicate.hpp>
#include <seqan3/utility/detail/type_name_as_string.hpp>
#include <seqan3/utility/views/to.hpp>
#include <seqan3/utility/range/to.hpp>

namespace seqan3
{
Expand Down Expand Up @@ -241,7 +241,7 @@ class format_vienna
{
std::string e_str = stream_view | detail::take_line
| std::views::filter(!(is_space || is_char<'('> || is_char<')'>))
| views::to<std::string>;
| ranges::to<std::string>();
if (!e_str.empty())
{
size_t num_processed;
Expand Down
5 changes: 3 additions & 2 deletions include/seqan3/utility/container/dynamic_bitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
#include <seqan3/core/concept/cereal.hpp>
#include <seqan3/core/debug_stream/debug_stream_type.hpp>
#include <seqan3/utility/detail/integer_traits.hpp>
#include <seqan3/utility/range/to.hpp>
#include <seqan3/utility/views/interleave.hpp>
#include <seqan3/utility/views/repeat_n.hpp>
#include <seqan3/utility/views/to.hpp>

namespace seqan3
{
Expand Down Expand Up @@ -1947,7 +1947,8 @@ class dynamic_bitset
template <typename char_t>
friend debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & s, dynamic_bitset arg)
{
s << (std::string_view{arg.to_string()} | views::interleave(4, std::string_view{"'"}) | views::to<std::string>);
s << (std::string_view{arg.to_string()} | views::interleave(4, std::string_view{"'"})
| ranges::to<std::string>());
return s;
}
//!\}
Expand Down
1 change: 1 addition & 0 deletions include/seqan3/utility/range/all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,4 @@
#pragma once

#include <seqan3/utility/range/concept.hpp>
#include <seqan3/utility/range/to.hpp>
196 changes: 196 additions & 0 deletions include/seqan3/utility/range/to.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// -----------------------------------------------------------------------------------------------------
// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
// Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
// -----------------------------------------------------------------------------------------------------

/*!\file
* \author Simon Gene Gottlieb <simon.gottlieb AT fu-berlin.de>
* \brief Provides seqan3::ranges::to.
*/

#pragma once

#include <algorithm>
#include <seqan3/std/ranges>

#include <seqan3/core/range/detail/adaptor_from_functor.hpp>
#include <seqan3/utility/concept.hpp>

namespace seqan3::detail
{

//!\brief Function object to convert a std::ranges::input_range to a fully defined container.
template <typename container_t>
requires (!std::ranges::view<container_t>)
struct to_fn
{
private:
/*!\brief Copies a range into a container.
* \tparam rng_t Type of the range.
* \tparam container_t Type of the target container.
*/
template <std::ranges::input_range rng_t>
requires std::convertible_to<std::ranges::range_reference_t<rng_t>, std::ranges::range_value_t<container_t>>
auto impl(rng_t && rng, container_t & container) const
{
std::ranges::copy(rng, std::back_inserter(container));
}

//!\overload
template <std::ranges::input_range rng_t>
auto impl(rng_t && rng, container_t & container) const
requires std::ranges::input_range<std::ranges::range_value_t<rng_t>>
{
auto adaptor = to_fn<std::ranges::range_value_t<container_t>>{};
auto inner_rng = rng | std::views::transform(adaptor);
std::ranges::copy(inner_rng, std::back_inserter(container));
}

public:
/*!\brief Converts a template-template into a container.
* \tparam rng_t The type of the range being processed.
* \tparam args_t The types of the arguments for the constructor.
* \param rng The range being processed.
* \param args Arguments to pass to the constructor of the container.
*/
template <std::ranges::input_range rng_t, typename... args_t>
constexpr auto operator()(rng_t && rng, args_t &&... args) const
{
auto new_container = container_t(std::forward<args_t>(args)...);

// reserve memory if functionality is available
if constexpr (std::ranges::sized_range<rng_t> && requires (container_t c) { c.reserve(size_t{}); })
new_container.reserve(std::ranges::size(rng));

impl(std::forward<rng_t>(rng), new_container);
return new_container;
}
};

/*!\brief Similar to to_fn, but accepts a template-template as argument,
* e.g.: to_fn<vector> instead of to_fn<vector<int>>.
*/
template <template <typename> typename container_t>
struct to_template_template_fn
{
/*!\brief Converts a template-template into a container.
* \tparam rng_t The type of the range being processed.
* \tparam args_t The types of the arguments for the constructor.
* \param rng The range being processed.
* \param args Arguments to pass to the constructor of the container.
*/
template <std::ranges::input_range rng_t, typename... args_t>
constexpr auto operator()(rng_t && rng, args_t &&... args) const
{
auto adaptor = to_fn<container_t<std::ranges::range_value_t<rng_t>>>{};
return adaptor(std::forward<rng_t>(rng), std::forward<args_t>(args)...);
}
};

} // namespace seqan3::detail

namespace seqan3::ranges
{

/*!\brief Converts a range to a container.
* \ingroup utility_range
* \details
* To convert a range to a container, either the "pipe syntax" or the "function call" syntax can be used.
* Both syntaxes support the explicit specification of the target container or
* a specification with a deduced value type.
*
* Currently supported containers are:
* - `std::vector`
* - `std::list`
* - `std::deque`
*
* \include doc/tutorial/05_ranges/to.cpp
*
* \noapi{This is a implementation of the C++23 ranges::to. It will be replaced with std::ranges::to.}
*/
template <typename container_t, typename... args_t>
constexpr auto to(args_t &&... args)
{
return detail::adaptor_from_functor{detail::to_fn<container_t>{}, std::forward<args_t>(args)...};
}

/*!\brief Converts a range to a container.
* \ingroup utility_range
* \overload
*/
template <template <typename...> typename container_t, typename... args_t>
constexpr auto to(args_t &&... args)
{
return detail::adaptor_from_functor{detail::to_template_template_fn<container_t>{}, std::forward<args_t>(args)...};
}

/*!\brief Converts a range to a container.
* \ingroup utility_range
* \overload
*/
template <typename container_t, std::ranges::input_range rng_t, typename... args_t>
constexpr auto to(rng_t && rng, args_t &&... args)
{
return detail::adaptor_from_functor{detail::to_fn<container_t>{},
std::forward<args_t>(args)...}(std::forward<rng_t>(rng));
}

/*!\brief Converts a range to a container.
* \ingroup utility_range
* \overload
*/
template <template <class...> typename container_t, std::ranges::input_range rng_t, typename... args_t>
constexpr auto to(rng_t && rng, args_t &&... args)
{
return detail::adaptor_from_functor{detail::to_template_template_fn<container_t>{},
std::forward<args_t>(args)...}(std::forward<rng_t>(rng));
}

} // namespace seqan3::ranges

namespace seqan3::views
{

/*!\brief Converts a range to a container.
* \ingroup utility_views
* \deprecated Use seqan3::ranges::to instead.
*/
template <typename container_t, typename... args_t>
SEQAN3_DEPRECATED_330 constexpr auto to(args_t &&... args)
{
return ranges::to<container_t>(std::forward<args_t>(args)...);
}

/*!\brief Converts a range to a container.
* \ingroup utility_views
* \deprecated Use seqan3::ranges::to instead.
*/
template <template <typename...> typename container_t, typename... args_t>
SEQAN3_DEPRECATED_330 constexpr auto to(args_t &&... args)
{
return ranges::to<container_t>(std::forward<args_t>(args)...);
}

/*!\brief Converts a range to a container.
* \ingroup utility_views
* \deprecated Use seqan3::ranges::to instead.
*/
template <typename container_t, std::ranges::input_range rng_t, typename... args_t>
SEQAN3_DEPRECATED_330 constexpr auto to(rng_t && rng, args_t &&... args)
{
return ranges::to<container_t>(std::forward<rng_t>(rng), std::forward<args_t>(args)...);
}

/*!\brief Converts a range to a container.
* \ingroup utility_views
* \deprecated Use seqan3::ranges::to instead.
*/
template <template <typename...> typename container_t, std::ranges::input_range rng_t, typename... args_t>
SEQAN3_DEPRECATED_330 constexpr auto to(rng_t && rng, args_t &&... args)
{
return ranges::to<container_t>(std::forward<rng_t>(rng), std::forward<args_t>(args)...);
}

} // namespace seqan3::views
2 changes: 1 addition & 1 deletion include/seqan3/utility/views/all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@

#pragma once

#include <seqan3/utility/range/to.hpp>
#include <seqan3/utility/views/chunk.hpp>
#include <seqan3/utility/views/convert.hpp>
#include <seqan3/utility/views/deep.hpp>
Expand All @@ -179,6 +180,5 @@
#include <seqan3/utility/views/repeat_n.hpp>
#include <seqan3/utility/views/single_pass_input.hpp>
#include <seqan3/utility/views/slice.hpp>
#include <seqan3/utility/views/to.hpp>
#include <seqan3/utility/views/type_reduce.hpp>
#include <seqan3/utility/views/zip.hpp>
25 changes: 5 additions & 20 deletions include/seqan3/utility/views/to.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,9 @@

#pragma once

#include <seqan3/std/ranges>
#include <seqan3/utility/range/to.hpp>

#include <seqan3/core/platform.hpp>

#include <range/v3/range/conversion.hpp>

namespace seqan3::views
{

/*!\brief A to view
* \ingroup utility_views
* \details
* \noapi{This is currently range-v3's to implementation.}
*/
#if SEQAN3_DOXYGEN_ONLY(1) 0
inline constexpr auto to;
#else // ^^^ doxygen only / real import vvv
using ::ranges::to;
#endif // SEQAN3_DOXYGEN_ONLY(1)0

} // namespace seqan3::views
// clang-format off
SEQAN3_DEPRECATED_HEADER(
"This header is deprecated and will be removed in SeqAn-3.3.0; Please #include <seqan3/utility/range/to.hpp> instead.")
// clang-format on

0 comments on commit 53b2bcf

Please sign in to comment.