//===----------------------------------------------------------------------===// // // 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 // There is a bug in older versions of Clang that causes trouble with constraints in classes like // `ContainerWithDirectCtr`. // XFAIL: apple-clang-15 // template class C, input_range R, class... Args> // constexpr auto to(R&& r, Args&&... args); // Since C++23 #include #include #include #include #include "container.h" template struct ContainerWithDirectCtr : Container { using Container::Container; }; template ContainerWithDirectCtr(Range&&) -> ContainerWithDirectCtr>; template ContainerWithDirectCtr(Range&&, int, char) -> ContainerWithDirectCtr>; template struct ContainerWithFromRangeT : Container { using Container::Container; }; template ContainerWithFromRangeT(std::from_range_t, Range&&) -> ContainerWithFromRangeT>; template ContainerWithFromRangeT(std::from_range_t, Range&&, int, char) -> ContainerWithFromRangeT>; template struct ContainerWithBeginEndPair : Container { using Container::Container; }; template ContainerWithBeginEndPair(Iter, Iter) -> ContainerWithBeginEndPair>; template ContainerWithBeginEndPair(Iter, Iter, int, char) -> ContainerWithBeginEndPair>; constexpr bool test() { std::array in = {1, 2, 3, 4, 5}; int arg1 = 42; char arg2 = 'a'; { // Case 1 -- can construct directly from the given range. { std::same_as> decltype(auto) result = std::ranges::to(in); assert(result.ctr_choice == CtrChoice::DirectCtr); assert(std::ranges::equal(result, in)); assert((in | std::ranges::to()) == result); } { // Extra arguments. std::same_as> decltype(auto) result = std::ranges::to(in, arg1, arg2); assert(result.ctr_choice == CtrChoice::DirectCtr); assert(std::ranges::equal(result, in)); assert(result.extra_arg1 == arg1); assert(result.extra_arg2 == arg2); assert((in | std::ranges::to(arg1, arg2)) == result); } } { // Case 2 -- can construct from the given range using the `from_range_t` tagged constructor. { std::same_as> decltype(auto) result = std::ranges::to(in); assert(result.ctr_choice == CtrChoice::FromRangeT); assert(std::ranges::equal(result, in)); assert((in | std::ranges::to()) == result); } { // Extra arguments. std::same_as> decltype(auto) result = std::ranges::to(in, arg1, arg2); assert(result.ctr_choice == CtrChoice::FromRangeT); assert(std::ranges::equal(result, in)); assert(result.extra_arg1 == arg1); assert(result.extra_arg2 == arg2); assert((in | std::ranges::to(arg1, arg2)) == result); } } { // Case 3 -- can construct from a begin-end iterator pair. { std::same_as> decltype(auto) result = std::ranges::to(in); assert(result.ctr_choice == CtrChoice::BeginEndPair); assert(std::ranges::equal(result, in)); assert((in | std::ranges::to()) == result); } { // Extra arguments. std::same_as> decltype(auto) result = std::ranges::to(in, arg1, arg2); assert(result.ctr_choice == CtrChoice::BeginEndPair); assert(std::ranges::equal(result, in)); assert(result.extra_arg1 == arg1); assert(result.extra_arg2 == arg2); assert((in | std::ranges::to(arg1, arg2)) == result); } } return true; } int main(int, char**) { test(); static_assert(test()); return 0; }