]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/24_iterators/range_operations/100768.cc
libstdc++: Change [range.iter.op] functions to function objects [PR 100768]
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 24_iterators / range_operations / 100768.cc
CommitLineData
a49a045b
JW
1// Copyright (C) 2021 Free Software Foundation, Inc.
2//
3// This file is part of the GNU ISO C++ Library. This library is free
4// software; you can redistribute it and/or modify it under the
5// terms of the GNU General Public License as published by the
6// Free Software Foundation; either version 3, or (at your option)
7// any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License along
15// with this library; see the file COPYING3. If not see
16// <http://www.gnu.org/licenses/>.
17
18// { dg-options "-std=gnu++20" }
19// { dg-do compile { target c++20 } }
20
21// PR libstdc++/100768 - Range iterator operations should be function objects
22
23#include <iterator>
24#include <ranges>
25
26namespace ns1
27{
28 struct R { };
29 void check_adl(R) { }
30}
31
32namespace ns2
33{
34 using ns1::R;
35
36 struct A { };
37
38 template<typename I>
39 R advance(I, ...) { return R{}; }
40
41 template<typename I>
42 R distance(I, ...) { return R{}; }
43
44 template<typename I>
45 R next(I, ...) { return R{}; }
46
47 template<typename I>
48 R prev(I, ...) { return R{}; }
49}
50
51template<typename T, typename U> struct associated { };
52
53void
54test02()
55{
56 // This type has both ns2 and std::ranges as associated namespaces.
57 using X = associated<ns2::A, std::ranges::dangling>;
58
59 X range[1];
60 X* iter = range;
61 X* const sentinel = iter + 1;
62
63 // [range.iter.op.general] p2 says: "The function templates defined in
64 // [range.iter.ops] are not found by argument-dependent name lookup."
65 //
66 // If we do not meet that requirement then the following will find those
67 // function templates (because std::ranges is an associated namespace),
68 // and the calls to check_adl will be ill-formed.
69 check_adl( advance(iter, 1) );
70 check_adl( advance(iter, 1, sentinel) );
71 check_adl( distance(iter, sentinel) );
72 check_adl( distance(range) );
73 check_adl( next(iter) );
74 check_adl( next(iter, 1) );
75 check_adl( next(iter, sentinel) );
76 check_adl( next(iter, 1, sentinel) );
77 check_adl( prev(iter) );
78 check_adl( prev(iter, 1) );
79 check_adl( prev(iter, 1, sentinel) );
80}
81
82namespace ns3
83{
84 struct A { };
85
86 void advance(A*, int) = delete;
87 void advance(A*, int, A*) = delete;
88
89 void distance(A*, A*) = delete;
90 void distance(A(&)[1]) = delete;
91
92 void next(A*) = delete;
93 void next(A*, int) = delete;
94 void next(A*, A*) = delete;
95 void next(A*, int, A*) = delete;
96
97 void prev(A*) = delete;
98 void prev(A*, int) = delete;
99 void prev(A*, int, A*) = delete;
100}
101
102void
103test01()
104{
105 ns3::A range[1];
106 ns3::A* iter = range;
107 ns3::A* const sentinel = iter + 1;
108
109 // [range.iter.op.general] p2 also says: "When found by unqualified name
110 // lookup for the postfix-expression in a function call, they inhibit
111 // argument-dependent name lookup."
112 //
113 // If we do not meet that requirement then the following will find the
114 // deleted overloads in namespace ns3 (because it is an associated namespace
115 // and those functions are exact matches for the arguments).
116 using namespace std::ranges;
117 advance(iter, 1);
118 advance(iter, 3, sentinel);
119 distance(iter, sentinel);
120 distance(range);
121 next(iter);
122 next(iter, -1);
123 next(iter, sentinel);
124 next(iter, 5, sentinel);
125 prev(iter);
126 prev(iter, 0);
127 prev(iter, 0, sentinel);
128}