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
10
11// template<class I1, class I2, class Out,
12// class R = ranges::less, class P1 = identity, class P2 = identity>
13// concept mergeable = see below; // since C++20
14
15#include <iterator>
16
17#include <functional>
18
19#include "test_iterators.h"
20#include "test_macros.h"
21
22using CompDefault = std::ranges::less;
23using CompInt = bool(*)(int, int);
24using ProjDefault = std::identity;
25
26using Input = cpp20_input_iterator<int*>;
27static_assert( std::input_iterator<Input>);
28using InputLong = cpp20_input_iterator<long*>;
29static_assert( std::input_iterator<InputLong>);
30
31using Output = cpp17_output_iterator<int*>;
32static_assert( std::weakly_incrementable<Output>);
33
34static_assert( std::indirectly_copyable<Input, Output>);
35static_assert( std::indirectly_copyable<InputLong, Output>);
36static_assert( std::indirect_strict_weak_order<CompDefault, Input, Input>);
37static_assert( std::indirect_strict_weak_order<CompInt, Input, Input>);
38static_assert( std::indirect_strict_weak_order<CompDefault, Input, InputLong>);
39static_assert( std::indirect_strict_weak_order<CompInt, Input, InputLong>);
40
41// All requirements satisfied.
42static_assert( std::mergeable<Input, Input, Output>);
43static_assert( std::mergeable<Input, Input, Output, CompInt>);
44static_assert( std::mergeable<Input, Input, Output, CompInt, ProjDefault>);
45
46// Non-default projections.
47struct Foo {};
48using ProjFooToInt = int(*)(Foo);
49using ProjFooToLong = long(*)(Foo);
50static_assert( std::indirect_strict_weak_order<CompDefault,
51 std::projected<Foo*, ProjFooToInt>, std::projected<Foo*, ProjFooToLong>>);
52static_assert( std::mergeable<Foo*, Foo*, Foo*, CompDefault, ProjFooToInt, ProjFooToLong>);
53static_assert( std::indirect_strict_weak_order<CompInt,
54 std::projected<Foo*, ProjFooToInt>, std::projected<Foo*, ProjFooToLong>>);
55static_assert( std::mergeable<Foo*, Foo*, Foo*, CompInt, ProjFooToInt, ProjFooToLong>);
56
57// I1 or I2 is not an input iterator.
58static_assert(!std::input_iterator<Output>);
59static_assert(!std::mergeable<Output, Input, Output>);
60static_assert(!std::mergeable<Input, Output, Output>);
61
62// O is not weakly incrementable.
63struct NotWeaklyIncrementable {
64 int& operator*() const;
65};
66
67static_assert(!std::weakly_incrementable<NotWeaklyIncrementable>);
68static_assert( std::indirectly_copyable<Input, NotWeaklyIncrementable>);
69static_assert( std::indirect_strict_weak_order<CompDefault, Input, Input>);
70static_assert(!std::mergeable<Input, Input, NotWeaklyIncrementable>);
71
72// I1 or I2 is not indirectly copyable into O.
73struct AssignableOnlyFromInt {
74 AssignableOnlyFromInt& operator=(int);
75 template <class T>
76 AssignableOnlyFromInt& operator=(T) = delete;
77};
78using OutputOnlyInt = cpp17_output_iterator<AssignableOnlyFromInt*>;
79static_assert( std::weakly_incrementable<OutputOnlyInt>);
80
81static_assert( std::indirectly_copyable<Input, OutputOnlyInt>);
82static_assert(!std::indirectly_copyable<InputLong, OutputOnlyInt>);
83static_assert( std::indirect_strict_weak_order<CompDefault, Input, InputLong>);
84static_assert( std::mergeable<Input, Input, OutputOnlyInt>);
85static_assert(!std::mergeable<Input, InputLong, OutputOnlyInt>);
86static_assert(!std::mergeable<InputLong, Input, OutputOnlyInt>);
87
88// No indirect strict weak order between I1 and I2 (bad comparison functor).
89using GoodComp = bool(*)(int, int);
90static_assert( std::indirect_strict_weak_order<GoodComp, Input, Input>);
91static_assert( std::mergeable<Input, Input, Output, GoodComp>);
92using BadComp = bool(*)(int*, int*);
93static_assert(!std::indirect_strict_weak_order<BadComp, Input, Input>);
94static_assert(!std::mergeable<Input, Input, Output, BadComp>);
95
96// No indirect strict weak order between I1 and I2 (bad projection).
97using ToInt = int(*)(int);
98using ToPtr = int*(*)(int);
99static_assert( std::mergeable<Input, Input, Output, GoodComp, std::identity, std::identity>);
100static_assert( std::mergeable<Input, Input, Output, GoodComp, ToInt, ToInt>);
101static_assert(!std::mergeable<Input, Input, Output, GoodComp, ToPtr, ToInt>);
102static_assert(!std::mergeable<Input, Input, Output, GoodComp, ToInt, ToPtr>);
103static_assert(!std::mergeable<Input, Input, Output, bool(*)(int*, int), ToPtr, ToInt>);
104static_assert(!std::mergeable<Input, Input, Output, bool(*)(int, int*), ToInt, ToPtr>);
105
106// A projection that only supports non-const references and has a non-const `operator()` still has to work.
107struct ProjectionOnlyMutable {
108 int operator()(int&);
109 int operator()(int&&) const = delete;
110};
111static_assert( std::mergeable<Input, Input, Output, CompDefault, ProjectionOnlyMutable, ProjectionOnlyMutable>);
112
113// The output is weakly incrementable but not an output iterator.
114struct WeaklyIncrementable {
115 using value_type = int;
116 using difference_type = int;
117
118 int& operator*() const;
119 WeaklyIncrementable& operator++();
120 // `output_iterator` requires `i++` to return an iterator,
121 // while `weakly_incrementable` requires only that `i++` be well-formed.
122 void operator++(int);
123};
124static_assert( std::weakly_incrementable<WeaklyIncrementable>);
125static_assert( std::indirectly_copyable<int*, WeaklyIncrementable>);
126static_assert(!std::output_iterator<WeaklyIncrementable, int>);
127static_assert( std::mergeable<Input, Input, WeaklyIncrementable>);
128

source code of libcxx/test/std/iterators/iterator.requirements/alg.req.mergeable/mergeable.compile.pass.cpp