Quick Links:

bal | bbl | bdl | bsl

Classes | Namespaces | Functions

Component bdlb_printmethods
[Package bdlb]

Provide methods for uniform printing of value-semantic types. More...

Classes

struct  bdlb::TypeTraitHasPrintMethod
struct  bdlb::TypeTraitHasPrintMethod::Metafunction< TYPE >

Namespaces

namespace  bdlb::PrintMethods

Functions

bsl::ostream & bdlb::PrintMethods::print (bsl::ostream &stream, char object, int level=0, int spacesPerLevel=4)
bsl::ostream & bdlb::PrintMethods::print (bsl::ostream &stream, unsigned char object, int level=0, int spacesPerLevel=4)
template<class CHAR_T , class CHAR_TRAITS_T , class ALLOC >
bsl::ostream & bdlb::PrintMethods::print (bsl::ostream &stream, const bsl::basic_string< CHAR_T, CHAR_TRAITS_T, ALLOC > &object, int level=0, int spacesPerLevel=4)
template<class ALLOC >
bsl::ostream & bdlb::PrintMethods::print (bsl::ostream &stream, const bsl::vector< char, ALLOC > &object, int level=0, int spacesPerLevel=4)
template<class TYPE >
bsl::ostream & bdlb::PrintMethods::print (bsl::ostream &stream, const std::optional< TYPE > &object, int level=0, int spacesPerLevel=4)
template<class... TYPE>
bsl::ostream & bdlb::PrintMethods::print (bsl::ostream &stream, const std::variant< TYPE...> &object, int level=0, int spacesPerLevel=4)
bsl::ostream & bdlb::PrintMethods::print (bsl::ostream &stream, const std::monostate &object, int level=0, int spacesPerLevel=4)

Detailed Description

Outline
Purpose:
Provide methods for uniform printing of value-semantic types.
Classes:
bdlb::PrintMethods templates for uniform printing of value-semantic types
bdlb::HasPrintMethod trait indicating existence of print method
bdlb::TypeTraitHasPrintMethod old-style version of bdlb::HasPrintMethod
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 )
  bslalg::HasStlIterators
  bslmf::IsPair              ( lowest precedence  )
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:
  template <class TYPE>
  class MyWrapper {
    // An example wrapper class for a 'TYPE' object.

    // PRIVATE DATA MEMBERS
    TYPE d_obj;  // wrapped object

    public:
      // TRAITS
      BSLMF_NESTED_TRAIT_DECLARATION(MyWrapper, bdlb::HasPrintMethod);

      // CREATORS
      MyWrapper(): d_obj() {};
      MyWrapper(const TYPE& value) : d_obj(value) { }
      // ... other constructors and destructor ...

      // MANIPULATORS
      // ... assignment operator, etc. ...

      // ACCESSORS
      bsl::ostream& print(bsl::ostream& stream,
                          int           level          = 0,
                          int           spacesPerLevel = 4) const;
          // 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.
  };
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()
  {
      BSLMF_ASSERT(bdlb::HasPrintMethod<MyDate>::value);

      MyDate            myDate;
      MyWrapper<MyDate> myWrapperForMyDate(myDate);

      BSLMF_ASSERT(!bdlb::HasPrintMethod<int>::value);

      bsl::ostringstream oss1;
      myWrapperForMyDate.print(oss1); // No problem expected since
                                      // 'bsls::TimeInterval' has a 'print'
                                      // method.
      assert("01JAN0001\n" == oss1.str());
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);

      bsl::ostringstream oss2;
      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;

      bsl::ostringstream oss3;
      myWrappedWrapper.print(oss3);
      assert("0\n" == oss3.str());
  }
See the bslmf_nestedtraitdeclaration component for more information about declaring traits for user-defined classes.

Function Documentation

bsl::ostream& bdlb::PrintMethods::print ( bsl::ostream &  stream,
char  object,
int  level = 0,
int  spacesPerLevel = 4 
)
bsl::ostream& bdlb::PrintMethods::print ( bsl::ostream &  stream,
unsigned char  object,
int  level = 0,
int  spacesPerLevel = 4 
)

Format the specified 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.

template<class CHAR_T , class CHAR_TRAITS_T , class ALLOC >
bsl::ostream& bdlb::PrintMethods::print ( bsl::ostream &  stream,
const bsl::basic_string< CHAR_T, CHAR_TRAITS_T, ALLOC > &  object,
int  level = 0,
int  spacesPerLevel = 4 
)

Format the specified object to the specified output stream at the (absolute value of) the optionally specified indentation level and return a reference to stream. Note that output will be formatted on one line. If stream is not valid on entry, this operation has no effect.

template<class ALLOC >
bsl::ostream& bdlb::PrintMethods::print ( bsl::ostream &  stream,
const bsl::vector< char, ALLOC > &  object,
int  level = 0,
int  spacesPerLevel = 4 
)

Format the specified object to the specified output stream at the (absolute value of) the optionally specified indentation level and return a reference to stream. Note that output will be formatted on one line. Also note that non-printable characters in object will be printed using their hexadecimal representation. If stream is not valid on entry, this operation has no effect.

template<class TYPE >
bsl::ostream& bdlb::PrintMethods::print ( bsl::ostream &  stream,
const std::optional< TYPE > &  object,
int  level = 0,
int  spacesPerLevel = 4 
)

Format the specified 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. A descriptive, human-readable message, indented according to level and spacesPerLevel, is output for objects having no value (i.e., false == object.has_value()).

template<class... TYPE>
bsl::ostream& bdlb::PrintMethods::print ( bsl::ostream &  stream,
const std::variant< TYPE...> &  object,
int  level = 0,
int  spacesPerLevel = 4 
)

Format the specified 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. A descriptive, human-readable message, indented according to level and spacesPerLevel, is output for objects holding the value of type std::monostate. Note that a std::variant object can hold the std::monostate value only if its template parameters explicitly mention the std::monostate type.

bsl::ostream& bdlb::PrintMethods::print ( bsl::ostream &  stream,
const std::monostate &  object,
int  level = 0,
int  spacesPerLevel = 4 
)

Format the specified 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. As all objects of this type have the same value, object is ignored and a descriptive, human-readable message is output for all objects of this type.