1c3648f37Svarconst //===----------------------------------------------------------------------===//
2c3648f37Svarconst //
3c3648f37Svarconst // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c3648f37Svarconst // See https://llvm.org/LICENSE.txt for license information.
5c3648f37Svarconst // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c3648f37Svarconst //
7c3648f37Svarconst //===----------------------------------------------------------------------===//
8c3648f37Svarconst
9c3648f37Svarconst // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10c3648f37Svarconst
11c3648f37Svarconst // Test that the "mandates" requirements on the given container are checked correctly using `static_assert`.
12c3648f37Svarconst
13c3648f37Svarconst #include <ranges>
14c3648f37Svarconst #include <vector>
15c3648f37Svarconst
16c3648f37Svarconst template <bool HasDefaultCtr = true, bool HasSingleArgCtr = true,
17c3648f37Svarconst bool HasInsert = true, bool HasInsertWithRightSignature = true,
18c3648f37Svarconst bool HasPushBack = true, bool HasPushBackWithRightSignature = true>
19c3648f37Svarconst struct Container {
20c3648f37Svarconst using value_type = int;
21c3648f37Svarconst
beginContainer22c3648f37Svarconst int* begin() const { return nullptr; }
endContainer23c3648f37Svarconst int* end() const { return nullptr; }
24c3648f37Svarconst
25c3648f37Svarconst Container()
26c3648f37Svarconst requires HasDefaultCtr = default;
27c3648f37Svarconst
ContainerContainer28c3648f37Svarconst Container(int)
29c3648f37Svarconst requires HasSingleArgCtr {
30c3648f37Svarconst }
31c3648f37Svarconst
insertContainer32c3648f37Svarconst int* insert(int*, int)
33c3648f37Svarconst requires (HasInsert && HasInsertWithRightSignature) {
34c3648f37Svarconst return nullptr;
35c3648f37Svarconst }
36c3648f37Svarconst
insertContainer37c3648f37Svarconst int* insert()
38c3648f37Svarconst requires (HasInsert && !HasInsertWithRightSignature) {
39c3648f37Svarconst return nullptr;
40c3648f37Svarconst }
41c3648f37Svarconst
push_backContainer42c3648f37Svarconst void push_back(int)
43c3648f37Svarconst requires (HasPushBack && HasPushBackWithRightSignature) {
44c3648f37Svarconst }
45c3648f37Svarconst
push_backContainer46c3648f37Svarconst void push_back()
47c3648f37Svarconst requires (HasPushBack && !HasPushBackWithRightSignature) {
48c3648f37Svarconst }
49c3648f37Svarconst
50c3648f37Svarconst };
51c3648f37Svarconst
test()52c3648f37Svarconst void test() {
53c3648f37Svarconst using R = std::vector<int>;
54c3648f37Svarconst R in = {1, 2, 3};
55c3648f37Svarconst
56c3648f37Svarconst // Case 4 -- default-construct (or construct from the extra arguments) and insert.
57c3648f37Svarconst { // All constraints satisfied.
58c3648f37Svarconst using C = Container<>;
59c3648f37Svarconst (void)std::ranges::to<C>(in);
60c3648f37Svarconst (void)std::ranges::to<C>(in, 1);
61c3648f37Svarconst (void)std::ranges::to<C>(in, 1.0);
62c3648f37Svarconst }
63c3648f37Svarconst
64c3648f37Svarconst { // No default constructor.
65c3648f37Svarconst using C = Container</*HasDefaultCtr=*/false>;
66*9bb9ec38SLouis Dionne (void)std::ranges::to<C>(in); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
67c3648f37Svarconst }
68c3648f37Svarconst
69c3648f37Svarconst { // No single-argument constructor.
70c3648f37Svarconst using C = Container</*HasDefaultCtr=*/true, /*HasSingleArgCtr=*/false>;
71*9bb9ec38SLouis Dionne (void)std::ranges::to<C>(in, 1); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
72c3648f37Svarconst }
73c3648f37Svarconst
74c3648f37Svarconst { // No `insert` and no `push_back`.
75c3648f37Svarconst using C = Container</*HasDefaultCtr=*/true, /*HasSingleArgCtr=*/true,
76c3648f37Svarconst /*HasInsert=*/false, /*HasInsertWithRightSignature=*/false,
77c3648f37Svarconst /*HasPushBack=*/false, /*HasPushBackWithRightSignature=*/false>;
78*9bb9ec38SLouis Dionne (void)std::ranges::to<C>(in); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
79c3648f37Svarconst }
80c3648f37Svarconst
81c3648f37Svarconst { // No `push_back`, `insert` has a wrong signature.
82c3648f37Svarconst using C = Container</*HasDefaultCtr=*/true, /*HasSingleArgCtr=*/true,
83c3648f37Svarconst /*HasInsert=*/true, /*HasInsertWithRightSignature=*/false,
84c3648f37Svarconst /*HasPushBack=*/false, /*HasPushBackWithRightSignature=*/false>;
85*9bb9ec38SLouis Dionne (void)std::ranges::to<C>(in); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
86c3648f37Svarconst }
87c3648f37Svarconst
88c3648f37Svarconst { // No `insert`, `push_back` has a wrong signature.
89c3648f37Svarconst using C = Container</*HasDefaultCtr=*/true, /*HasSingleArgCtr=*/true,
90c3648f37Svarconst /*HasInsert=*/false, /*HasInsertWithRightSignature=*/false,
91c3648f37Svarconst /*HasPushBack=*/true, /*HasPushBackWithRightSignature=*/false>;
92*9bb9ec38SLouis Dionne (void)std::ranges::to<C>(in); //expected-error-re@*:* {{static assertion failed{{.*}}ranges::to: unable to convert to the given container type}}
93c3648f37Svarconst }
94c3648f37Svarconst }
95