133 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// template<template<class...> class C, input_range R, class... Args>12// constexpr auto to(R&& r, Args&&... args); // Since C++2313 14#include <ranges>15 16#include <algorithm>17#include <array>18#include <cassert>19#include "container.h"20 21template <class ElementType>22struct ContainerWithDirectCtr : Container<ElementType, CtrChoice::DirectCtr> {23 using Container<ElementType, CtrChoice::DirectCtr>::Container;24};25 26template <std::ranges::input_range Range>27ContainerWithDirectCtr(Range&&) -> ContainerWithDirectCtr<std::ranges::range_value_t<Range>>;28 29template <std::ranges::input_range Range>30ContainerWithDirectCtr(Range&&, int, char) -> ContainerWithDirectCtr<std::ranges::range_value_t<Range>>;31 32template <class ElementType>33struct ContainerWithFromRangeT : Container<ElementType, CtrChoice::FromRangeT> {34 using Container<ElementType, CtrChoice::FromRangeT>::Container;35};36 37template <std::ranges::input_range Range>38ContainerWithFromRangeT(std::from_range_t, Range&&) -> ContainerWithFromRangeT<std::ranges::range_value_t<Range>>;39 40template <std::ranges::input_range Range>41ContainerWithFromRangeT(std::from_range_t, Range&&, int, char) ->42 ContainerWithFromRangeT<std::ranges::range_value_t<Range>>;43 44template <class ElementType>45struct ContainerWithBeginEndPair : Container<ElementType, CtrChoice::BeginEndPair> {46 using Container<ElementType, CtrChoice::BeginEndPair>::Container;47};48 49template <class Iter>50ContainerWithBeginEndPair(Iter, Iter) -> ContainerWithBeginEndPair<std::iter_value_t<Iter>>;51 52template <class Iter>53ContainerWithBeginEndPair(Iter, Iter, int, char) -> ContainerWithBeginEndPair<std::iter_value_t<Iter>>;54 55constexpr bool test() {56 std::array in = {1, 2, 3, 4, 5};57 int arg1 = 42;58 char arg2 = 'a';59 60 { // Case 1 -- can construct directly from the given range.61 {62 std::same_as<ContainerWithDirectCtr<int>> decltype(auto) result = std::ranges::to<ContainerWithDirectCtr>(in);63 64 assert(result.ctr_choice == CtrChoice::DirectCtr);65 assert(std::ranges::equal(result, in));66 assert((in | std::ranges::to<ContainerWithDirectCtr>()) == result);67 }68 69 { // Extra arguments.70 std::same_as<ContainerWithDirectCtr<int>> decltype(auto) result =71 std::ranges::to<ContainerWithDirectCtr>(in, arg1, arg2);72 73 assert(result.ctr_choice == CtrChoice::DirectCtr);74 assert(std::ranges::equal(result, in));75 assert(result.extra_arg1 == arg1);76 assert(result.extra_arg2 == arg2);77 assert((in | std::ranges::to<ContainerWithDirectCtr>(arg1, arg2)) == result);78 }79 }80 81 { // Case 2 -- can construct from the given range using the `from_range_t` tagged constructor.82 {83 std::same_as<ContainerWithFromRangeT<int>> decltype(auto) result = std::ranges::to<ContainerWithFromRangeT>(in);84 85 assert(result.ctr_choice == CtrChoice::FromRangeT);86 assert(std::ranges::equal(result, in));87 assert((in | std::ranges::to<ContainerWithFromRangeT>()) == result);88 }89 90 { // Extra arguments.91 std::same_as<ContainerWithFromRangeT<int>> decltype(auto) result =92 std::ranges::to<ContainerWithFromRangeT>(in, arg1, arg2);93 94 assert(result.ctr_choice == CtrChoice::FromRangeT);95 assert(std::ranges::equal(result, in));96 assert(result.extra_arg1 == arg1);97 assert(result.extra_arg2 == arg2);98 assert((in | std::ranges::to<ContainerWithFromRangeT>(arg1, arg2)) == result);99 }100 }101 102 { // Case 3 -- can construct from a begin-end iterator pair.103 {104 std::same_as<ContainerWithBeginEndPair<int>> decltype(auto) result =105 std::ranges::to<ContainerWithBeginEndPair>(in);106 107 assert(result.ctr_choice == CtrChoice::BeginEndPair);108 assert(std::ranges::equal(result, in));109 assert((in | std::ranges::to<ContainerWithBeginEndPair>()) == result);110 }111 112 { // Extra arguments.113 std::same_as<ContainerWithBeginEndPair<int>> decltype(auto) result =114 std::ranges::to<ContainerWithBeginEndPair>(in, arg1, arg2);115 116 assert(result.ctr_choice == CtrChoice::BeginEndPair);117 assert(std::ranges::equal(result, in));118 assert(result.extra_arg1 == arg1);119 assert(result.extra_arg2 == arg2);120 assert((in | std::ranges::to<ContainerWithBeginEndPair>(arg1, arg2)) == result);121 }122 }123 124 return true;125}126 127int main(int, char**) {128 test();129 static_assert(test());130 131 return 0;132}133