BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslfmt_streamed.h
Go to the documentation of this file.
1/// @file bslfmt_streamed.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslfmt_streamed.h -*-C++-*-
8
9#ifndef INCLUDED_BSLFMT_STREAMED
10#define INCLUDED_BSLFMT_STREAMED
11
12#include <bsls_ident.h>
13BSLS_IDENT("$Id: $")
14
15/// @defgroup bslfmt_streamed bslfmt_streamed
16/// @brief Provide a wrapper to format using an `ostream` `operator<<`
17/// @addtogroup bsl
18/// @{
19/// @addtogroup bslfmt
20/// @{
21/// @addtogroup bslfmt_streamed
22/// @{
23///
24/// <h1> Outline </h1>
25/// * <a href="#bslfmt_streamed-purpose"> Purpose</a>
26/// * <a href="#bslfmt_streamed-classes"> Classes </a>
27/// * <a href="#bslfmt_streamed-description"> Description </a>
28/// * <a href="#bslfmt_streamed-usage"> Usage </a>
29/// * <a href="#bslfmt_streamed-formatting-a-streamable-object"> Formatting a Streamable Object </a>
30///
31/// # Purpose {#bslfmt_streamed-purpose}
32/// Provide a wrapper to format using an `ostream` `operator<<`
33///
34/// # Classes {#bslfmt_streamed-classes}
35///
36/// - bslfmt::Streamed: formattable wrapper that uses `ostream` `operator<<`
37///
38/// # Description {#bslfmt_streamed-description}
39/// This component provides both a wrapper class template and a
40/// function template for creating a wrapper that enables `bsl::format`ing
41/// values that offer an `ostream` insert `operator<<`. This wrapper is also
42/// compatible with `std::format` on platforms where it is provided.
43///
44/// @code
45/// bsl::format("Example: {}", bslfmt::streamed(ATypeWithoutAFormatter(42)));
46/// @endcode
47///
48/// Using the `bslfmt::streamed` free function may be preferred to using the
49/// `bslfmt::Streamed` type directly because the `bslfmt::streamed`
50/// free-function supports simpler syntax on platforms that do not support class
51/// template argument deduction (CTAD, introduced in C++17).
52///
53/// For more (important) information please see
54/// [the package documentation](@ref bslfmt-streaming-based-formatting) .
55///
56/// ## Usage {#bslfmt_streamed-usage}
57///
58///
59/// In this section we show the intended use of this component.
60///
61/// ### Formatting a Streamable Object {#bslfmt_streamed-formatting-a-streamable-object}
62///
63///
64/// Suppose we want to format an object that already supports streaming into an
65/// `ostream` using the insert `operator<<`.
66///
67/// First, we define a type with a streaming operator but without a formatter
68/// specialization:
69/// @code
70/// class NonFormattableType {};
71///
72/// std::ostream& operator<<(std::ostream& os, const NonFormattableType&)
73/// {
74/// return os << "The printout";
75/// }
76/// @endcode
77/// Then we create an instance of this type and use bsl::streamed to allow us to
78/// format it:
79/// @code
80/// const NonFormattableType obj;
81/// @endcode
82/// Next, we format the "value" using `bsl::format` with the wrapper-creator
83/// function:
84/// @code
85/// bsl::string s = bsl::format("{}", bslfmt::streamed(obj));
86/// @endcode
87/// Finally, we verify the output is correct:
88/// @code
89/// assert(s == "The printout");
90/// @endcode
91/// @}
92/** @} */
93/** @} */
94
95/** @addtogroup bsl
96 * @{
97 */
98/** @addtogroup bslfmt
99 * @{
100 */
101/** @addtogroup bslfmt_streamed
102 * @{
103 */
104
105#include <bslscm_version.h>
106
107#include <bslfmt_format.h>
108#include <bslfmt_formattable.h>
110
113#include <bsls_keyword.h>
114
115
116namespace bslfmt {
117
118#ifdef BSL_FORMATTABLE_DEFINED
119
120#define BSLFMT_STREAMED_INSTANCE_DEPRECATED_ \
121 BSLS_DEPRECATE_FEATURE( \
122 "bslfmt", \
123 "streamed", \
124 "There is already a formatter available for the specified type, " \
125 "please use that instead of streaming.")
126
127 // =======================================
128 // struct Streamed_NoWarningConstructorTag
129 // =======================================
130
131/// A *component private* tag type used to internally construct a `Streamed`
132/// object without a warning (about an already existing formatter).
133///
134/// See @ref bslfmt_streamed
135struct Streamed_NoWarningConstructorTag {
136};
137#endif // BSL_FORMATTABLE_DEFINED
138
139 // ==============
140 // class Streamed
141 // ==============
142
143/// This class provides a wrapper to enable a streamable type to be used with
144/// `bsl::format` (and `std::format`) when no formatter specialization is provided (the type is not formattable).
145///
146/// \note Note that it is possible to use
147/// this wrapper with types that have a formatter, if the compiler supports it
148/// we give a compilation warning directing the user to use the existing
149/// formatter instead of wrapping to use the streaming operator.
150///
151/// See @ref bslfmt_streamed
152template <class t_STREAMABLE>
153class Streamed {
154 private:
155 // DATA
156 const t_STREAMABLE& d_object;
157
158 private:
159 // PRIVATE CREATORS
160
161#ifdef BSL_FORMATTABLE_DEFINED
162 /// Create a `Streamed` wrapping the specified `object`.
163 ///
164 /// \pre The behavior is undefined unless the lifetime of `object` is at least as long as that
165 /// of the wrapper created. This constructor is the one used from the
166 /// `bslfmt::streamed` wrapper-creator function to avoid two warnings for
167 /// types that are already formattable.
168 Streamed(const t_STREAMABLE& object, Streamed_NoWarningConstructorTag);
169
170 // FRIENDS
171 template <class t_STREAMABLE2>
172 friend Streamed<t_STREAMABLE2> streamed(const t_STREAMABLE2& object)
173 requires(!bsl::formattable<t_STREAMABLE2, char>);
174 template <class t_STREAMABLE2>
175 friend Streamed<t_STREAMABLE2> streamed(const t_STREAMABLE2& object)
176 requires(bsl::formattable<t_STREAMABLE2, char>);
177#endif
178
179 public:
180 // CREATORS
181
182 /// Create a `Streamed` wrapper instance around the specified `object`.
183 ///
184 /// \pre The behavior is undefined unless the lifetime of `object` is at least
185 /// as long as that of the wrapper created.
186#ifdef BSL_FORMATTABLE_DEFINED
187 Streamed(const t_STREAMABLE& object)
188 requires(!bsl::formattable<t_STREAMABLE, char>);
189 BSLFMT_STREAMED_INSTANCE_DEPRECATED_
190 Streamed(const t_STREAMABLE& object)
191 requires(bsl::formattable<t_STREAMABLE, char>);
192#else // BSL_FORMATTABLE_DEFINED
193 Streamed(const t_STREAMABLE& object);
194#endif // else of BSL_FORMATTABLE_DEFINED
195
196 // ACCESSORS
197
198 /// Return a non-modifiable reference to the wrapped object.
199 const t_STREAMABLE& object() const;
200};
201
202#if defined(BSLS_COMPILERFEATURES_SUPPORT_CTAD) && \
203 defined(__apple_build_version__) && BSLS_PLATFORM_CMP_VERSION < 180000
204// The following deduction guide is needed for Apple versions of clang that do
205// not support CTAD with concepts present due to CWG issue 2628 resolution not
206// yet applied and therefore would give an ambiguity error indicating it does
207// not know which constructor to use for CTAD.
208template <class t_TYPE>
209Streamed(const t_TYPE& object) -> Streamed<t_TYPE>;
210#endif // CTAD is supported and on older Apple clang
211
212// FREE FUNCTIONS
213
214#ifdef BSL_FORMATTABLE_DEFINED
215/// Create and return a `bslfmt::Streamed` (wrapper) object for the specified streamable `object`.
216///
217/// \pre The behavior is undefined unless `t_STREAMABLE` has a
218/// standard and well-behaved `std::ostream` output operator. This
219/// wrapper-creator free function to support compilation with no CTAD (Class
220/// Template Argument Deduction); see (#Usage). Notice that for compilations
221/// that support the `bsl::formattable` trait we define two concept-driven
222/// overloads of this function, one of which will warn the user (compiler
223/// warning) if a `bsl::formatter` already exists for the type they try to
224/// streamed-wrap.
225template <class t_STREAMABLE>
226Streamed<t_STREAMABLE> streamed(const t_STREAMABLE& object)
227 requires(!bsl::formattable<t_STREAMABLE, char>);
228
229template <class t_STREAMABLE>
230BSLFMT_STREAMED_INSTANCE_DEPRECATED_ Streamed<t_STREAMABLE>
231streamed(const t_STREAMABLE& object)
232 requires(bsl::formattable<t_STREAMABLE, char>);
233#else // BSL_FORMATTABLE_DEFINED
234template <class t_STREAMABLE>
235Streamed<t_STREAMABLE> streamed(const t_STREAMABLE& object);
236#endif // else of BSL_FORMATTABLE_DEFINED
237
238// ============================================================================
239// INLINE DEFINITIONS
240// ============================================================================
241
242 // --------------
243 // class Streamed
244 // --------------
245
246// PRIVATE CREATORS
247#ifdef BSL_FORMATTABLE_DEFINED
248template <class t_STREAMABLE>
249inline
250Streamed<t_STREAMABLE>::Streamed(const t_STREAMABLE& object,
251 Streamed_NoWarningConstructorTag)
252: d_object(object)
253{
254}
255#endif // BSL_FORMATTABLE_DEFINED
256
257// ACCESSORS
258template <class t_STREAMABLE>
259inline
260const t_STREAMABLE& Streamed<t_STREAMABLE>::object() const
261{
262 return d_object;
263}
264
265// CREATORS
266#ifdef BSL_FORMATTABLE_DEFINED
267template <class t_STREAMABLE>
268Streamed<t_STREAMABLE>::Streamed(const t_STREAMABLE& object)
269 requires(!bsl::formattable<t_STREAMABLE, char>)
270: d_object(object)
271{
272}
273
274template <class t_STREAMABLE>
275BSLFMT_STREAMED_INSTANCE_DEPRECATED_
276Streamed<t_STREAMABLE>::Streamed(const t_STREAMABLE& object)
277 requires(bsl::formattable<t_STREAMABLE, char>)
278: d_object(object)
279{
280}
281#else // BSL_FORMATTABLE_DEFINED
282template <class t_STREAMABLE>
283Streamed<t_STREAMABLE>::Streamed(const t_STREAMABLE& object)
284: d_object(object)
285{
286}
287#endif // else of BSL_FORMATTABLE_DEFINED
288} // close package namespace
289
290// FREE FUNCTIONS
291#ifdef BSL_FORMATTABLE_DEFINED
292template <class t_STREAMABLE>
293bslfmt::Streamed<t_STREAMABLE> bslfmt::streamed(const t_STREAMABLE& object)
294 requires(!bsl::formattable<t_STREAMABLE, char>)
295{
296 return Streamed<t_STREAMABLE>(object, Streamed_NoWarningConstructorTag());
297}
298
299template <class t_STREAMABLE>
300BSLFMT_STREAMED_INSTANCE_DEPRECATED_
302bslfmt::streamed(const t_STREAMABLE& object)
303 requires(bsl::formattable<t_STREAMABLE, char>)
304{
305 return Streamed<t_STREAMABLE>(object, Streamed_NoWarningConstructorTag());
306}
307#else // BSLFMT_FORMATTABLE_DEFINED
308template <class t_STREAMABLE>
309bslfmt::Streamed<t_STREAMABLE> bslfmt::streamed(const t_STREAMABLE& object)
310{
311 return Streamed<t_STREAMABLE>(object);
312}
313#endif // BSLFMT_FORMATTABLE_DEFINED
314
315
316namespace bsl {
317
318/// Standard (`bsl`) formatter for the `bslfmt::Streamed` wrapper, delegates to
319/// `bslfmt::StreamedFormatter` of the wrapped type.
320template <class t_STREAMABLE>
321struct formatter<BloombergLP::bslfmt::Streamed<t_STREAMABLE>, char> {
322 private:
323 // DATA
324 BloombergLP::bslfmt::StreamedFormatter<t_STREAMABLE> d_formatter;
325
326 public:
327 // MANIPULATORS
328
329 /// Parse and validate the specification string stored in the iterator
330 /// accessed via the `begin()` method of the parseContext passed via the
331 /// specified `parseContext` parameter. Where nested parameters are
332 /// encountered in the specification string then the @ref next_arg_id and
333 /// @ref check_arg_id are called on `fc` as specified in the C++ Standard.
334 /// Return an end iterator of the parsed range. Throw an exception of type
335 /// `bsl::format_error` in the event of failure.
336 template <class t_PARSE_CONTEXT>
337 BSLS_KEYWORD_CONSTEXPR_CPP20 typename t_PARSE_CONTEXT::iterator parse(
338 t_PARSE_CONTEXT& parseContext)
339 {
340 return d_formatter.parse(parseContext);
341 }
342
343 // ACCESSORS
344
345 /// Format the specified `value` according to the specification stored as a
346 /// result of a previous call to the `parse` method, and write the result
347 /// to the iterator accessed by calling the `out()` method on the specified
348 /// `formatContext` parameter. Return an end iterator of the output range.
349 /// Throw an exception of type `bsl::format_error` in the event of failure.
350 template <class t_FORMAT_CONTEXT>
351 typename t_FORMAT_CONTEXT::iterator format(
352 const BloombergLP::bslfmt::Streamed<t_STREAMABLE>& value,
353 t_FORMAT_CONTEXT& formatContext) const
354 {
355 return d_formatter.format(value.object(), formatContext);
356 }
357};
358
359} // close namespace bsl
360
361#undef BSLFMT_STREAMED_INSTANCE_DEPRECATED_
362
363#endif // INCLUDED_BSLFMT_STREAMED
364
365// ----------------------------------------------------------------------------
366// Copyright 2025 Bloomberg Finance L.P.
367//
368// Licensed under the Apache License, Version 2.0 (the "License");
369// you may not use this file except in compliance with the License.
370// You may obtain a copy of the License at
371//
372// http://www.apache.org/licenses/LICENSE-2.0
373//
374// Unless required by applicable law or agreed to in writing, software
375// distributed under the License is distributed on an "AS IS" BASIS,
376// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
377// See the License for the specific language governing permissions and
378// limitations under the License.
379// ----------------------------- END-OF-FILE ----------------------------------
380
381/** @} */
382/** @} */
383/** @} */
Definition bslfmt_streamed.h:153
Streamed(const t_STREAMABLE &object)
Definition bslfmt_streamed.h:283
const t_STREAMABLE & object() const
Return a non-modifiable reference to the wrapped object.
Definition bslfmt_streamed.h:260
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR_CPP20
Definition bsls_keyword.h:645
Definition bdlat_valuetypefunctions.h:939
Definition bslfmt_enablestreamedformatter.h:130
Streamed< t_STREAMABLE > streamed(const t_STREAMABLE &object)
BSLS_KEYWORD_CONSTEXPR_CPP20 t_PARSE_CONTEXT::iterator parse(t_PARSE_CONTEXT &parseContext)
Definition bslfmt_streamed.h:337
t_FORMAT_CONTEXT::iterator format(const BloombergLP::bslfmt::Streamed< t_STREAMABLE > &value, t_FORMAT_CONTEXT &formatContext) const
Definition bslfmt_streamed.h:351
Definition bslfmt_formatterbase.h:426