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 
11 // Test that the "mandates" requirements on the given container are checked correctly using `static_assert`.
12 
13 #include <ranges>
14 #include <vector>
15 
16 template <bool HasDefaultCtr = true, bool HasSingleArgCtr = true,
17           bool HasInsert = true, bool HasInsertWithRightSignature = true,
18           bool HasPushBack = true, bool HasPushBackWithRightSignature = true>
19 struct Container {
20   using value_type = int;
21 
beginContainer22   int* begin() const { return nullptr; }
endContainer23   int* end() const { return nullptr; }
24 
25   Container()
26   requires HasDefaultCtr = default;
27 
ContainerContainer28   Container(int)
29   requires HasSingleArgCtr {
30   }
31 
insertContainer32   int* insert(int*, int)
33   requires (HasInsert && HasInsertWithRightSignature) {
34     return nullptr;
35   }
36 
insertContainer37   int* insert()
38   requires (HasInsert && !HasInsertWithRightSignature) {
39     return nullptr;
40   }
41 
push_backContainer42   void push_back(int)
43   requires (HasPushBack && HasPushBackWithRightSignature) {
44   }
45 
push_backContainer46   void push_back()
47   requires (HasPushBack && !HasPushBackWithRightSignature) {
48   }
49 
50 };
51 
test()52 void test() {
53   using R = std::vector<int>;
54   R in = {1, 2, 3};
55 
56   // Case 4 -- default-construct (or construct from the extra arguments) and insert.
57   { // All constraints satisfied.
58     using C = Container<>;
59     (void)std::ranges::to<C>(in);
60     (void)std::ranges::to<C>(in, 1);
61     (void)std::ranges::to<C>(in, 1.0);
62   }
63 
64   { // No default constructor.
65     using C = Container</*HasDefaultCtr=*/false>;
66     (void)std::ranges::to<C>(in); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
67   }
68 
69   { // No single-argument constructor.
70     using C = Container</*HasDefaultCtr=*/true, /*HasSingleArgCtr=*/false>;
71     (void)std::ranges::to<C>(in, 1); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
72   }
73 
74   { // No `insert` and no `push_back`.
75     using C = Container</*HasDefaultCtr=*/true, /*HasSingleArgCtr=*/true,
76                         /*HasInsert=*/false, /*HasInsertWithRightSignature=*/false,
77                         /*HasPushBack=*/false, /*HasPushBackWithRightSignature=*/false>;
78     (void)std::ranges::to<C>(in); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
79   }
80 
81   { // No `push_back`, `insert` has a wrong signature.
82     using C = Container</*HasDefaultCtr=*/true, /*HasSingleArgCtr=*/true,
83                         /*HasInsert=*/true, /*HasInsertWithRightSignature=*/false,
84                         /*HasPushBack=*/false, /*HasPushBackWithRightSignature=*/false>;
85     (void)std::ranges::to<C>(in); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
86   }
87 
88   { // No `insert`, `push_back` has a wrong signature.
89     using C = Container</*HasDefaultCtr=*/true, /*HasSingleArgCtr=*/true,
90                         /*HasInsert=*/false, /*HasInsertWithRightSignature=*/false,
91                         /*HasPushBack=*/true, /*HasPushBackWithRightSignature=*/false>;
92     (void)std::ranges::to<C>(in); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
93   }
94 }
95