From d6330af06996fd8276707d30eed5d277a49c7dea Mon Sep 17 00:00:00 2001 From: Simon Gene Gottlieb Date: Fri, 3 Jun 2022 17:23:55 +0200 Subject: [PATCH 1/2] [FEATURE] seqan3::ranges::to --- CHANGELOG.md | 5 + .../04_alphabet/alphabet_gc_content.cpp | 7 +- doc/tutorial/05_ranges/to.cpp | 39 ++++ include/seqan3/io/sam_file/format_sam.hpp | 6 +- .../io/structure_file/format_vienna.hpp | 4 +- .../utility/container/dynamic_bitset.hpp | 5 +- include/seqan3/utility/range/all.hpp | 1 + include/seqan3/utility/range/to.hpp | 196 ++++++++++++++++++ include/seqan3/utility/views/all.hpp | 2 +- include/seqan3/utility/views/to.hpp | 25 +-- ...al_affine_alignment_parallel_benchmark.cpp | 4 +- .../views/view_translate_1D_benchmark.cpp | 8 +- .../views/view_translate_2D_1D_benchmark.cpp | 16 +- .../views/view_translate_2D_benchmark.cpp | 14 +- .../io/format_vienna_benchmark.cpp | 4 +- .../interleaved_bloom_filter_benchmark.cpp | 6 +- .../search/index_construction_benchmark.cpp | 12 +- test/performance/search/search_benchmark.cpp | 4 +- .../utility/simd/views/to_simd_benchmark.cpp | 4 +- .../alphabet/composite/semialphabet_any.cpp | 6 +- .../views/range_view_all_retransform.cpp | 6 +- .../utility/views/convert_int_to_bool.cpp | 4 +- .../debug_stream_alignment_test.cpp | 8 +- ...ise_alignment_collection_test_template.hpp | 12 +- .../bi_fm_index_cursor_collection_test.cpp | 12 +- .../bi_fm_index_cursor_test.cpp | 8 +- .../fm_index_cursor_collection_test.cpp | 2 +- .../fm_index_cursor/fm_index_cursor_test.cpp | 2 +- test/unit/search/helper.hpp | 4 +- .../search/search_scheme_algorithm_test.cpp | 9 +- test/unit/search/search_test.cpp | 18 +- test/unit/utility/range/CMakeLists.txt | 1 + test/unit/utility/range/to_test.cpp | 168 +++++++++++++++ 33 files changed, 511 insertions(+), 111 deletions(-) create mode 100644 doc/tutorial/05_ranges/to.cpp create mode 100644 include/seqan3/utility/range/to.hpp create mode 100644 test/unit/utility/range/CMakeLists.txt create mode 100644 test/unit/utility/range/to_test.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index bf196b76e7..16b73698fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/doc/tutorial/04_alphabet/alphabet_gc_content.cpp b/doc/tutorial/04_alphabet/alphabet_gc_content.cpp index b673b8525a..8517ece0d4 100644 --- a/doc/tutorial/04_alphabet/alphabet_gc_content.cpp +++ b/doc/tutorial/04_alphabet/alphabet_gc_content.cpp @@ -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 sequence = input | seqan3::views::char_to | seqan3::views::to; + // std::vector sequence = input + // | seqan3::views::char_to + // | seqan3::ranges::to(); // Initialise an array with count values for dna5 symbols. std::array count{}; // default initialised with zeroes @@ -56,5 +58,6 @@ void alternatively() { std::string input{}; // if something changes in here, please update above: - std::vector sequence = input | seqan3::views::char_to | seqan3::views::to; + std::vector sequence = + input | seqan3::views::char_to | seqan3::ranges::to(); } diff --git a/doc/tutorial/05_ranges/to.cpp b/doc/tutorial/05_ranges/to.cpp new file mode 100644 index 0000000000..af9ca7d55f --- /dev/null +++ b/doc/tutorial/05_ranges/to.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +#include + +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>(); + static_assert(std::same_as>); + + // convert range to vector but auto deducing the element type + auto vec1 = lst | seqan3::ranges::to(); + static_assert(std::same_as>); + + // convert range to vector using function call syntax + auto vec2 = seqan3::ranges::to>(lst); + static_assert(std::same_as>); + + // using function call syntax and auto deducing element type + auto vec3 = seqan3::ranges::to(lst); + static_assert(std::same_as>); + + // convert nested ranges into nested containers + auto nested_lst = std::list>{{1, 2, 3}, {4, 5, 6, 7}}; + auto vec4 = nested_lst | seqan3::ranges::to>>(); + static_assert(std::same_as>>); + + // different supported container types + auto vec5 = lst | seqan3::ranges::to(); + static_assert(std::same_as>); + + auto vec6 = lst | seqan3::ranges::to(); + static_assert(std::same_as>); +} diff --git a/include/seqan3/io/sam_file/format_sam.hpp b/include/seqan3/io/sam_file/format_sam.hpp index a669ea7e60..4e62deed76 100644 --- a/include/seqan3/io/sam_file/format_sam.hpp +++ b/include/seqan3/io/sam_file/format_sam.hpp @@ -32,9 +32,9 @@ #include #include #include +#include #include #include -#include namespace seqan3 { @@ -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 = id | detail::take_until_and_consume(is_space) | ranges::to(); } //!\copydoc sequence_file_output_format::write_sequence_record @@ -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; + target[tag] = stream_view | ranges::to(); break; } case 'H': diff --git a/include/seqan3/io/structure_file/format_vienna.hpp b/include/seqan3/io/structure_file/format_vienna.hpp index 7629537fbd..9c0ff672c9 100644 --- a/include/seqan3/io/structure_file/format_vienna.hpp +++ b/include/seqan3/io/structure_file/format_vienna.hpp @@ -40,7 +40,7 @@ #include #include #include -#include +#include namespace seqan3 { @@ -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; + | ranges::to(); if (!e_str.empty()) { size_t num_processed; diff --git a/include/seqan3/utility/container/dynamic_bitset.hpp b/include/seqan3/utility/container/dynamic_bitset.hpp index bd6a44372b..5c362d698a 100644 --- a/include/seqan3/utility/container/dynamic_bitset.hpp +++ b/include/seqan3/utility/container/dynamic_bitset.hpp @@ -17,9 +17,9 @@ #include #include #include +#include #include #include -#include namespace seqan3 { @@ -1947,7 +1947,8 @@ class dynamic_bitset template friend debug_stream_type & operator<<(debug_stream_type & s, dynamic_bitset arg) { - s << (std::string_view{arg.to_string()} | views::interleave(4, std::string_view{"'"}) | views::to); + s << (std::string_view{arg.to_string()} | views::interleave(4, std::string_view{"'"}) + | ranges::to()); return s; } //!\} diff --git a/include/seqan3/utility/range/all.hpp b/include/seqan3/utility/range/all.hpp index 4125c81f05..31e0f46e3d 100644 --- a/include/seqan3/utility/range/all.hpp +++ b/include/seqan3/utility/range/all.hpp @@ -79,3 +79,4 @@ #pragma once #include +#include diff --git a/include/seqan3/utility/range/to.hpp b/include/seqan3/utility/range/to.hpp new file mode 100644 index 0000000000..fdefa729dc --- /dev/null +++ b/include/seqan3/utility/range/to.hpp @@ -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 + * \brief Provides seqan3::ranges::to. + */ + +#pragma once + +#include +#include + +#include +#include + +namespace seqan3::detail +{ + +//!\brief Function object to convert a std::ranges::input_range to a fully defined container. +template + requires (!std::ranges::view) +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 + requires std::convertible_to, std::ranges::range_value_t> + auto impl(rng_t && rng, container_t & container) const + { + std::ranges::copy(rng, std::back_inserter(container)); + } + + //!\overload + template + auto impl(rng_t && rng, container_t & container) const + requires std::ranges::input_range> + { + auto adaptor = to_fn>{}; + 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 + constexpr auto operator()(rng_t && rng, args_t &&... args) const + { + auto new_container = container_t(std::forward(args)...); + + // reserve memory if functionality is available + if constexpr (std::ranges::sized_range && requires (container_t c) { c.reserve(size_t{}); }) + new_container.reserve(std::ranges::size(rng)); + + impl(std::forward(rng), new_container); + return new_container; + } +}; + +/*!\brief Similar to to_fn, but accepts a template-template as argument, + * e.g.: to_fn instead of to_fn>. + */ +template