BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslfmt_formatterbase.h
Go to the documentation of this file.
1/// @file bslfmt_formatterbase.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslfmt_formatterbase.h -*-C++-*-
8#ifndef INCLUDED_BSLFMT_FORMATTERBASE
9#define INCLUDED_BSLFMT_FORMATTERBASE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslfmt_formatterbase bslfmt_formatterbase
15/// @brief Provide a base template for formatter specializations.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslfmt
19/// @{
20/// @addtogroup bslfmt_formatterbase
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslfmt_formatterbase-purpose"> Purpose</a>
25/// * <a href="#bslfmt_formatterbase-classes"> Classes </a>
26/// * <a href="#bslfmt_formatterbase-canonical-header"> Canonical Header </a>
27/// * <a href="#bslfmt_formatterbase-description"> Description </a>
28/// * <a href="#bslfmt_formatterbase-user-provided-formatters"> User-provided Formatters </a>
29/// * <a href="#bslfmt_formatterbase-usage"> Usage </a>
30/// * <a href="#bslfmt_formatterbase-example-1-creating-custom-formatter-for-user-type"> Example 1: Creating Custom Formatter For User Type </a>
31///
32/// # Purpose {#bslfmt_formatterbase-purpose}
33/// Provide a base template for formatter specializations.
34///
35/// # Classes {#bslfmt_formatterbase-classes}
36///
37/// - bsl::formatter: standard-compliant formatter base template
38///
39/// # Canonical Header {#bslfmt_formatterbase-canonical-header}
40/// bsl_format.h
41///
42/// # Description {#bslfmt_formatterbase-description}
43/// This component provides a base template of the C++20 Standard
44/// Library's `formatter`, which is a customization point for user defined
45/// types seeking to use the formatting library.
46///
47/// It also provides a mechanism, when the standard library `<format>` header is
48/// available, to forward those partial specializations to the `std` namespace
49/// to enable use of `std::format` as well as `bsl::format`.
50///
51/// This header is not intended to be included directly. Please include
52/// `<bsl_format.h>` to be able to use specializations of `bsl::formatter`.
53///
54/// ## User-provided Formatters {#bslfmt_formatterbase-user-provided-formatters}
55///
56///
57/// User-provided formatters are supported by the BSL implementation, just as
58/// they are by the standard library implementation. However, in order for them
59/// to be compatible with both implementations, there are specific requirements,
60/// notably:
61/// * The formatter for a user defined type `T`, should be declared in the same
62/// component header in which this type is declared to avoid issues due to
63/// users forgetting to include the header for the formatter.
64/// * Formatter must be defined in the namespace `bsl`, not `std`.
65/// * Template arguments must be used for the format and parse context
66/// parameters. This is essential as the parameter type passed in might
67/// depend upon underlying implementation.
68/// * The `parse` function should be constexpr in C++20, but this is not
69/// required (and may not be possible) for earlier C++ standards.
70///
71/// ## Usage {#bslfmt_formatterbase-usage}
72///
73///
74/// This section illustrates intended use of this component.
75///
76/// ### Example 1: Creating Custom Formatter For User Type {#bslfmt_formatterbase-example-1-creating-custom-formatter-for-user-type}
77///
78///
79/// Suppose we have a custom type representing a date. And we want to output it
80/// to the stream in different formats depending on the circumstances using
81/// `bsl::format` function. The following example shows how this can be done.
82///
83/// First, we define our `Date` class:
84/// @code
85/// /// This class implements a complex-constrained, value-semantic type for
86/// /// representing dates. Each object of this class *always* represents a
87/// /// *valid* date value in the range `[0001JAN01 .. 9999DEC31]` inclusive.
88/// class Date {
89/// private:
90/// // DATA
91/// int d_year; // year
92/// int d_month; // month
93/// int d_day; // day
94///
95/// public:
96/// // CREATORS
97///
98/// /// Create an object having the value represented by the specified
99/// /// `year`, `month`, and `day`.
100/// Date(int year, int month, int day);
101///
102/// // ACCESSORS
103///
104/// /// Return the year of this date.
105/// int year() const;
106///
107/// /// Return the month of this date.
108/// int month() const;
109///
110/// /// Return the day of this date.
111/// int day() const;
112/// };
113/// @endcode
114/// Now, we define `formatter` specialization for the `Date` and in particular
115/// `parse()` and `format()` functions which will be called by `bsl::format`.
116/// Note that specialization must be defined in the namespace `bsl`.
117/// @code
118/// namespace bsl {
119///
120/// template <class t_CHAR>
121/// struct formatter<Date, t_CHAR> {
122/// // MANIPULATORS
123///
124/// /// Parse the specified `parseContext` and return an iterator, pointing
125/// /// to the beginning of the format string.
126/// template <class t_PARSE_CONTEXT>
127/// BSLS_KEYWORD_CONSTEXPR_CPP20 typename t_PARSE_CONTEXT::iterator parse(
128/// t_PARSE_CONTEXT& parseContext);
129///
130/// // ACCESSORS
131///
132/// /// Create string representation of the specified `value`, customized
133/// /// in accordance with the requested format and the specified
134/// /// `formatContext`, and copy it to the output that the output iterator
135/// /// of the `formatContext` points to.
136/// template <class t_FORMAT_CONTEXT>
137/// typename t_FORMAT_CONTEXT::iterator format(
138/// Date value,
139/// t_FORMAT_CONTEXT& formatContext) const;
140/// };
141///
142/// } // close namespace bsl
143/// @endcode
144/// Unfortunately, due to the position of this component in the class hierarchy,
145/// a full-fledged example would require duplicating a huge amount of code. A
146/// complete example of a custom formatter implementation can be found in the
147/// @ref bslfmt_format component.
148/// @}
149/** @} */
150/** @} */
151
152/** @addtogroup bsl
153 * @{
154 */
155/** @addtogroup bslfmt
156 * @{
157 */
158/** @addtogroup bslfmt_formatterbase
159 * @{
160 */
161
162#include <bslscm_version.h>
163
165
167#include <bsls_keyword.h>
168#include <bsls_libraryfeatures.h>
169
170#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT
171 #include <chrono>
172 #include <concepts>
173 #include <format>
174 #include <string>
175 #include <string_view>
176#endif
177
178#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT
179
180namespace bslfmt {
181
182/// Simple trait type that tells is `t_TYPE` is an instance of
183/// `std::basic_string`.
184///
185/// See @ref bslfmt_formatterbase
186template <class t_TYPE>
187struct FormatterBase_IsStdBasicString {
188 static const bool value = false;
189};
190
191template <class t_CHAR, class t_TRAITS, class t_ALLOCATOR>
192struct FormatterBase_IsStdBasicString<
193 std::basic_string<t_CHAR, t_TRAITS, t_ALLOCATOR> > {
194 static const bool value = true;
195};
196
197/// Simple trait type that tells is `t_TYPE` is an instance of
198/// `std::basic_string_view`.
199///
200/// See @ref bslfmt_formatterbase
201template <class t_TYPE>
202struct FormatterBase_IsStdBasicStringView {
203 static const bool value = false;
204};
205
206template <class t_CHAR, class t_TRAITS>
207struct FormatterBase_IsStdBasicStringView<
208 std::basic_string_view<t_CHAR, t_TRAITS> > {
209 static const bool value = true;
210};
211
212/// Simple trait type that tells is `t_TYPE` is an instance of
213/// `std::chrono::duration`.
214///
215/// See @ref bslfmt_formatterbase
216template <class t_TYPE>
217struct FormatterBase_IsStdChronoDuration {
218 static const bool value = false;
219};
220
221template <class t_REP, class t_PERIOD>
222struct FormatterBase_IsStdChronoDuration<
223 std::chrono::duration<t_REP, t_PERIOD> > {
224 static const bool value = true;
225};
226
227#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_CALENDAR
228/// Simple trait type that tells is `t_TYPE` is an instance of
229/// `std::chrono::sys_time`.
230///
231/// See @ref bslfmt_formatterbase
232template <class t_TYPE>
233struct FormatterBase_IsStdChronoSysTime {
234 static const bool value = false;
235};
236
237template <class t_DURATION>
238struct FormatterBase_IsStdChronoSysTime<
239 std::chrono::sys_time<t_DURATION> > {
240 static const bool value = true;
241};
242
243/// Simple trait type that tells is `t_TYPE` is an instance of
244/// `std::chrono::utc_time`.
245///
246/// See @ref bslfmt_formatterbase
247template <class t_TYPE>
248struct FormatterBase_IsStdChronoUtcTime {
249 static const bool value = false;
250};
251
252template <class t_DURATION>
253struct FormatterBase_IsStdChronoUtcTime<
254 std::chrono::utc_time<t_DURATION> > {
255 static const bool value = true;
256};
257
258/// Simple trait type that tells is `t_TYPE` is an instance of
259/// `std::chrono::tai_time`.
260///
261/// See @ref bslfmt_formatterbase
262template <class t_TYPE>
263struct FormatterBase_IsStdChronoTaiTime {
264 static const bool value = false;
265};
266
267template <class t_DURATION>
268struct FormatterBase_IsStdChronoTaiTime<
269 std::chrono::tai_time<t_DURATION> > {
270 static const bool value = true;
271};
272
273/// Simple trait type that tells is `t_TYPE` is an instance of
274/// `std::chrono::gps_time`.
275///
276/// See @ref bslfmt_formatterbase
277template <class t_TYPE>
278struct FormatterBase_IsStdChronoGpsTime {
279 static const bool value = false;
280};
281
282template <class t_DURATION>
283struct FormatterBase_IsStdChronoGpsTime<
284 std::chrono::gps_time<t_DURATION> > {
285 static const bool value = true;
286};
287
288/// Simple trait type that tells is `t_TYPE` is an instance of
289/// `std::chrono::file_time`.
290///
291/// See @ref bslfmt_formatterbase
292template <class t_TYPE>
293struct FormatterBase_IsStdChronoFileTime {
294 static const bool value = false;
295};
296
297template <class t_DURATION>
298struct FormatterBase_IsStdChronoFileTime<
299 std::chrono::file_time<t_DURATION> > {
300 static const bool value = true;
301};
302
303/// Simple trait type that tells is `t_TYPE` is an instance of
304/// `std::chrono::local_time`.
305///
306/// See @ref bslfmt_formatterbase
307template <class t_TYPE>
308struct FormatterBase_IsStdChronoLocalTime {
309 static const bool value = false;
310};
311
312template <class t_DURATION>
313struct FormatterBase_IsStdChronoLocalTime<
314 std::chrono::local_time<t_DURATION> > {
315 static const bool value = true;
316};
317
318/// Simple trait type that tells is `t_TYPE` is an instance of
319/// `std::chrono::hh_mm_ss`.
320///
321/// See @ref bslfmt_formatterbase
322template <class t_TYPE>
323struct FormatterBase_IsStdChronoHhMmSs {
324 static const bool value = false;
325};
326
327template <class t_DURATION>
328struct FormatterBase_IsStdChronoHhMmSs<
329 std::chrono::hh_mm_ss<t_DURATION> > {
330 static const bool value = true;
331};
332
333/// Simple trait type that tells is `t_TYPE` is an instance of any of
334/// `std::chrono::*_time`.
335///
336/// See @ref bslfmt_formatterbase
337template <class t_TYPE>
338struct FormatterBase_IsStdChronoTimeType {
339 static const bool value =
340 FormatterBase_IsStdChronoSysTime<t_TYPE>::value ||
341 FormatterBase_IsStdChronoUtcTime<t_TYPE>::value ||
342 FormatterBase_IsStdChronoTaiTime<t_TYPE>::value ||
343 FormatterBase_IsStdChronoGpsTime<t_TYPE>::value ||
344 FormatterBase_IsStdChronoFileTime<t_TYPE>::value ||
345 FormatterBase_IsStdChronoLocalTime<t_TYPE>::value ||
346 FormatterBase_IsStdChronoHhMmSs<t_TYPE>::value;
347};
348#endif // BSLS_LIBRARYFEATURES_HAS_CPP20_CALENDAR
349
350/// Simple trait type that tells is `t_TYPE` is an instance of any of the
351/// `std::chrono` types that deal with points in time.
352///
353/// See @ref bslfmt_formatterbase
354template <class t_TYPE>
355struct FormatterBase_IsStdChronoPointInTimeType {
356 static const bool value =
357 std::is_same_v<t_TYPE, std::chrono::day> ||
358 std::is_same_v<t_TYPE, std::chrono::month> ||
359 std::is_same_v<t_TYPE, std::chrono::year> ||
360 std::is_same_v<t_TYPE, std::chrono::weekday> ||
361 std::is_same_v<t_TYPE, std::chrono::weekday_indexed> ||
362 std::is_same_v<t_TYPE, std::chrono::weekday_last> ||
363 std::is_same_v<t_TYPE, std::chrono::month_day> ||
364 std::is_same_v<t_TYPE, std::chrono::month_day_last> ||
365 std::is_same_v<t_TYPE, std::chrono::month_weekday> ||
366 std::is_same_v<t_TYPE, std::chrono::month_weekday_last> ||
367 std::is_same_v<t_TYPE, std::chrono::year_month> ||
368 std::is_same_v<t_TYPE, std::chrono::year_month_day> ||
369 std::is_same_v<t_TYPE, std::chrono::year_month_day_last> ||
370 std::is_same_v<t_TYPE, std::chrono::year_month_weekday> ||
371 std::is_same_v<t_TYPE, std::chrono::year_month_weekday_last>;
372};
373
374/// Simple trait type that tells is `t_TYPE` is an instance of
375/// `std::chrono::zoned_time`.
376///
377/// See @ref bslfmt_formatterbase
378template <class t_TYPE>
379struct FormatterBase_IsStdChronoZonedTime {
380 static const bool value = false;
381};
382
383#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_TIMEZONE
384template <class t_DURATION, class t_TIME_ZONE_PTR>
385struct FormatterBase_IsStdChronoZonedTime<
386 std::chrono::zoned_time<t_DURATION, t_TIME_ZONE_PTR> > {
387 static const bool value = true;
388};
389#endif
390
391/// Simple trait type that tells is `t_TYPE` is an instance of any of the C++20
392/// standard formattable `std::chrono` types.
393///
394/// See @ref bslfmt_formatterbase
395template <class t_TYPE>
396struct FormatterBase_IsStdChronoCpp20FormattableType {
397 static const bool value =
398#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_CALENDAR
399 FormatterBase_IsStdChronoTimeType<t_TYPE>::value ||
400#endif // BSLS_LIBRARYFEATURES_HAS_CPP20_CALENDAR
401#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_TIMEZONE
402 FormatterBase_IsStdChronoZonedTime<t_TYPE>::value ||
403 std::is_same_v<t_TYPE, std::chrono::sys_info> ||
404 std::is_same_v<t_TYPE, std::chrono::local_info> ||
405#endif // BSLS_LIBRARYFEATURES_HAS_CPP20_TIMEZONE
406 FormatterBase_IsStdChronoPointInTimeType<t_TYPE>::value;
407};
408
409} // close package namespace
410
411#endif // BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT
412
413namespace bsl {
414
415 // ================
416 // struct formatter
417 // ================
418
419/// This is the base template for the `bsl::formatter` class. Its members are
420/// deleted to ensure attempts to format a type without a partial
421/// specialization of `formatter` for that type will result in a compile time
422/// error.
423///
424/// See @ref bslfmt_formatterbase
425template <class t_ARG, class t_CHAR = char>
426struct formatter {
427 private:
428 // NOT IMPLEMENTED
430 formatter& operator=(const formatter&) BSLS_KEYWORD_DELETED;
431};
432
433} // close namespace bsl
434
435#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT
436namespace std {
437
438/// Partial `formatter` specialization in the `std` namespace to enable use of
439/// formatters defined in the `bsl` namespace.
440template <class t_ARG, class t_CHAR>
441 requires(
442 !std::is_arithmetic_v<t_ARG> &&
443 !std::is_same_v<t_ARG, std::nullptr_t> &&
444 !std::is_same_v<t_ARG, void *> &&
445 !std::is_same_v<t_ARG, const void *> &&
446 !std::is_same_v<t_ARG, t_CHAR *> &&
447 !std::is_same_v<t_ARG, const t_CHAR *> &&
448 !std::is_same_v<std::remove_extent_t<t_ARG>, const t_CHAR> &&
449 !BloombergLP::bslfmt::FormatterBase_IsStdBasicString<t_ARG>::value &&
450 !BloombergLP::bslfmt::FormatterBase_IsStdBasicStringView<
451 t_ARG>::value &&
452 !BloombergLP::bslfmt::FormatterBase_IsStdChronoCpp20FormattableType<
453 t_ARG>::value &&
454 std::default_initializable<bsl::formatter<t_ARG, t_CHAR> >)
455struct formatter<t_ARG, t_CHAR> : bsl::formatter<t_ARG, t_CHAR> {};
456
457} // close namespace std
458#endif // BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT
459
460#endif // INCLUDED_BSLFMT_FORMATTERBASE
461
462// ----------------------------------------------------------------------------
463// Copyright 2023 Bloomberg Finance L.P.
464//
465// Licensed under the Apache License, Version 2.0 (the "License");
466// you may not use this file except in compliance with the License.
467// You may obtain a copy of the License at
468//
469// http://www.apache.org/licenses/LICENSE-2.0
470//
471// Unless required by applicable law or agreed to in writing, software
472// distributed under the License is distributed on an "AS IS" BASIS,
473// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
474// See the License for the specific language governing permissions and
475// limitations under the License.
476// ----------------------------- END-OF-FILE ----------------------------------
477
478/** @} */
479/** @} */
480/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
Definition bdlat_valuetypefunctions.h:939
Definition bslfmt_enablestreamedformatter.h:130
Definition bdldfp_decimal.h:5549
Definition bslfmt_formatterbase.h:426