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

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