1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
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
19 #include "test_iterators.h"
20 #include "test_macros.h"
22 using CompDefault
= std::ranges::less
;
23 using CompInt
= bool(*)(int, int);
24 using ProjDefault
= std::identity
;
26 using Input
= cpp20_input_iterator
<int*>;
27 static_assert( std::input_iterator
<Input
>);
28 using InputLong
= cpp20_input_iterator
<long*>;
29 static_assert( std::input_iterator
<InputLong
>);
31 using Output
= cpp17_output_iterator
<int*>;
32 static_assert( std::weakly_incrementable
<Output
>);
34 static_assert( std::indirectly_copyable
<Input
, Output
>);
35 static_assert( std::indirectly_copyable
<InputLong
, Output
>);
36 static_assert( std::indirect_strict_weak_order
<CompDefault
, Input
, Input
>);
37 static_assert( std::indirect_strict_weak_order
<CompInt
, Input
, Input
>);
38 static_assert( std::indirect_strict_weak_order
<CompDefault
, Input
, InputLong
>);
39 static_assert( std::indirect_strict_weak_order
<CompInt
, Input
, InputLong
>);
41 // All requirements satisfied.
42 static_assert( std::mergeable
<Input
, Input
, Output
>);
43 static_assert( std::mergeable
<Input
, Input
, Output
, CompInt
>);
44 static_assert( std::mergeable
<Input
, Input
, Output
, CompInt
, ProjDefault
>);
46 // Non-default projections.
48 using ProjFooToInt
= int(*)(Foo
);
49 using ProjFooToLong
= long(*)(Foo
);
50 static_assert( std::indirect_strict_weak_order
<CompDefault
,
51 std::projected
<Foo
*, ProjFooToInt
>, std::projected
<Foo
*, ProjFooToLong
>>);
52 static_assert( std::mergeable
<Foo
*, Foo
*, Foo
*, CompDefault
, ProjFooToInt
, ProjFooToLong
>);
53 static_assert( std::indirect_strict_weak_order
<CompInt
,
54 std::projected
<Foo
*, ProjFooToInt
>, std::projected
<Foo
*, ProjFooToLong
>>);
55 static_assert( std::mergeable
<Foo
*, Foo
*, Foo
*, CompInt
, ProjFooToInt
, ProjFooToLong
>);
57 // I1 or I2 is not an input iterator.
58 static_assert(!std::input_iterator
<Output
>);
59 static_assert(!std::mergeable
<Output
, Input
, Output
>);
60 static_assert(!std::mergeable
<Input
, Output
, Output
>);
62 // O is not weakly incrementable.
63 struct NotWeaklyIncrementable
{
64 int& operator*() const;
67 static_assert(!std::weakly_incrementable
<NotWeaklyIncrementable
>);
68 static_assert( std::indirectly_copyable
<Input
, NotWeaklyIncrementable
>);
69 static_assert( std::indirect_strict_weak_order
<CompDefault
, Input
, Input
>);
70 static_assert(!std::mergeable
<Input
, Input
, NotWeaklyIncrementable
>);
72 // I1 or I2 is not indirectly copyable into O.
73 struct AssignableOnlyFromInt
{
74 AssignableOnlyFromInt
& operator=(int);
76 AssignableOnlyFromInt
& operator=(T
) = delete;
78 using OutputOnlyInt
= cpp17_output_iterator
<AssignableOnlyFromInt
*>;
79 static_assert( std::weakly_incrementable
<OutputOnlyInt
>);
81 static_assert( std::indirectly_copyable
<Input
, OutputOnlyInt
>);
82 static_assert(!std::indirectly_copyable
<InputLong
, OutputOnlyInt
>);
83 static_assert( std::indirect_strict_weak_order
<CompDefault
, Input
, InputLong
>);
84 static_assert( std::mergeable
<Input
, Input
, OutputOnlyInt
>);
85 static_assert(!std::mergeable
<Input
, InputLong
, OutputOnlyInt
>);
86 static_assert(!std::mergeable
<InputLong
, Input
, OutputOnlyInt
>);
88 // No indirect strict weak order between I1 and I2 (bad comparison functor).
89 using GoodComp
= bool(*)(int, int);
90 static_assert( std::indirect_strict_weak_order
<GoodComp
, Input
, Input
>);
91 static_assert( std::mergeable
<Input
, Input
, Output
, GoodComp
>);
92 using BadComp
= bool(*)(int*, int*);
93 static_assert(!std::indirect_strict_weak_order
<BadComp
, Input
, Input
>);
94 static_assert(!std::mergeable
<Input
, Input
, Output
, BadComp
>);
96 // No indirect strict weak order between I1 and I2 (bad projection).
97 using ToInt
= int(*)(int);
98 using ToPtr
= int*(*)(int);
99 static_assert( std::mergeable
<Input
, Input
, Output
, GoodComp
, std::identity
, std::identity
>);
100 static_assert( std::mergeable
<Input
, Input
, Output
, GoodComp
, ToInt
, ToInt
>);
101 static_assert(!std::mergeable
<Input
, Input
, Output
, GoodComp
, ToPtr
, ToInt
>);
102 static_assert(!std::mergeable
<Input
, Input
, Output
, GoodComp
, ToInt
, ToPtr
>);
103 static_assert(!std::mergeable
<Input
, Input
, Output
, bool(*)(int*, int), ToPtr
, ToInt
>);
104 static_assert(!std::mergeable
<Input
, Input
, Output
, bool(*)(int, int*), ToInt
, ToPtr
>);
106 // A projection that only supports non-const references and has a non-const `operator()` still has to work.
107 struct ProjectionOnlyMutable
{
108 int operator()(int&);
109 int operator()(int&&) const = delete;
111 static_assert( std::mergeable
<Input
, Input
, Output
, CompDefault
, ProjectionOnlyMutable
, ProjectionOnlyMutable
>);
113 // The output is weakly incrementable but not an output iterator.
114 struct WeaklyIncrementable
{
115 using value_type
= int;
116 using difference_type
= int;
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);
124 static_assert( std::weakly_incrementable
<WeaklyIncrementable
>);
125 static_assert( std::indirectly_copyable
<int*, WeaklyIncrementable
>);
126 static_assert(!std::output_iterator
<WeaklyIncrementable
, int>);
127 static_assert( std::mergeable
<Input
, Input
, WeaklyIncrementable
>);