1//===----------------------------------------------------------------------===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
8// UNSUPPORTED: c++03, c++11, c++14, c++17
9// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
10
11// <format>
12
13// basic_format_arg<Context> get(size_t i) const noexcept;
14
15#include <format>
16#include <cassert>
17#include <type_traits>
18
19#include "test_macros.h"
20#include "make_string.h"
21
22template <class Context, class To, class From>
23void test(From value) {
24 auto store = std::make_format_args<Context>(value);
25 const std::basic_format_args<Context> format_args{store};
26
27 auto visitor = [v = To(value)](auto a) {
28 if constexpr (std::is_same_v<To, decltype(a)>)
29 assert(v == a);
30 else
31 assert(false);
32 };
33#if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
34 format_args.get(0).visit(visitor);
35#else
36 std::visit_format_arg(visitor, format_args.get(0));
37#endif
38}
39
40// Some types, as an extension, are stored in the variant. The Standard
41// requires them to be observed as a handle.
42template <class Context, class T>
43void test_handle(T value) {
44 auto store = std::make_format_args<Context>(value);
45 std::basic_format_args<Context> format_args{store};
46
47 auto visitor = [](auto a) { assert((std::is_same_v<decltype(a), typename std::basic_format_arg<Context>::handle>)); };
48#if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
49 format_args.get(0).visit(visitor);
50#else
51 std::visit_format_arg(visitor, format_args.get(0));
52#endif
53}
54
55// Test specific for string and string_view.
56//
57// Since both result in a string_view there's no need to pass this as a
58// template argument.
59template <class Context, class From>
60void test_string_view(From value) {
61 auto store = std::make_format_args<Context>(value);
62 const std::basic_format_args<Context> format_args{store};
63
64 using CharT = typename Context::char_type;
65 using To = std::basic_string_view<CharT>;
66 using V = std::basic_string<CharT>;
67
68 auto visitor = [v = V(value.begin(), value.end())](auto a) {
69 if constexpr (std::is_same_v<To, decltype(a)>)
70 assert(v == a);
71 else
72 assert(false);
73 };
74#if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
75 format_args.get(0).visit(visitor);
76#else
77 std::visit_format_arg(visitor, format_args.get(0));
78#endif
79}
80
81template <class CharT>
82void test() {
83 using Context = std::basic_format_context<CharT*, CharT>;
84 {
85 const std::basic_format_args<Context> format_args{};
86 ASSERT_NOEXCEPT(format_args.get(0));
87 assert(!format_args.get(0));
88 }
89
90 using char_type = typename Context::char_type;
91 std::basic_string<char_type> empty;
92 std::basic_string<char_type> str = MAKE_STRING(char_type, "abc");
93
94 // Test boolean types.
95
96 test<Context, bool>(true);
97 test<Context, bool>(false);
98
99 // Test char_type types.
100
101 test<Context, char_type, char_type>('a');
102 test<Context, char_type, char_type>('z');
103 test<Context, char_type, char_type>('0');
104 test<Context, char_type, char_type>('9');
105
106 // Test char types.
107
108 if (std::is_same_v<char_type, char>) {
109 // char to char -> char
110 test<Context, char_type, char>('a');
111 test<Context, char_type, char>('z');
112 test<Context, char_type, char>('0');
113 test<Context, char_type, char>('9');
114 } else {
115 if (std::is_same_v<char_type, wchar_t>) {
116 // char to wchar_t -> wchar_t
117 test<Context, wchar_t, char>('a');
118 test<Context, wchar_t, char>('z');
119 test<Context, wchar_t, char>('0');
120 test<Context, wchar_t, char>('9');
121 } else if (std::is_signed_v<char>) {
122 // char to char_type -> int
123 // This happens when Context::char_type is a char8_t, char16_t, or
124 // char32_t and char is a signed type.
125 // Note if sizeof(char_type) > sizeof(int) this test fails. If there are
126 // platforms where that occurs extra tests need to be added for char32_t
127 // testing it against a long long.
128 test<Context, int, char>('a');
129 test<Context, int, char>('z');
130 test<Context, int, char>('0');
131 test<Context, int, char>('9');
132 } else {
133 // char to char_type -> unsigned
134 // This happens when Context::char_type is a char8_t, char16_t, or
135 // char32_t and char is an unsigned type.
136 // Note if sizeof(char_type) > sizeof(unsigned) this test fails. If there
137 // are platforms where that occurs extra tests need to be added for
138 // char32_t testing it against an unsigned long long.
139 test<Context, unsigned, char>('a');
140 test<Context, unsigned, char>('z');
141 test<Context, unsigned, char>('0');
142 test<Context, unsigned, char>('9');
143 }
144 }
145
146 // Test signed integer types.
147
148 test<Context, int, signed char>(std::numeric_limits<signed char>::min());
149 test<Context, int, signed char>(0);
150 test<Context, int, signed char>(std::numeric_limits<signed char>::max());
151
152 test<Context, int, short>(std::numeric_limits<short>::min());
153 test<Context, int, short>(std::numeric_limits<signed char>::min());
154 test<Context, int, short>(0);
155 test<Context, int, short>(std::numeric_limits<signed char>::max());
156 test<Context, int, short>(std::numeric_limits<short>::max());
157
158 test<Context, int, int>(std::numeric_limits<int>::min());
159 test<Context, int, int>(std::numeric_limits<short>::min());
160 test<Context, int, int>(std::numeric_limits<signed char>::min());
161 test<Context, int, int>(0);
162 test<Context, int, int>(std::numeric_limits<signed char>::max());
163 test<Context, int, int>(std::numeric_limits<short>::max());
164 test<Context, int, int>(std::numeric_limits<int>::max());
165
166 using LongToType =
167 std::conditional_t<sizeof(long) == sizeof(int), int, long long>;
168
169 test<Context, LongToType, long>(std::numeric_limits<long>::min());
170 test<Context, LongToType, long>(std::numeric_limits<int>::min());
171 test<Context, LongToType, long>(std::numeric_limits<short>::min());
172 test<Context, LongToType, long>(std::numeric_limits<signed char>::min());
173 test<Context, LongToType, long>(0);
174 test<Context, LongToType, long>(std::numeric_limits<signed char>::max());
175 test<Context, LongToType, long>(std::numeric_limits<short>::max());
176 test<Context, LongToType, long>(std::numeric_limits<int>::max());
177 test<Context, LongToType, long>(std::numeric_limits<long>::max());
178
179 test<Context, long long, long long>(std::numeric_limits<long long>::min());
180 test<Context, long long, long long>(std::numeric_limits<long>::min());
181 test<Context, long long, long long>(std::numeric_limits<int>::min());
182 test<Context, long long, long long>(std::numeric_limits<short>::min());
183 test<Context, long long, long long>(std::numeric_limits<signed char>::min());
184 test<Context, long long, long long>(0);
185 test<Context, long long, long long>(std::numeric_limits<signed char>::max());
186 test<Context, long long, long long>(std::numeric_limits<short>::max());
187 test<Context, long long, long long>(std::numeric_limits<int>::max());
188 test<Context, long long, long long>(std::numeric_limits<long>::max());
189 test<Context, long long, long long>(std::numeric_limits<long long>::max());
190
191#ifndef TEST_HAS_NO_INT128
192 test_handle<Context, __int128_t>(0);
193#endif // TEST_HAS_NO_INT128
194
195 // Test unsigned integer types.
196
197 test<Context, unsigned, unsigned char>(0);
198 test<Context, unsigned, unsigned char>(
199 std::numeric_limits<unsigned char>::max());
200
201 test<Context, unsigned, unsigned short>(0);
202 test<Context, unsigned, unsigned short>(
203 std::numeric_limits<unsigned char>::max());
204 test<Context, unsigned, unsigned short>(
205 std::numeric_limits<unsigned short>::max());
206
207 test<Context, unsigned, unsigned>(0);
208 test<Context, unsigned, unsigned>(std::numeric_limits<unsigned char>::max());
209 test<Context, unsigned, unsigned>(std::numeric_limits<unsigned short>::max());
210 test<Context, unsigned, unsigned>(std::numeric_limits<unsigned>::max());
211
212 using UnsignedLongToType =
213 std::conditional_t<sizeof(unsigned long) == sizeof(unsigned), unsigned,
214 unsigned long long>;
215
216 test<Context, UnsignedLongToType, unsigned long>(0);
217 test<Context, UnsignedLongToType, unsigned long>(
218 std::numeric_limits<unsigned char>::max());
219 test<Context, UnsignedLongToType, unsigned long>(
220 std::numeric_limits<unsigned short>::max());
221 test<Context, UnsignedLongToType, unsigned long>(
222 std::numeric_limits<unsigned>::max());
223 test<Context, UnsignedLongToType, unsigned long>(
224 std::numeric_limits<unsigned long>::max());
225
226 test<Context, unsigned long long, unsigned long long>(0);
227 test<Context, unsigned long long, unsigned long long>(
228 std::numeric_limits<unsigned char>::max());
229 test<Context, unsigned long long, unsigned long long>(
230 std::numeric_limits<unsigned short>::max());
231 test<Context, unsigned long long, unsigned long long>(
232 std::numeric_limits<unsigned>::max());
233 test<Context, unsigned long long, unsigned long long>(
234 std::numeric_limits<unsigned long>::max());
235 test<Context, unsigned long long, unsigned long long>(
236 std::numeric_limits<unsigned long long>::max());
237
238#ifndef TEST_HAS_NO_INT128
239 test_handle<Context, __uint128_t>(0);
240#endif // TEST_HAS_NO_INT128
241
242 // Test floating point types.
243
244 test<Context, float, float>(-std::numeric_limits<float>::max());
245 test<Context, float, float>(-std::numeric_limits<float>::min());
246 test<Context, float, float>(-0.0);
247 test<Context, float, float>(0.0);
248 test<Context, float, float>(std::numeric_limits<float>::min());
249 test<Context, float, float>(std::numeric_limits<float>::max());
250
251 test<Context, double, double>(-std::numeric_limits<double>::max());
252 test<Context, double, double>(-std::numeric_limits<double>::min());
253 test<Context, double, double>(-0.0);
254 test<Context, double, double>(0.0);
255 test<Context, double, double>(std::numeric_limits<double>::min());
256 test<Context, double, double>(std::numeric_limits<double>::max());
257
258 test<Context, long double, long double>(
259 -std::numeric_limits<long double>::max());
260 test<Context, long double, long double>(
261 -std::numeric_limits<long double>::min());
262 test<Context, long double, long double>(-0.0);
263 test<Context, long double, long double>(0.0);
264 test<Context, long double, long double>(
265 std::numeric_limits<long double>::min());
266 test<Context, long double, long double>(
267 std::numeric_limits<long double>::max());
268
269 // Test const char_type pointer types.
270
271 test<Context, const char_type*, const char_type*>(empty.c_str());
272 test<Context, const char_type*, const char_type*>(str.c_str());
273
274 // Test string_view types.
275
276 test<Context, std::basic_string_view<char_type>>(
277 std::basic_string_view<char_type>());
278 test<Context, std::basic_string_view<char_type>,
279 std::basic_string_view<char_type>>(empty);
280 test<Context, std::basic_string_view<char_type>,
281 std::basic_string_view<char_type>>(str);
282
283 // Test string types.
284
285 test<Context, std::basic_string_view<char_type>>(
286 std::basic_string<char_type>());
287 test<Context, std::basic_string_view<char_type>,
288 std::basic_string<char_type>>(empty);
289 test<Context, std::basic_string_view<char_type>,
290 std::basic_string<char_type>>(str);
291
292 // Test pointer types.
293
294 test<Context, const void*>(nullptr);
295}
296
297void test() {
298 test<char>();
299#ifndef TEST_HAS_NO_WIDE_CHARACTERS
300 test<wchar_t>();
301#endif
302}
303
304int main(int, char**) {
305 test();
306
307 return 0;
308}
309

source code of libcxx/test/std/utilities/format/format.arguments/format.args/get.pass.cpp