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
10 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
14 // basic_format_arg<Context> get(size_t i) const noexcept;
19 #include <type_traits>
21 #include "test_macros.h"
22 #include "make_string.h"
24 template <class Context
, class To
, class From
>
25 void test(From value
) {
26 auto store
= std::make_format_args
<Context
>(value
);
27 const std::basic_format_args
<Context
> format_args
{store
};
29 auto visitor
= [v
= To(value
)](auto a
) {
30 if constexpr (std::is_same_v
<To
, decltype(a
)>)
35 #if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
36 format_args
.get(0).visit(visitor
);
38 std::visit_format_arg(visitor
, format_args
.get(0));
42 // Some types, as an extension, are stored in the variant. The Standard
43 // requires them to be observed as a handle.
44 template <class Context
, class T
>
45 void test_handle(T value
) {
46 auto store
= std::make_format_args
<Context
>(value
);
47 std::basic_format_args
<Context
> format_args
{store
};
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
);
53 std::visit_format_arg(visitor
, format_args
.get(0));
57 // Test specific for string and string_view.
59 // Since both result in a string_view there's no need to pass this as a
61 template <class Context
, class From
>
62 void test_string_view(From value
) {
63 auto store
= std::make_format_args
<Context
>(value
);
64 const std::basic_format_args
<Context
> format_args
{store
};
66 using CharT
= typename
Context::char_type
;
67 using To
= std::basic_string_view
<CharT
>;
68 using V
= std::basic_string
<CharT
>;
70 auto visitor
= [v
= V(value
.begin(), value
.end())](auto a
) {
71 if constexpr (std::is_same_v
<To
, decltype(a
)>)
76 #if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER)
77 format_args
.get(0).visit(visitor
);
79 std::visit_format_arg(visitor
, format_args
.get(0));
83 template <class CharT
>
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");
90 // Test boolean types.
92 test
<Context
, bool>(true);
93 test
<Context
, bool>(false);
95 // Test char_type types.
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');
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');
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');
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');
142 // Test signed integer types.
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());
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());
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());
163 std::conditional_t
<sizeof(long) == sizeof(int), int, long long>;
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());
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());
187 #ifndef TEST_HAS_NO_INT128
188 test_handle
<Context
, __int128_t
>(0);
189 #endif // TEST_HAS_NO_INT128
191 // Test unsigned integer types.
193 test
<Context
, unsigned, unsigned char>(0);
194 test
<Context
, unsigned, unsigned char>(
195 std::numeric_limits
<unsigned char>::max());
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());
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());
208 using UnsignedLongToType
=
209 std::conditional_t
<sizeof(unsigned long) == sizeof(unsigned), unsigned,
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());
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());
234 #ifndef TEST_HAS_NO_INT128
235 test_handle
<Context
, __uint128_t
>(0);
236 #endif // TEST_HAS_NO_INT128
238 // Test floating point types.
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());
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());
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());
265 // Test const char_type pointer types.
267 test
<Context
, const char_type
*, const char_type
*>(empty
.c_str());
268 test
<Context
, const char_type
*, const char_type
*>(str
.c_str());
270 // Test string_view types.
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
);
279 // Test string types.
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
);
288 // Test pointer types.
290 test
<Context
, const void*>(nullptr);
295 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
300 int main(int, char**) {