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

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