1 // Copyright (C) 2019-2024 Free Software Foundation, Inc.
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)
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.
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/>.
18 // { dg-do compile { target c++20 } }
25 concept has_inc_traits_type
26 = requires
{ typename
std::incrementable_traits
<T
>::difference_type
; };
28 // Check std::incrementable_traits<T>::difference_type is U (or doesn't exist).
29 template<typename T
, typename U
>
30 concept check_inc_traits
= (has_inc_traits_type
<T
> != std::same_as
<U
, none
>);
32 static_assert( check_inc_traits
<void, none
> );
33 static_assert( check_inc_traits
<const void, none
> );
34 static_assert( check_inc_traits
<void*, none
> );
35 static_assert( check_inc_traits
<const void*, none
> );
37 static_assert( check_inc_traits
<int, int> );
38 static_assert( check_inc_traits
<const int, int> );
40 static_assert( check_inc_traits
<int*, std::ptrdiff_t> );
41 static_assert( check_inc_traits
<const int*, std::ptrdiff_t> );
42 static_assert( check_inc_traits
<int[2], std::ptrdiff_t> );
43 static_assert( check_inc_traits
<const int[2], std::ptrdiff_t> );
45 struct A
{ using difference_type
= int; };
46 static_assert( check_inc_traits
<A
, int> );
47 static_assert( check_inc_traits
<const A
, int> );
48 struct B
: private A
{ };
49 static_assert( check_inc_traits
<B
, none
> );
52 short operator-(C
, C
) { return 0; }
53 static_assert( check_inc_traits
<C
, short> );
54 static_assert( check_inc_traits
<const C
, short> );
57 unsigned short operator-(D
, D
) { return 0; }
58 static_assert( check_inc_traits
<D
, short> );
59 static_assert( check_inc_traits
<const D
, short> );
63 struct std::incrementable_traits
<E
> { using difference_type
= long; };
64 static_assert( check_inc_traits
<E
, long> );
65 static_assert( check_inc_traits
<const E
, long> );
68 concept has_alias
= requires
{ typename
std::iter_difference_t
<T
>; };
70 // Check std::iter_difference_t<T> is U (or doesn't exist).
71 template<typename T
, typename U
>
72 concept check_alias
= (has_alias
<T
> != std::same_as
<U
, none
>);
74 static_assert( check_alias
<void, none
> );
75 static_assert( check_alias
<const void, none
> );
76 static_assert( check_alias
<void*, none
> );
77 static_assert( check_alias
<const void*, none
> );
79 static_assert( check_alias
<int, int> );
80 static_assert( check_alias
<const int, int> );
81 static_assert( check_alias
<int*, std::ptrdiff_t> );
82 static_assert( check_alias
<const int*, std::ptrdiff_t> );
83 static_assert( check_alias
<int[2], std::ptrdiff_t> );
84 static_assert( check_alias
<const int[2], std::ptrdiff_t> );
86 static_assert( check_alias
<A
, int> );
87 static_assert( check_alias
<const A
, int> );
88 static_assert( check_alias
<B
, none
> );
89 static_assert( check_alias
<C
, short> );
90 static_assert( check_alias
<const C
, short> );
91 static_assert( check_alias
<D
, short> );
92 static_assert( check_alias
<const D
, short> );
93 static_assert( check_alias
<E
, long> );
94 static_assert( check_alias
<const E
, long> );
98 struct std::iterator_traits
<F
> { using difference_type
= F
; };
99 // iterator_traits<F> is specialized, so use its difference_type.
100 static_assert( check_alias
<F
, std::iterator_traits
<F
>::difference_type
> );
104 struct std::incrementable_traits
<G
> { using difference_type
= G
; };
106 struct std::iterator_traits
<G
> { using difference_type
= int; };
107 // iterator_traits<G> is specialized, so use its difference_type.
108 static_assert( check_alias
<G
, std::iterator_traits
<G
>::difference_type
> );
112 struct std::incrementable_traits
<H
> { using difference_type
= H
; };
114 struct std::iterator_traits
<H
>
116 using iterator_category
= input_iterator_tag
;
117 using difference_type
= int;
118 using value_type
= char;
119 using reference
= value_type
&;
121 // iterator_traits<H> is specialized, so use its difference_type.
122 static_assert( check_alias
<H
, std::iterator_traits
<H
>::difference_type
> );
126 using difference_type
= I
;
128 // iterator_traits<I> is not specialized, and no standard specialization
129 // matches, so use incrementable_traits.
130 static_assert( check_alias
<I
, std::incrementable_traits
<I
>::difference_type
> );
134 using iterator_category
= std::input_iterator_tag
;
135 using difference_type
= int;
136 using value_type
= char;
137 using reference
= value_type
&;
139 // iterator_traits<J> matches constrained specialization in the library,
140 // so use its difference_type.
141 static_assert( check_alias
<J
, int> );