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, c++20
10
11// This test uses std::filesystem::path, which is not always available
12// XFAIL: availability-filesystem-missing
13
14// <format>
15
16// template<class T, class charT>
17// concept formattable = ...
18
19#include <array>
20#include <bitset>
21#include <bitset>
22#include <chrono>
23#include <complex>
24#include <concepts>
25#include <deque>
26#include <filesystem>
27#include <flat_map>
28#include <format>
29#include <forward_list>
30#include <list>
31#include <map>
32#include <memory>
33#include <optional>
34#include <queue>
35#include <set>
36#include <span>
37#include <stack>
38#include <system_error>
39#include <tuple>
40#include <type_traits>
41#include <unordered_map>
42#include <unordered_set>
43#include <valarray>
44#include <variant>
45
46#include "test_macros.h"
47#include "min_allocator.h"
48
49#ifndef TEST_HAS_NO_LOCALIZATION
50# include <regex>
51#endif
52#ifndef TEST_HAS_NO_THREADS
53# include <thread>
54#endif
55
56template <class T, class CharT>
57void assert_is_not_formattable() {
58 // clang-format off
59 static_assert(!std::formattable< T , CharT>);
60 static_assert(!std::formattable< T& , CharT>);
61 static_assert(!std::formattable< T&& , CharT>);
62 static_assert(!std::formattable<const T , CharT>);
63 static_assert(!std::formattable<const T& , CharT>);
64 static_assert(!std::formattable<const T&& , CharT>);
65 // clang-format on
66}
67
68template <class T, class CharT>
69void assert_is_formattable() {
70 // Only formatters for CharT == char || CharT == wchar_t are enabled for the
71 // standard formatters. When CharT is a different type the formatter should
72 // be disabled.
73 if constexpr (std::same_as<CharT, char>
74#ifndef TEST_HAS_NO_WIDE_CHARACTERS
75 || std::same_as<CharT, wchar_t>
76#endif
77 ) {
78 // clang-format off
79 static_assert(std::formattable< T , CharT>);
80 static_assert(std::formattable< T& , CharT>);
81 static_assert(std::formattable< T&& , CharT>);
82 static_assert(std::formattable<const T , CharT>);
83 static_assert(std::formattable<const T& , CharT>);
84 static_assert(std::formattable<const T&& , CharT>);
85 // clang-format on
86 } else
87 assert_is_not_formattable<T, CharT>();
88}
89
90// Tests for P0645 Text Formatting
91template <class CharT>
92void test_P0645() {
93#ifndef TEST_HAS_NO_WIDE_CHARACTERS
94 // Tests the special formatter that converts a char to a wchar_t.
95 assert_is_formattable<char, wchar_t>();
96#endif
97 assert_is_formattable<CharT, CharT>();
98
99 assert_is_formattable<CharT*, CharT>();
100 assert_is_formattable<const CharT*, CharT>();
101 assert_is_formattable<CharT[42], CharT>();
102 if constexpr (!std::same_as<CharT, int>) { // string and string_view only work with proper character types
103 assert_is_formattable<std::basic_string<CharT>, CharT>();
104 assert_is_formattable<std::basic_string_view<CharT>, CharT>();
105 }
106
107 assert_is_formattable<bool, CharT>();
108
109 assert_is_formattable<signed char, CharT>();
110 assert_is_formattable<signed short, CharT>();
111 assert_is_formattable<signed int, CharT>();
112 assert_is_formattable<signed long, CharT>();
113 assert_is_formattable<signed long long, CharT>();
114#ifndef TEST_HAS_NO_INT128
115 assert_is_formattable<__int128_t, CharT>();
116#endif
117
118 assert_is_formattable<unsigned char, CharT>();
119 assert_is_formattable<unsigned short, CharT>();
120 assert_is_formattable<unsigned int, CharT>();
121 assert_is_formattable<unsigned long, CharT>();
122 assert_is_formattable<unsigned long long, CharT>();
123#ifndef TEST_HAS_NO_INT128
124 assert_is_formattable<__uint128_t, CharT>();
125#endif
126
127 // floating-point types are tested in concept.formattable.float.compile.pass.cpp
128
129 assert_is_formattable<std::nullptr_t, CharT>();
130 assert_is_formattable<void*, CharT>();
131 assert_is_formattable<const void*, CharT>();
132}
133
134// Tests for P1361 Integration of chrono with text formatting
135//
136// Some tests are commented out since these types haven't been implemented in
137// chrono yet. After P1361 has been implemented these formatters should be all
138// enabled.
139template <class CharT>
140void test_P1361() {
141// The chrono formatters require localization support.
142// [time.format]/7
143// If the chrono-specs is omitted, the chrono object is formatted as if by
144// streaming it to std::ostringstream os with the formatting
145// locale imbued and copying os.str() through the output iterator of the
146// context with additional padding and adjustments as specified by the format
147// specifiers.
148// In libc++ std:::ostringstream requires localization support.
149#ifndef TEST_HAS_NO_LOCALIZATION
150
151 assert_is_formattable<std::chrono::microseconds, CharT>();
152
153 assert_is_formattable<std::chrono::sys_time<std::chrono::microseconds>, CharT>();
154# if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) && \
155 !defined(TEST_HAS_NO_FILESYSTEM)
156 assert_is_formattable<std::chrono::utc_time<std::chrono::microseconds>, CharT>();
157 assert_is_formattable<std::chrono::tai_time<std::chrono::microseconds>, CharT>();
158 assert_is_formattable<std::chrono::gps_time<std::chrono::microseconds>, CharT>();
159
160# endif // !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&
161 // !defined(TEST_HAS_NO_FILESYSTEM)
162
163 assert_is_formattable<std::chrono::file_time<std::chrono::microseconds>, CharT>();
164 assert_is_formattable<std::chrono::local_time<std::chrono::microseconds>, CharT>();
165
166 assert_is_formattable<std::chrono::day, CharT>();
167 assert_is_formattable<std::chrono::month, CharT>();
168 assert_is_formattable<std::chrono::year, CharT>();
169
170 assert_is_formattable<std::chrono::weekday, CharT>();
171 assert_is_formattable<std::chrono::weekday_indexed, CharT>();
172 assert_is_formattable<std::chrono::weekday_last, CharT>();
173
174 assert_is_formattable<std::chrono::month_day, CharT>();
175 assert_is_formattable<std::chrono::month_day_last, CharT>();
176 assert_is_formattable<std::chrono::month_weekday, CharT>();
177 assert_is_formattable<std::chrono::month_weekday_last, CharT>();
178
179 assert_is_formattable<std::chrono::year_month, CharT>();
180 assert_is_formattable<std::chrono::year_month_day, CharT>();
181 assert_is_formattable<std::chrono::year_month_day_last, CharT>();
182 assert_is_formattable<std::chrono::year_month_weekday, CharT>();
183 assert_is_formattable<std::chrono::year_month_weekday_last, CharT>();
184
185 assert_is_formattable<std::chrono::hh_mm_ss<std::chrono::microseconds>, CharT>();
186
187# if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB)
188 assert_is_formattable<std::chrono::sys_info, CharT>();
189 assert_is_formattable<std::chrono::local_info, CharT>();
190
191# if !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) && !defined(TEST_HAS_NO_FILESYSTEM)
192 assert_is_formattable<std::chrono::zoned_time<std::chrono::microseconds>, CharT>();
193# endif // !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) && !defined(TEST_HAS_NO_FILESYSTEM)
194# endif // !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB)
195
196#endif // TEST_HAS_NO_LOCALIZATION
197}
198
199// Tests for P1636 Formatters for library types
200//
201// The paper hasn't been voted in so currently all formatters are disabled.
202// Note the paper has been abandoned, the types are kept since other papers may
203// introduce these formatters.
204template <class CharT>
205void test_P1636() {
206 assert_is_not_formattable<std::basic_streambuf<CharT>, CharT>();
207 assert_is_not_formattable<std::bitset<42>, CharT>();
208 assert_is_not_formattable<std::complex<double>, CharT>();
209 assert_is_not_formattable<std::error_code, CharT>();
210 assert_is_not_formattable<std::filesystem::path, CharT>();
211 assert_is_not_formattable<std::shared_ptr<int>, CharT>();
212#ifndef TEST_HAS_NO_LOCALIZATION
213 if constexpr (!std::same_as<CharT, int>) // sub_match only works with proper character types
214 assert_is_not_formattable<std::sub_match<CharT*>, CharT>();
215#endif
216#ifndef TEST_HAS_NO_THREADS
217 assert_is_formattable<std::thread::id, CharT>();
218#endif
219 assert_is_not_formattable<std::unique_ptr<int>, CharT>();
220}
221
222template <class CharT, class Vector>
223void test_P2286_vector_bool() {
224 assert_is_formattable<Vector, CharT>();
225 assert_is_formattable<typename Vector::reference, CharT>();
226
227 // The const_reference shall be a bool.
228 // However libc++ uses a __bit_const_reference<vector> when
229 // _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL is defined.
230 assert_is_formattable<const Vector&, CharT>();
231 assert_is_formattable<typename Vector::const_reference, CharT>();
232}
233
234// Tests for P2286 Formatting ranges
235template <class CharT>
236void test_P2286() {
237 assert_is_formattable<std::array<int, 42>, CharT>();
238 assert_is_formattable<std::vector<int>, CharT>();
239 assert_is_formattable<std::deque<int>, CharT>();
240 assert_is_formattable<std::forward_list<int>, CharT>();
241 assert_is_formattable<std::list<int>, CharT>();
242
243 assert_is_formattable<std::set<int>, CharT>();
244 assert_is_formattable<std::map<int, int>, CharT>();
245 assert_is_formattable<std::multiset<int>, CharT>();
246 assert_is_formattable<std::multimap<int, int>, CharT>();
247
248#if TEST_STD_VER >= 23
249 // assert_is_formattable<std::flat_set<int>, CharT>();
250 assert_is_formattable<std::flat_map<int, int>, CharT>();
251 // assert_is_formattable<std::flat_multiset<int>, CharT>();
252 assert_is_formattable<std::flat_multimap<int, int>, CharT>();
253#endif // TEST_STD_VER >= 2
254
255 assert_is_formattable<std::unordered_set<int>, CharT>();
256 assert_is_formattable<std::unordered_map<int, int>, CharT>();
257 assert_is_formattable<std::unordered_multiset<int>, CharT>();
258 assert_is_formattable<std::unordered_multimap<int, int>, CharT>();
259
260 assert_is_formattable<std::stack<int>, CharT>();
261 assert_is_formattable<std::queue<int>, CharT>();
262 assert_is_formattable<std::priority_queue<int>, CharT>();
263
264 assert_is_formattable<std::span<int>, CharT>();
265
266 assert_is_formattable<std::valarray<int>, CharT>();
267
268 assert_is_formattable<std::pair<int, int>, CharT>();
269 assert_is_formattable<std::tuple<int>, CharT>();
270
271 test_P2286_vector_bool<CharT, std::vector<bool>>();
272 test_P2286_vector_bool<CharT, std::vector<bool, std::allocator<bool>>>();
273 test_P2286_vector_bool<CharT, std::vector<bool, min_allocator<bool>>>();
274}
275
276// Tests volatile qualified objects are no longer formattable.
277template <class CharT>
278void test_LWG3631() {
279 assert_is_not_formattable<volatile CharT, CharT>();
280
281 assert_is_not_formattable<volatile bool, CharT>();
282
283 assert_is_not_formattable<volatile signed int, CharT>();
284 assert_is_not_formattable<volatile unsigned int, CharT>();
285
286 assert_is_not_formattable<volatile std::chrono::microseconds, CharT>();
287 assert_is_not_formattable<volatile std::chrono::sys_time<std::chrono::microseconds>, CharT>();
288 assert_is_not_formattable<volatile std::chrono::day, CharT>();
289
290 assert_is_not_formattable<std::array<volatile int, 42>, CharT>();
291
292 assert_is_not_formattable<std::pair<volatile int, int>, CharT>();
293 assert_is_not_formattable<std::pair<int, volatile int>, CharT>();
294 assert_is_not_formattable<std::pair<volatile int, volatile int>, CharT>();
295}
296
297void test_LWG3944() {
298#ifndef TEST_HAS_NO_WIDE_CHARACTERS
299 assert_is_not_formattable<char*, wchar_t>();
300 assert_is_not_formattable<const char*, wchar_t>();
301 assert_is_not_formattable<char[42], wchar_t>();
302 assert_is_not_formattable<std::string, wchar_t>();
303 assert_is_not_formattable<std::string_view, wchar_t>();
304
305 assert_is_formattable<std::vector<char>, wchar_t>();
306 assert_is_formattable<std::set<char>, wchar_t>();
307 assert_is_formattable<std::map<char, char>, wchar_t>();
308 assert_is_formattable<std::tuple<char>, wchar_t>();
309#endif
310}
311
312class c {
313 void f();
314 void fc() const;
315 static void sf();
316};
317enum e { a };
318enum class ec { a };
319template <class CharT>
320void test_disabled() {
321#ifndef TEST_HAS_NO_WIDE_CHARACTERS
322 assert_is_not_formattable<const char*, wchar_t>();
323#endif
324 assert_is_not_formattable<const char*, char8_t>();
325 assert_is_not_formattable<const char*, char16_t>();
326 assert_is_not_formattable<const char*, char32_t>();
327
328 assert_is_not_formattable<c, CharT>();
329 assert_is_not_formattable<const c, CharT>();
330 assert_is_not_formattable<volatile c, CharT>();
331 assert_is_not_formattable<const volatile c, CharT>();
332
333 assert_is_not_formattable<e, CharT>();
334 assert_is_not_formattable<const e, CharT>();
335 assert_is_not_formattable<volatile e, CharT>();
336 assert_is_not_formattable<const volatile e, CharT>();
337
338 assert_is_not_formattable<ec, CharT>();
339 assert_is_not_formattable<const ec, CharT>();
340 assert_is_not_formattable<volatile ec, CharT>();
341 assert_is_not_formattable<const volatile ec, CharT>();
342
343 assert_is_not_formattable<int*, CharT>();
344 assert_is_not_formattable<const int*, CharT>();
345 assert_is_not_formattable<volatile int*, CharT>();
346 assert_is_not_formattable<const volatile int*, CharT>();
347
348 assert_is_not_formattable<c*, CharT>();
349 assert_is_not_formattable<const c*, CharT>();
350 assert_is_not_formattable<volatile c*, CharT>();
351 assert_is_not_formattable<const volatile c*, CharT>();
352
353 assert_is_not_formattable<e*, CharT>();
354 assert_is_not_formattable<const e*, CharT>();
355 assert_is_not_formattable<volatile e*, CharT>();
356 assert_is_not_formattable<const volatile e*, CharT>();
357
358 assert_is_not_formattable<ec*, CharT>();
359 assert_is_not_formattable<const ec*, CharT>();
360 assert_is_not_formattable<volatile ec*, CharT>();
361 assert_is_not_formattable<const volatile ec*, CharT>();
362
363 assert_is_not_formattable<void (*)(), CharT>();
364 assert_is_not_formattable<void (c::*)(), CharT>();
365 assert_is_not_formattable<void (c::*)() const, CharT>();
366
367 assert_is_not_formattable<std::optional<int>, CharT>();
368 assert_is_not_formattable<std::variant<int>, CharT>();
369
370 assert_is_not_formattable<std::shared_ptr<c>, CharT>();
371 assert_is_not_formattable<std::unique_ptr<c>, CharT>();
372
373 assert_is_not_formattable<std::array<c, 42>, CharT>();
374 assert_is_not_formattable<std::vector<c>, CharT>();
375 assert_is_not_formattable<std::deque<c>, CharT>();
376 assert_is_not_formattable<std::forward_list<c>, CharT>();
377 assert_is_not_formattable<std::list<c>, CharT>();
378
379 assert_is_not_formattable<std::set<c>, CharT>();
380 assert_is_not_formattable<std::map<c, int>, CharT>();
381 assert_is_not_formattable<std::multiset<c>, CharT>();
382 assert_is_not_formattable<std::multimap<c, int>, CharT>();
383
384 assert_is_not_formattable<std::unordered_set<c>, CharT>();
385 assert_is_not_formattable<std::unordered_map<c, int>, CharT>();
386 assert_is_not_formattable<std::unordered_multiset<c>, CharT>();
387 assert_is_not_formattable<std::unordered_multimap<c, int>, CharT>();
388
389 assert_is_not_formattable<std::stack<c>, CharT>();
390 assert_is_not_formattable<std::queue<c>, CharT>();
391 assert_is_not_formattable<std::priority_queue<c>, CharT>();
392
393 assert_is_not_formattable<std::span<c>, CharT>();
394
395 assert_is_not_formattable<std::valarray<c>, CharT>();
396
397 assert_is_not_formattable<std::pair<c, int>, CharT>();
398 assert_is_not_formattable<std::tuple<c>, CharT>();
399
400 assert_is_not_formattable<std::optional<c>, CharT>();
401 assert_is_not_formattable<std::variant<c>, CharT>();
402}
403
404struct abstract {
405 virtual ~abstract() = 0;
406};
407
408template <class CharT>
409 requires std::same_as<CharT, char>
410#ifndef TEST_HAS_NO_WIDE_CHARACTERS
411 || std::same_as<CharT, wchar_t>
412#endif
413struct std::formatter<abstract, CharT> {
414 template <class ParseContext>
415 constexpr typename ParseContext::iterator parse(ParseContext& parse_ctx) {
416 return parse_ctx.begin();
417 }
418
419 template <class FormatContext>
420 typename FormatContext::iterator format(const abstract&, FormatContext& ctx) const {
421 return ctx.out();
422 }
423};
424
425template <class CharT>
426void test_abstract_class() {
427 assert_is_formattable<abstract, CharT>();
428}
429
430template <class CharT>
431void test() {
432 test_P0645<CharT>();
433 test_P1361<CharT>();
434 test_P1636<CharT>();
435 test_P2286<CharT>();
436 test_LWG3631<CharT>();
437 test_LWG3944();
438 test_abstract_class<CharT>();
439 test_disabled<CharT>();
440}
441
442void test() {
443 test<char>();
444#ifndef TEST_HAS_NO_WIDE_CHARACTERS
445 test<wchar_t>();
446#endif
447 test<char8_t>();
448 test<char16_t>();
449 test<char32_t>();
450}
451

source code of libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp