//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // Test that `ranges::to` can be used to convert between arbitrary standard containers. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test_iterators.h" #include "test_range.h" #include "type_algorithms.h" #include "unwrap_container_adaptor.h" std::vector> ints = { {5, 1, 3, 4, 2}, {3}, {} }; std::vector> chars = { {'a', 'b', 'c'}, {'a'}, {} }; std::vector>> pairs = { {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}}, {{1, 2}}, {} }; template void test_is_equal(std::vector> inputs) { for (const auto& in : inputs) { From from(in.begin(), in.end()); std::same_as decltype(auto) result = std::ranges::to(from); assert(std::ranges::equal(in, result)); } } template void test_is_permutation(std::vector> inputs) { for (const auto& in : inputs) { From from(in.begin(), in.end()); std::same_as decltype(auto) result = std::ranges::to(in); assert(std::ranges::is_permutation(in, result)); } } template void test_is_equal_for_adaptors(std::vector> inputs) { for (const auto& in : inputs) { From from(in.begin(), in.end()); std::same_as decltype(auto) result = std::ranges::to(in); UnwrapAdaptor unwrap_from(std::move(from)); UnwrapAdaptor unwrap_to(std::move(result)); assert(std::ranges::is_permutation(unwrap_from.get_container(), unwrap_to.get_container())); } } template using sequence_containers = types::type_list< std::vector, std::deque, std::list, std::forward_list >; template using associative_sets = types::type_list< std::set, std::multiset >; template using associative_maps = types::type_list< std::map, std::multimap >; template using unordered_sets = types::type_list< std::unordered_set, std::unordered_multiset >; template using unordered_maps = types::type_list< std::unordered_map, std::unordered_multimap >; template using container_adaptors = types::type_list< std::stack, std::queue, std::priority_queue >; template using sequences_and_sets = types::concatenate_t, associative_sets, unordered_sets>; template using all_containers = types::concatenate_t< sequence_containers>, associative_sets>, associative_maps, unordered_sets>, unordered_maps>; // This is necessary to be able to use `pair`s with unordered sets. template struct std::hash> { std::size_t operator()(const std::pair& p) const { std::size_t h1 = std::hash{}(p.first); std::size_t h2 = std::hash{}(p.second); return h1 ^ (h2 << 1); } }; void test() { { // Conversions always preserving equality. { // sequences <-> sequences types::for_each(sequence_containers{}, []() { types::for_each(sequence_containers{}, []() { test_is_equal(ints); }); }); types::for_each(sequence_containers{}, []() { types::for_each(sequence_containers{}, []() { test_is_equal(ints); }); }); } { // sequences <-> string types::for_each(sequence_containers{}, []() { test_is_equal>(chars); test_is_equal, Seq>(chars); }); } } { // sequences/sets <-> sequences/sets types::for_each(sequences_and_sets{}, []() { types::for_each(sequences_and_sets{}, []() { test_is_permutation(ints); }); }); types::for_each(sequences_and_sets{}, []() { types::for_each(sequences_and_sets{}, []() { test_is_permutation(ints); }); }); } { // sequences/sets/maps <-> sequences/sets/maps. Uses `pair` for non-map containers to allow mutual conversion with // map types. types::for_each(all_containers{}, []() { types::for_each(all_containers{}, []() { test_is_permutation(pairs); }); }); types::for_each(all_containers{}, []() { types::for_each(all_containers{}, []() { test_is_permutation(pairs); }); }); } { // adaptors <-> adaptors types::for_each(container_adaptors{}, []() { types::for_each(container_adaptors{}, []() { test_is_equal_for_adaptors(ints); }); }); types::for_each(container_adaptors{}, []() { types::for_each(container_adaptors{}, []() { test_is_equal_for_adaptors(ints); }); }); } } int main(int, char**) { test(); return 0; }