BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlb_printmethods

Detailed Description

Outline

Purpose

Provide methods for uniform printing of value-semantic types.

Classes

See also
bslalg_nestedtraitdeclaration

Description

This component provides a namespace for print utilities that support uniform ostream printing across all printable types, including template types and containers. The bdlb::PrintMethods namespace enables clients to output the value of any printable object according to the standard BDE print protocol. If the parameterized TYPE does not provide a print method, TYPE::operator<< is used. Availability of a print method is determined by testing for the bdlb::HasPrintMethod and bdlb::TypeTraitHasPrintMethod traits.

Traits Affecting Printing

By default, bdlb::PrintMethods::print uses the << stream output operator to print a value. This formats the entire output on one line, suppressing all indentation. A class can override this behavior by declaring certain traits related to printing. This component detects these traits and invokes an appropriate print operation. The following lists the traits recognized by this component:

bdlb::HasPrintMethod ( highest precedence )
bslmf::IsPair ( lowest precedence )
Definition bdlb_printmethods.h:306
Definition bslalg_hasstliterators.h:99
Definition bslmf_ispair.h:88

Since a class may declare multiple traits (see the component-level documentation of bslalg_nestedtraitdeclaration for information about declaring traits), the relative precedence of the traits is shown above. The next sub-sections describe these traits and their effects on printing.

Effect of bdlb::TypeTraitHasPrintMethod Trait

If a class X declares the bdlb::TypeTraitHasPrintMethod trait, then it must provide a print method with the following signature:

bsl::ostream& print(bsl::ostream& stream,
int level = 0,
int spacesPerLevel = 4) const;

To output an X object with this trait declared, the bdlb::PrintMethods::print method simply forwards to this method. This means that the print operation is completely defined by the class. Ideally, it should behave according to the standard BDE print protocol that is documented as follows:

Format this object to the specified output `stream` at the (absolute value
of) the optionally specified indentation `level` and return a reference to
`stream`. If `level` is specified, optionally specify `spacesPerLevel`,
the number of spaces per indentation level for this and all of its nested
objects. If `level` is negative, suppress indentation of the first line.
If `spacesPerLevel` is negative, format the entire output on one line,
suppressing all but the initial indentation (as governed by `level`). If
`stream` is not valid on entry, this operation has no effect.

Effect of bslalg::HasStlIterators Trait

If a class X declares the bslalg::HasStlIterators trait, then it must provide access to iterators using the standard STL protocol. The BDE implementation of STL declares this trait for all STL container types that have STL iterators. Other containers that provide STL iterators should declare this trait to get correct printing behavior.

When an X object with this trait is printed using bdlb::PrintMethods::print, the contents of the object is traversed via an iterator and the output is formatted according to the standard BDE print protocol, as documented above. Additionally, an opening [ character is prepended at the beginning of the output and a closing ] character is appended at the end of the output. Each iterated element is printed using its own print method, and with an indentation level one higher than that of the container.

Effect of bslmf::IsPair Trait

If a class X declares the bslmf::IsPair trait, then the class must contain two public data members named first and second. The BDE implementation of STL declares this trait for the bsl::pair struct. Other classes that have public first and second data members may declare this trait to get printing behavior similar to that of bsl::pair.

When an X object with this trait is printed using bdlb::PrintMethods::print, its output is formatted based on the standard BDE print protocol, as documented above. Additionally, an opening [ character is prepended at the beginning of the output and a closing ] character is appended at the end of the output. The first and second elements are printed using their own print methods, and with an indentation level one higher than that of the pair object.

Usage

This section illustrates intended use of this component.

Example 1: Supplying a print Method for a Parameterized Class

Suppose we must create a value-semantic class that holds an object of parameterized TYPE and, per BDE convention for VSTs, provides a print method that shows the value in some human-readable format.

First, we define the wrapper class:

/// An example wrapper class for a `TYPE` object.
template <class TYPE>
class MyWrapper {
// PRIVATE DATA MEMBERS
TYPE d_obj; // wrapped object
public:
// TRAITS
// CREATORS
MyWrapper(): d_obj() {};
MyWrapper(const TYPE& value) : d_obj(value) { }
// ... other constructors and destructor ...
// MANIPULATORS
// ... assignment operator, etc. ...
// ACCESSORS
/// Format the contained `TYPE` to the specified output `stream` at
/// the (absolute value of) the optionally specified indentation
/// `level` and return a reference to `stream`. If `level` is
/// specified, optionally specify `spacesPerLevel`, the number of
/// spaces per indentation level for this and all of its nested
/// objects. If `level` is negative, suppress indentation of the
/// first line. If `spacesPerLevel` is negative, format the entire
/// output on one line, suppressing all but the initial indentation
/// (as governed by `level`). If `stream` is not valid on entry,
/// this operation has no effect.
bsl::ostream& print(bsl::ostream& stream,
int level = 0,
int spacesPerLevel = 4) const;
};
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
bsl::ostream & print(bsl::ostream &stream, const TYPE &object, int level=0, int spacesPerLevel=4)
Definition bdlb_printmethods.h:719

Now, we implement the print method of MyWrapper using the bdlb::PrintMethods utility. Doing so gives us a method that produces results both when TYPE defines a print method and when it does not. In the latter case TYPE::operator<< is used.

template <class TYPE>
bsl::ostream& MyWrapper<TYPE>::print(bsl::ostream& stream,
int level,
int spacesPerLevel) const
{
return bdlb::PrintMethods::print(stream, d_obj, level, spacesPerLevel);
}

Finally, we exercise our MyWrapper class using several representative types, starting with MyDate (not shown) a class that implements a print method.

static void usingMyWrapper()
{
MyDate myDate;
MyWrapper<MyDate> myWrapperForMyDate(myDate);
myWrapperForMyDate.print(oss1); // No problem expected since
// `bsls::TimeInterval` has a `print`
// method.
assert("01JAN0001\n" == oss1.str());
Definition bslstl_ostringstream.h:175
void str(const StringType &value)
Definition bslstl_ostringstream.h:581
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229

Using an int type shows how bdlb::PrintMethods::print transparently handles types that do not provide print methods:

int myInt = 123;
MyWrapper<int> myWrapperForInt(myInt);
myWrapperForInt.print(oss2); // `int` has no `print` method.
// Problem?
assert("123\n" == oss2.str()); // No problem!

Lastly, since MyWrapper itself is a type that implements print – and sets the bdlb::TypeTraitHasPrintMethod trait – one instance of the MyWrapper type can be wrapped by another.

BSLMF_ASSERT(bdlb::HasPrintMethod<MyWrapper<int> >::value);
MyWrapper<MyWrapper<int> > myWrappedWrapper;
myWrappedWrapper.print(oss3);
assert("0\n" == oss3.str());
}

See the bslmf_nestedtraitdeclaration component for more information about declaring traits for user-defined classes.