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

source code of libcxx/test/std/ranges/range.utility/range.utility.conv/to_deduction.pass.cpp