brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.9 KiB · 4c19ea4 Raw
215 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 11// Test that `ranges::to` can be used to convert between arbitrary standard containers.12 13#include <ranges>14 15#include <algorithm>16#include <cassert>17#include <deque>18#include <forward_list>19#include <list>20#include <map>21#include <queue>22#include <set>23#include <stack>24#include <string>25#include <unordered_map>26#include <unordered_set>27#include <vector>28 29#include "test_iterators.h"30#include "test_range.h"31#include "type_algorithms.h"32#include "unwrap_container_adaptor.h"33 34std::vector<std::vector<int>> ints = {35  {5, 1, 3, 4, 2},36  {3},37  {}38};39 40std::vector<std::vector<char>> chars = {41  {'a', 'b', 'c'},42  {'a'},43  {}44};45 46std::vector<std::vector<std::pair<const int, int>>> pairs = {47  {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}},48  {{1, 2}},49  {}50};51 52template <class From, class To>53void test_is_equal(std::vector<std::vector<typename From::value_type>> inputs) {54  for (const auto& in : inputs) {55    From from(in.begin(), in.end());56    std::same_as<To> decltype(auto) result = std::ranges::to<To>(from);57    assert(std::ranges::equal(in, result));58  }59}60 61template <class From, class To>62void test_is_permutation(std::vector<std::vector<typename From::value_type>> inputs) {63  for (const auto& in : inputs) {64    From from(in.begin(), in.end());65    std::same_as<To> decltype(auto) result = std::ranges::to<To>(in);66    assert(std::ranges::is_permutation(in, result));67  }68}69 70template <class From, class To>71void test_is_equal_for_adaptors(std::vector<std::vector<typename From::value_type>> inputs) {72  for (const auto& in : inputs) {73    From from(in.begin(), in.end());74    std::same_as<To> decltype(auto) result = std::ranges::to<To>(in);75 76    UnwrapAdaptor<From> unwrap_from(std::move(from));77    UnwrapAdaptor<To> unwrap_to(std::move(result));78    assert(std::ranges::is_permutation(unwrap_from.get_container(), unwrap_to.get_container()));79  }80}81 82template <class T>83using sequence_containers = types::type_list<84    std::vector<T>,85    std::deque<T>,86    std::list<T>,87    std::forward_list<T>88>;89 90template <class T>91using associative_sets = types::type_list<92    std::set<T>,93    std::multiset<T>94>;95 96template <class K, class V>97using associative_maps = types::type_list<98    std::map<K, V>,99    std::multimap<K, V>100>;101 102template <class T>103using unordered_sets = types::type_list<104    std::unordered_set<T>,105    std::unordered_multiset<T>106>;107 108template <class K, class V>109using unordered_maps = types::type_list<110    std::unordered_map<K, V>,111    std::unordered_multimap<K, V>112>;113 114template <class T>115using container_adaptors = types::type_list<116    std::stack<T>,117    std::queue<T>,118    std::priority_queue<T>119>;120 121template <class T>122using sequences_and_sets = types::concatenate_t<sequence_containers<T>, associative_sets<T>, unordered_sets<T>>;123 124template <class K, class V>125using all_containers = types::concatenate_t<126    sequence_containers<std::pair<const K, V>>,127    associative_sets<std::pair<const K, V>>,128    associative_maps<K, V>,129    unordered_sets<std::pair<const K, V>>,130    unordered_maps<K, V>>;131 132// This is necessary to be able to use `pair`s with unordered sets.133template <class K, class V>134struct std::hash<std::pair<const K, V>> {135  std::size_t operator()(const std::pair<const K, V>& p) const {136    std::size_t h1 = std::hash<K>{}(p.first);137    std::size_t h2 = std::hash<V>{}(p.second);138    return h1 ^ (h2 << 1);139  }140};141 142void test() {143  { // Conversions always preserving equality.144    { // sequences <-> sequences145      types::for_each(sequence_containers<int>{}, []<class From>() {146        types::for_each(sequence_containers<int>{}, []<class To>() {147          test_is_equal<From, To>(ints);148        });149      });150 151      types::for_each(sequence_containers<int>{}, []<class From>() {152        types::for_each(sequence_containers<double>{}, []<class To>() {153          test_is_equal<From, To>(ints);154        });155      });156    }157 158    { // sequences <-> string159      types::for_each(sequence_containers<char>{}, []<class Seq>() {160        test_is_equal<Seq, std::basic_string<char>>(chars);161        test_is_equal<std::basic_string<char>, Seq>(chars);162      });163    }164  }165 166  { // sequences/sets <-> sequences/sets167    types::for_each(sequences_and_sets<int>{}, []<class From>() {168      types::for_each(sequences_and_sets<int>{}, []<class To>() {169        test_is_permutation<From, To>(ints);170      });171    });172 173    types::for_each(sequences_and_sets<int>{}, []<class From>() {174      types::for_each(sequences_and_sets<double>{}, []<class To>() {175        test_is_permutation<From, To>(ints);176      });177    });178  }179 180  { // sequences/sets/maps <-> sequences/sets/maps. Uses `pair` for non-map containers to allow mutual conversion with181    // map types.182    types::for_each(all_containers<int, int>{}, []<class From>() {183      types::for_each(all_containers<int, int>{}, []<class To>() {184        test_is_permutation<From, To>(pairs);185      });186    });187 188    types::for_each(all_containers<int, int>{}, []<class From>() {189      types::for_each(all_containers<long, double>{}, []<class To>() {190        test_is_permutation<From, To>(pairs);191      });192    });193  }194 195  { // adaptors <-> adaptors196    types::for_each(container_adaptors<int>{}, []<class From>() {197      types::for_each(container_adaptors<int>{}, []<class To>() {198        test_is_equal_for_adaptors<From, To>(ints);199      });200    });201 202    types::for_each(container_adaptors<int>{}, []<class From>() {203      types::for_each(container_adaptors<double>{}, []<class To>() {204        test_is_equal_for_adaptors<From, To>(ints);205      });206    });207  }208}209 210int main(int, char**) {211  test();212 213  return 0;214}215