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, c++20
11 // This test uses std::filesystem::path, which is not always available
12 // XFAIL: availability-filesystem-missing
16 // template<class T, class charT>
17 // concept formattable = ...
28 #include <forward_list>
37 #include <system_error>
39 #include <type_traits>
40 #include <unordered_map>
41 #include <unordered_set>
45 #include "test_macros.h"
46 #include "min_allocator.h"
48 #ifndef TEST_HAS_NO_LOCALIZATION
51 #ifndef TEST_HAS_NO_THREADS
55 template <class T
, class CharT
>
56 void assert_is_not_formattable() {
58 static_assert(!std::formattable
< T
, CharT
>);
59 static_assert(!std::formattable
< T
& , CharT
>);
60 static_assert(!std::formattable
< T
&& , CharT
>);
61 static_assert(!std::formattable
<const T
, CharT
>);
62 static_assert(!std::formattable
<const T
& , CharT
>);
63 static_assert(!std::formattable
<const T
&& , CharT
>);
67 template <class T
, class CharT
>
68 void assert_is_formattable() {
69 // Only formatters for CharT == char || CharT == wchar_t are enabled for the
70 // standard formatters. When CharT is a different type the formatter should
72 if constexpr (std::same_as
<CharT
, char>
73 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
74 || std::same_as
<CharT
, wchar_t>
78 static_assert(std::formattable
< T
, CharT
>);
79 static_assert(std::formattable
< T
& , CharT
>);
80 static_assert(std::formattable
< T
&& , CharT
>);
81 static_assert(std::formattable
<const T
, CharT
>);
82 static_assert(std::formattable
<const T
& , CharT
>);
83 static_assert(std::formattable
<const T
&& , CharT
>);
86 assert_is_not_formattable
<T
, CharT
>();
89 // Tests for P0645 Text Formatting
90 template <class CharT
>
92 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
93 // Tests the special formatter that converts a char to a wchar_t.
94 assert_is_formattable
<char, wchar_t>();
96 assert_is_formattable
<CharT
, CharT
>();
98 assert_is_formattable
<CharT
*, CharT
>();
99 assert_is_formattable
<const CharT
*, CharT
>();
100 assert_is_formattable
<CharT
[42], CharT
>();
101 if constexpr (!std::same_as
<CharT
, int>) { // string and string_view only work with proper character types
102 assert_is_formattable
<std::basic_string
<CharT
>, CharT
>();
103 assert_is_formattable
<std::basic_string_view
<CharT
>, CharT
>();
106 assert_is_formattable
<bool, CharT
>();
108 assert_is_formattable
<signed char, CharT
>();
109 assert_is_formattable
<signed short, CharT
>();
110 assert_is_formattable
<signed int, CharT
>();
111 assert_is_formattable
<signed long, CharT
>();
112 assert_is_formattable
<signed long long, CharT
>();
113 #ifndef TEST_HAS_NO_INT128
114 assert_is_formattable
<__int128_t
, CharT
>();
117 assert_is_formattable
<unsigned char, CharT
>();
118 assert_is_formattable
<unsigned short, CharT
>();
119 assert_is_formattable
<unsigned int, CharT
>();
120 assert_is_formattable
<unsigned long, CharT
>();
121 assert_is_formattable
<unsigned long long, CharT
>();
122 #ifndef TEST_HAS_NO_INT128
123 assert_is_formattable
<__uint128_t
, CharT
>();
126 // floating-point types are tested in concept.formattable.float.compile.pass.cpp
128 assert_is_formattable
<std::nullptr_t
, CharT
>();
129 assert_is_formattable
<void*, CharT
>();
130 assert_is_formattable
<const void*, CharT
>();
133 // Tests for P1361 Integration of chrono with text formatting
135 // Some tests are commented out since these types haven't been implemented in
136 // chrono yet. After P1361 has been implemented these formatters should be all
138 template <class CharT
>
140 // The chrono formatters require localization support.
142 // If the chrono-specs is omitted, the chrono object is formatted as if by
143 // streaming it to std::ostringstream os with the formatting
144 // locale imbued and copying os.str() through the output iterator of the
145 // context with additional padding and adjustments as specified by the format
147 // In libc++ std:::ostringstream requires localization support.
148 #ifndef TEST_HAS_NO_LOCALIZATION
150 assert_is_formattable
<std::chrono::microseconds
, CharT
>();
152 assert_is_formattable
<std::chrono::sys_time
<std::chrono::microseconds
>, CharT
>();
153 //assert_is_formattable<std::chrono::utc_time<std::chrono::microseconds>, CharT>();
154 //assert_is_formattable<std::chrono::tai_time<std::chrono::microseconds>, CharT>();
155 //assert_is_formattable<std::chrono::gps_time<std::chrono::microseconds>, CharT>();
156 assert_is_formattable
<std::chrono::file_time
<std::chrono::microseconds
>, CharT
>();
157 assert_is_formattable
<std::chrono::local_time
<std::chrono::microseconds
>, CharT
>();
159 assert_is_formattable
<std::chrono::day
, CharT
>();
160 assert_is_formattable
<std::chrono::month
, CharT
>();
161 assert_is_formattable
<std::chrono::year
, CharT
>();
163 assert_is_formattable
<std::chrono::weekday
, CharT
>();
164 assert_is_formattable
<std::chrono::weekday_indexed
, CharT
>();
165 assert_is_formattable
<std::chrono::weekday_last
, CharT
>();
167 assert_is_formattable
<std::chrono::month_day
, CharT
>();
168 assert_is_formattable
<std::chrono::month_day_last
, CharT
>();
169 assert_is_formattable
<std::chrono::month_weekday
, CharT
>();
170 assert_is_formattable
<std::chrono::month_weekday_last
, CharT
>();
172 assert_is_formattable
<std::chrono::year_month
, CharT
>();
173 assert_is_formattable
<std::chrono::year_month_day
, CharT
>();
174 assert_is_formattable
<std::chrono::year_month_day_last
, CharT
>();
175 assert_is_formattable
<std::chrono::year_month_weekday
, CharT
>();
176 assert_is_formattable
<std::chrono::year_month_weekday_last
, CharT
>();
178 assert_is_formattable
<std::chrono::hh_mm_ss
<std::chrono::microseconds
>, CharT
>();
180 # if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB)
181 assert_is_formattable
<std::chrono::sys_info
, CharT
>();
182 assert_is_formattable
<std::chrono::local_info
, CharT
>();
184 //assert_is_formattable<std::chrono::zoned_time, CharT>();
185 # endif // !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB)
187 #endif // TEST_HAS_NO_LOCALIZATION
190 // Tests for P1636 Formatters for library types
192 // The paper hasn't been voted in so currently all formatters are disabled.
193 // Note the paper has been abandoned, the types are kept since other papers may
194 // introduce these formatters.
195 template <class CharT
>
197 assert_is_not_formattable
<std::basic_streambuf
<CharT
>, CharT
>();
198 assert_is_not_formattable
<std::bitset
<42>, CharT
>();
199 assert_is_not_formattable
<std::complex<double>, CharT
>();
200 assert_is_not_formattable
<std::error_code
, CharT
>();
201 assert_is_not_formattable
<std::filesystem::path
, CharT
>();
202 assert_is_not_formattable
<std::shared_ptr
<int>, CharT
>();
203 #ifndef TEST_HAS_NO_LOCALIZATION
204 if constexpr (!std::same_as
<CharT
, int>) // sub_match only works with proper character types
205 assert_is_not_formattable
<std::sub_match
<CharT
*>, CharT
>();
207 #ifndef TEST_HAS_NO_THREADS
208 assert_is_formattable
<std::thread::id
, CharT
>();
210 assert_is_not_formattable
<std::unique_ptr
<int>, CharT
>();
213 template <class CharT
, class Vector
>
214 void test_P2286_vector_bool() {
215 assert_is_formattable
<Vector
, CharT
>();
216 assert_is_formattable
<typename
Vector::reference
, CharT
>();
218 // The const_reference shall be a bool.
219 // However libc++ uses a __bit_const_reference<vector> when
220 // _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL is defined.
221 assert_is_formattable
<const Vector
&, CharT
>();
222 assert_is_formattable
<typename
Vector::const_reference
, CharT
>();
225 // Tests for P2286 Formatting ranges
226 template <class CharT
>
228 assert_is_formattable
<std::array
<int, 42>, CharT
>();
229 assert_is_formattable
<std::vector
<int>, CharT
>();
230 assert_is_formattable
<std::deque
<int>, CharT
>();
231 assert_is_formattable
<std::forward_list
<int>, CharT
>();
232 assert_is_formattable
<std::list
<int>, CharT
>();
234 assert_is_formattable
<std::set
<int>, CharT
>();
235 assert_is_formattable
<std::map
<int, int>, CharT
>();
236 assert_is_formattable
<std::multiset
<int>, CharT
>();
237 assert_is_formattable
<std::multimap
<int, int>, CharT
>();
239 assert_is_formattable
<std::unordered_set
<int>, CharT
>();
240 assert_is_formattable
<std::unordered_map
<int, int>, CharT
>();
241 assert_is_formattable
<std::unordered_multiset
<int>, CharT
>();
242 assert_is_formattable
<std::unordered_multimap
<int, int>, CharT
>();
244 assert_is_formattable
<std::stack
<int>, CharT
>();
245 assert_is_formattable
<std::queue
<int>, CharT
>();
246 assert_is_formattable
<std::priority_queue
<int>, CharT
>();
248 assert_is_formattable
<std::span
<int>, CharT
>();
250 assert_is_formattable
<std::valarray
<int>, CharT
>();
252 assert_is_formattable
<std::pair
<int, int>, CharT
>();
253 assert_is_formattable
<std::tuple
<int>, CharT
>();
255 test_P2286_vector_bool
<CharT
, std::vector
<bool>>();
256 test_P2286_vector_bool
<CharT
, std::vector
<bool, std::allocator
<bool>>>();
257 test_P2286_vector_bool
<CharT
, std::vector
<bool, min_allocator
<bool>>>();
260 // Tests volatile qualified objects are no longer formattable.
261 template <class CharT
>
262 void test_LWG3631() {
263 assert_is_not_formattable
<volatile CharT
, CharT
>();
265 assert_is_not_formattable
<volatile bool, CharT
>();
267 assert_is_not_formattable
<volatile signed int, CharT
>();
268 assert_is_not_formattable
<volatile unsigned int, CharT
>();
270 assert_is_not_formattable
<volatile std::chrono::microseconds
, CharT
>();
271 assert_is_not_formattable
<volatile std::chrono::sys_time
<std::chrono::microseconds
>, CharT
>();
272 assert_is_not_formattable
<volatile std::chrono::day
, CharT
>();
274 assert_is_not_formattable
<std::array
<volatile int, 42>, CharT
>();
276 assert_is_not_formattable
<std::pair
<volatile int, int>, CharT
>();
277 assert_is_not_formattable
<std::pair
<int, volatile int>, CharT
>();
278 assert_is_not_formattable
<std::pair
<volatile int, volatile int>, CharT
>();
288 template <class CharT
>
289 void test_disabled() {
290 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
291 assert_is_not_formattable
<const char*, wchar_t>();
293 assert_is_not_formattable
<const char*, char8_t
>();
294 assert_is_not_formattable
<const char*, char16_t
>();
295 assert_is_not_formattable
<const char*, char32_t
>();
297 assert_is_not_formattable
<c
, CharT
>();
298 assert_is_not_formattable
<const c
, CharT
>();
299 assert_is_not_formattable
<volatile c
, CharT
>();
300 assert_is_not_formattable
<const volatile c
, CharT
>();
302 assert_is_not_formattable
<e
, CharT
>();
303 assert_is_not_formattable
<const e
, CharT
>();
304 assert_is_not_formattable
<volatile e
, CharT
>();
305 assert_is_not_formattable
<const volatile e
, CharT
>();
307 assert_is_not_formattable
<ec
, CharT
>();
308 assert_is_not_formattable
<const ec
, CharT
>();
309 assert_is_not_formattable
<volatile ec
, CharT
>();
310 assert_is_not_formattable
<const volatile ec
, CharT
>();
312 assert_is_not_formattable
<int*, CharT
>();
313 assert_is_not_formattable
<const int*, CharT
>();
314 assert_is_not_formattable
<volatile int*, CharT
>();
315 assert_is_not_formattable
<const volatile int*, CharT
>();
317 assert_is_not_formattable
<c
*, CharT
>();
318 assert_is_not_formattable
<const c
*, CharT
>();
319 assert_is_not_formattable
<volatile c
*, CharT
>();
320 assert_is_not_formattable
<const volatile c
*, CharT
>();
322 assert_is_not_formattable
<e
*, CharT
>();
323 assert_is_not_formattable
<const e
*, CharT
>();
324 assert_is_not_formattable
<volatile e
*, CharT
>();
325 assert_is_not_formattable
<const volatile e
*, CharT
>();
327 assert_is_not_formattable
<ec
*, CharT
>();
328 assert_is_not_formattable
<const ec
*, CharT
>();
329 assert_is_not_formattable
<volatile ec
*, CharT
>();
330 assert_is_not_formattable
<const volatile ec
*, CharT
>();
332 assert_is_not_formattable
<void (*)(), CharT
>();
333 assert_is_not_formattable
<void (c::*)(), CharT
>();
334 assert_is_not_formattable
<void (c::*)() const, CharT
>();
336 assert_is_not_formattable
<std::optional
<int>, CharT
>();
337 assert_is_not_formattable
<std::variant
<int>, CharT
>();
339 assert_is_not_formattable
<std::shared_ptr
<c
>, CharT
>();
340 assert_is_not_formattable
<std::unique_ptr
<c
>, CharT
>();
342 assert_is_not_formattable
<std::array
<c
, 42>, CharT
>();
343 assert_is_not_formattable
<std::vector
<c
>, CharT
>();
344 assert_is_not_formattable
<std::deque
<c
>, CharT
>();
345 assert_is_not_formattable
<std::forward_list
<c
>, CharT
>();
346 assert_is_not_formattable
<std::list
<c
>, CharT
>();
348 assert_is_not_formattable
<std::set
<c
>, CharT
>();
349 assert_is_not_formattable
<std::map
<c
, int>, CharT
>();
350 assert_is_not_formattable
<std::multiset
<c
>, CharT
>();
351 assert_is_not_formattable
<std::multimap
<c
, int>, CharT
>();
353 assert_is_not_formattable
<std::unordered_set
<c
>, CharT
>();
354 assert_is_not_formattable
<std::unordered_map
<c
, int>, CharT
>();
355 assert_is_not_formattable
<std::unordered_multiset
<c
>, CharT
>();
356 assert_is_not_formattable
<std::unordered_multimap
<c
, int>, CharT
>();
358 assert_is_not_formattable
<std::stack
<c
>, CharT
>();
359 assert_is_not_formattable
<std::queue
<c
>, CharT
>();
360 assert_is_not_formattable
<std::priority_queue
<c
>, CharT
>();
362 assert_is_not_formattable
<std::span
<c
>, CharT
>();
364 assert_is_not_formattable
<std::valarray
<c
>, CharT
>();
366 assert_is_not_formattable
<std::pair
<c
, int>, CharT
>();
367 assert_is_not_formattable
<std::tuple
<c
>, CharT
>();
369 assert_is_not_formattable
<std::optional
<c
>, CharT
>();
370 assert_is_not_formattable
<std::variant
<c
>, CharT
>();
374 virtual ~abstract() = 0;
377 template <class CharT
>
378 requires
std::same_as
<CharT
, char>
379 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
380 || std::same_as
<CharT
, wchar_t>
382 struct std::formatter
<abstract
, CharT
> {
383 template <class ParseContext
>
384 constexpr typename
ParseContext::iterator
parse(ParseContext
& parse_ctx
) {
385 return parse_ctx
.begin();
388 template <class FormatContext
>
389 typename
FormatContext::iterator
format(const abstract
&, FormatContext
& ctx
) const {
394 template <class CharT
>
395 void test_abstract_class() {
396 assert_is_formattable
<abstract
, CharT
>();
399 template <class CharT
>
405 test_LWG3631
<CharT
>();
406 test_abstract_class
<CharT
>();
407 test_disabled
<CharT
>();
412 #ifndef TEST_HAS_NO_WIDE_CHARACTERS