BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlb_variantprinter.h
Go to the documentation of this file.
1/// @file bdlb_variantprinter.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_variantprinter.h -*-C++-*-
8#ifndef INCLUDED_BDLB_VARIANTPRINTER
9#define INCLUDED_BDLB_VARIANTPRINTER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlb_variantprinter bdlb_variantprinter
15/// @brief Provide a suite of helper classes for printing `bsl::variant`.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlb
19/// @{
20/// @addtogroup bdlb_variantprinter
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlb_variantprinter-purpose"> Purpose</a>
25/// * <a href="#bdlb_variantprinter-classes"> Classes </a>
26/// * <a href="#bdlb_variantprinter-description"> Description </a>
27/// * <a href="#bdlb_variantprinter-usage"> Usage </a>
28/// * <a href="#bdlb_variantprinter-example-1-printing-bsl-variant-to-a-stream"> Example 1: Printing bsl::variant to a Stream </a>
29///
30/// # Purpose {#bdlb_variantprinter-purpose}
31/// Provide a suite of helper classes for printing `bsl::variant`.
32///
33/// # Classes {#bdlb_variantprinter-classes}
34///
35/// - bdlb::VariantPrinter: utility for printing `bsl::variant`
36/// - bdlb::VariantPrinterUtil: factory for constructing `bdlb::VariantPrinter`
37///
38/// # Description {#bdlb_variantprinter-description}
39/// This component provides utility classes `bdlb::VariantPrinter`
40/// and `bdlb::VariantPrinterUtil` for printing `bsl::variant`.
41///
42/// The class `bdlb::VariantPrinter` can also be used with `bsl::format` (it
43/// defines the `bslfmt::EnableStreamedFormatter` trait). For information about
44/// the supported format options see
45/// [the `bslfmt` package documentation](@ref bslfmt-streaming-based-formatting) .
46///
47/// ## Usage {#bdlb_variantprinter-usage}
48///
49///
50/// This section illustrates intended use of this component.
51///
52/// ### Example 1: Printing bsl::variant to a Stream {#bdlb_variantprinter-example-1-printing-bsl-variant-to-a-stream}
53///
54///
55/// In this example, we demonstrate how to use `bdlb::VariantPrinterUtil` to
56/// print `bsl::variant` to a stream.
57///
58/// First, we create a streamable type that throws `int` on copies. This will
59/// enable us to put a `variant` into a valueless state by copying one into it:
60/// @code
61/// struct ThrowOnCopy {
62/// // DATA
63/// int d_ii;
64///
65/// // CREATORS
66/// ThrowOnCopy(int ii)
67/// : d_ii(ii)
68/// {}
69///
70/// ThrowOnCopy(const ThrowOnCopy& original)
71/// : d_ii(original.d_ii)
72/// {
73/// BSLS_THROW(0);
74/// }
75///
76/// // MANIPULATORS
77/// ThrowOnCopy& operator=(const ThrowOnCopy& rhs)
78/// {
79/// d_ii = rhs.d_ii;
80///
81/// BSLS_THROW(0);
82///
83/// return *this;
84/// }
85/// };
86///
87/// bsl::ostream& operator<<(bsl::ostream& stream,
88/// const ThrowOnCopy& value)
89/// {
90/// return stream << value.d_ii;
91/// }
92/// @endcode
93/// Next, we create a shorthand for `VariantPrinterUtil` and our `variant` type:
94/// @code
95/// typedef bdlb::VariantPrinterUtil Util;
96/// typedef bsl::variant<int, bsl::string, ThrowOnCopy> VariantIST;
97/// @endcode
98/// Then, we declare a variable of `variant` type, which can hold, among other
99/// types, a `ThrowOnCopy`:
100/// @code
101/// VariantIST mV(107);
102/// const VariantIST& V = mV;
103///
104/// ThrowOnCopy toc(4);
105/// @endcode
106/// Next, we start doing some output:
107/// @code
108/// cout << toc << endl; // prints "4\n"
109///
110/// cout << Util::makePrinter(V) << endl; // prints "107\n"
111///
112/// mV = bsl::string("woof");
113/// cout << Util::makePrinter(V) << endl; // prints "woof\n"
114///
115/// mV = 27;
116/// cout << Util::makePrinter(V) << endl; // prints "27\n"
117/// @endcode
118/// Then, we see that the type `VariantPrinter<...>` returned by
119/// `makePrinter` has a standard BDE-style `print` accessor that will
120/// control formatting and indenting:
121/// @code
122/// mV = bsl::string("bow");
123/// Util::makePrinter(V).print(cout, 3, -2); // prints " bow"
124/// mV = bsl::string("wow");
125/// Util::makePrinter(V).print(cout, 1, 1); // prints " wow\n"
126/// @endcode
127/// Now, we assign a `ThrowOnCopy` to the variant, which will throw when
128/// copied, leaving `mV` in a `valueless` state, and we observe what
129/// happens when we then print it.
130/// @code
131/// assert(!V.valueless_by_exception());
132/// BSLS_TRY
133/// {
134/// mV = toc;
135/// assert(false);
136/// }
137/// BSLS_CATCH(...)
138/// {
139/// }
140/// assert(V.valueless_by_exception());
141///
142/// cout << Util::makePrinter(V) << endl; // prints "(valueless)\n"
143/// @endcode
144/// Finally, we see the output created by all this:
145/// @code
146/// 4
147/// 107
148/// woof
149/// 27
150/// bow wow
151/// (valueless)
152/// @endcode
153/// @}
154/** @} */
155/** @} */
156
157/** @addtogroup bdl
158 * @{
159 */
160/** @addtogroup bdlb
161 * @{
162 */
163/** @addtogroup bdlb_variantprinter
164 * @{
165 */
166
167
168#include <bdlscm_version.h>
169
170#include <bdlb_printmethods.h>
171
174#include <bsls_assert.h>
175#include <bsls_libraryfeatures.h>
176
177#include <bsl_ostream.h>
178
179
180namespace bdlb {
181
182 // =============================
183 // struct VariantPrinter_Visitor
184 // =============================
185
186/// Visitor for visiting `t_TYPE` held by a variant and printing it.
187///
188/// See @ref bdlb_variantprinter
190 // DATA
191 bsl::ostream *d_stream_p;
194
195 // ACCESSORS
196
197 /// Call `print` on `object` using the data fields of this `struct`.
198 template <class t_TYPE>
199 void operator()(const t_TYPE& object) const;
200};
201
202/// Utility for printing `bsl::variant` to standard output streams. This class
203/// has `operator<<` defined for it, so it can be used, for example, in `ball`
204/// logs.
205///
206/// See @ref bdlb_variantprinter
207template <class t_VARIANT>
209 // DATA
210 const t_VARIANT* d_data_p;
211
212 public:
213 // TRAITS
216
217 // CREATORS
218
219 /// Create `VariantPrinter` with the specified `data`.
220 explicit
221 VariantPrinter(const t_VARIANT *data);
222
223 // ACCESSORS
224
225 /// Format this object to the specified output `stream` at the (absolute
226 /// value of) the optionally specified indentation `level` and return a
227 /// reference to `stream`. If `level` is specified, optionally specify
228 /// `spacesPerLevel`, the number of spaces per indentation level for this
229 /// and all of its nested objects. If `level` is negative, suppress
230 /// indentation of the first line. If `spacesPerLevel` is negative, format
231 /// the entire output on one line, suppressing all but the initial
232 /// indentation (as governed by `level`). If `stream` is not valid on
233 /// entry, this operation has no effect.
234 bsl::ostream& print(bsl::ostream& stream,
235 int level = 0,
236 int spacesPerLevel = 4) const;
237};
238
239// FREE OPERATORS
240
241/// Write the value of the specified `printer` object to the specified
242/// output `stream` in a single-line format, and return a reference to
243/// `stream`. If `stream` is not valid on entry, this operation has no effect.
244///
245/// \note Note that this human-readable format is not fully specified,
246/// can change without notice, and is logically equivalent to:
247/// @code
248/// print(stream, 0, -1);
249/// @endcode
250template <class t_VARIANT>
251bsl::ostream&
252operator<<(bsl::ostream& stream,
253 const VariantPrinter<t_VARIANT>& printer);
254
255 // =========================
256 // struct VariantPrinterUtil
257 // =========================
258
259/// This utility `struct` provides a namespace for a function that creates a
260/// `bdlb::VariantPrinter` with its template argument deduced from a given
261/// instance of `bsl::variant`.
262///
263/// See @ref bdlb_variantprinter
265 public:
266 // CLASS METHODS
267
268 /// Return an `VariantPrinter` that prints the specified `data`.
269 template <class t_VARIANT>
270 static VariantPrinter<t_VARIANT> makePrinter(const t_VARIANT& data);
271};
272
273// ============================================================================
274// INLINE DEFINITIONS
275// ============================================================================
276
277 // -----------------------------
278 // struct VariantPrinter_Visitor
279 // -----------------------------
280
281template <class t_TYPE>
282inline
283void VariantPrinter_Visitor::operator()(const t_TYPE& object) const
284{
285 // Note that we don't return the reference to `*d_stream_p` returned by
286 // `PrintMethods::print` because we're called by `bdl::visit` which on
287 // C++03 returns a const ref while `VariantPrinter::print` need to return a
288 // non-const reference which doesn't compile, so in `VariantPrinter::print`
289 // we explicitly return the reference in a separate statement after the
290 // call to `visit`.
291
293}
294
295 // ---------------------
296 // struct VariantPrinter
297 // ---------------------
298
299// CREATORS
300template <class t_VARIANT>
302: d_data_p(data)
303{
304 BSLS_ASSERT(data);
305}
306
307// ACCESSORS
308template <class t_VARIANT>
310 bsl::ostream& stream,
311 int level,
312 int spacesPerLevel) const
313{
314 if (d_data_p->valueless_by_exception()) {
315 return bdlb::PrintMethods::print(stream,
316 "(valueless)",
317 level,
318 spacesPerLevel); // RETURN
319 }
320
321 VariantPrinter_Visitor visitor = { &stream, level, spacesPerLevel };
322
323 visit(visitor, *d_data_p);
324
325 // If `visitor()` returns `stream&`, `bsl::visit` on C++03 turns that into
326 // a const ref causing compile errors. So we just have `visitor()` return
327 // void and explicitly return `stream` after the `visit` call.
328
329 return stream;
330}
331
332 // -------------------------
333 // struct VariantPrinterUtil
334 // -------------------------
335
336// CLASS METHODS
337template <class t_VARIANT>
338inline
341{
342 return VariantPrinter<t_VARIANT>(&data);
343}
344
345} // close package namespace
346
347// FREE OPERATORS
348template <class t_VARIANT>
349bsl::ostream& bdlb::operator<<(
350 bsl::ostream& stream,
352{
353 return object.print(stream, 0, -1);
354}
355
356
357
358#endif // INCLUDED_BDLB_VARIANTPRINTER
359
360// ----------------------------------------------------------------------------
361// Copyright 2024 Bloomberg Finance L.P.
362//
363// Licensed under the Apache License, Version 2.0 (the "License");
364// you may not use this file except in compliance with the License.
365// You may obtain a copy of the License at
366//
367// http://www.apache.org/licenses/LICENSE-2.0
368//
369// Unless required by applicable law or agreed to in writing, software
370// distributed under the License is distributed on an "AS IS" BASIS,
371// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
372// See the License for the specific language governing permissions and
373// limitations under the License.
374// ----------------------------- END-OF-FILE ----------------------------------
375
376/** @} */
377/** @} */
378/** @} */
Definition bdlb_variantprinter.h:208
VariantPrinter(const t_VARIANT *data)
Create VariantPrinter with the specified data.
Definition bdlb_variantprinter.h:301
BSLMF_NESTED_TRAIT_DECLARATION(VariantPrinter, bslfmt::EnableStreamedFormatter)
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Definition bdlb_variantprinter.h:309
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
bsl::ostream & print(bsl::ostream &stream, const TYPE &object, int level=0, int spacesPerLevel=4)
Definition bdlb_printmethods.h:725
Definition bdlb_algorithmworkaroundutil.h:74
bsl::ostream & operator<<(bsl::ostream &stream, const BigEndianInt16 &integer)
Definition bdlb_variantprinter.h:264
static VariantPrinter< t_VARIANT > makePrinter(const t_VARIANT &data)
Return an VariantPrinter that prints the specified data.
Definition bdlb_variantprinter.h:340
Definition bdlb_variantprinter.h:189
int d_spacesPerLevel
Definition bdlb_variantprinter.h:193
bsl::ostream * d_stream_p
Definition bdlb_variantprinter.h:191
void operator()(const t_TYPE &object) const
Call print on object using the data fields of this struct.
Definition bdlb_variantprinter.h:283
int d_level
Definition bdlb_variantprinter.h:192
Definition bslfmt_enablestreamedformatter.h:141