// bdlb_printadapter.h -*-C++-*- #ifndef INCLUDED_BDLB_PRINTADAPTER #define INCLUDED_BDLB_PRINTADAPTER #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide object for streaming objects using 'bdlb::PrintMethods'. // //@CLASSES: // bdlb::PrintAdapter: class for streaming objects using 'bdlb::PrintMethods'. // bdlb::PrintAdapterUtil: utility for constructing 'bdlb::PrintAdapter'. // //@DESCRIPTION: This component provides a template 'class' that will enable any // object that can be streamed using 'bdlb::PrintMethods' to be streamed via // '<<'. // // Through using this 'class', one can stream an object using 'operator<<' and // at the same time specify 'level' and 'spacesPerLevel' arguments to // appropriately indent and format the output. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Use in C++03 ///- - - - - - - - - - - - // Suppose we have a few 'bdlb::IdentSpan' objects that we want to print, only // we want to stream them with 'operator<<' and we want to specify non-default // values of 'level' and 'spacesPerLevel' to their streaming. //.. // const bdlb::IndexSpan a(3, 7), b(241, 22), c(23, 17); //.. // First, we create a typedef of 'PrintAdapter<IdentSpan>' to use: //.. // typedef bdlb::PrintAdapter<bdlb::IndexSpan> PAIS; //.. // Then, we create a line of dashes: //.. // const char * const line = "------------------------------------" // "------------------------------------\n"; //.. // Now, we use the 'typedef' to construct temporary 'PrintAdapter' objects to // stream our 'IndexSpan' objects: //.. // cout << " a: " << line << PAIS(&a, 2, 2) // << " b: " << line << PAIS(&b, 3, 2) // << " c: " << line << PAIS(&c, 4, 2); //.. // Finally, we see the output: //.. // a: ------------------------------------------------------------------------ // [ // position = 3 // length = 7 // ] // b: ------------------------------------------------------------------------ // [ // position = 241 // length = 22 // ] // c: ------------------------------------------------------------------------ // [ // position = 23 // length = 17 // ] //.. // ///Example 2: Use of 'PrintAdapterUtil::makeAdapter' ///- - - - - - - - - - - - - - - - - - - - - - - - - // Suppose we have a few 'bdlb::IdentSpan' objects that we want to print, only // we want to stream them with 'operator<<' and we want to specify // non-default values of 'level' and 'spacesPerLevel' to their streaming. //.. // const bdlb::IndexSpan a(3, 7), b(241, 22), c(23, 17); //.. // First, we make a typedef to the namespace 'struct': //.. // typedef bdlb::PrintAdapterUtil Util; //.. // Then, we create a line of dashes: //.. // const char * const line = "------------------------------------" // "------------------------------------\n"; //.. // Now, we call the static function 'PrintAdapterUtil::makeAdapter' on the // 'IndexSpan' objects to stream which will return streamable 'PrintAdapter' // objects: //.. // cout << " a: " << line << Util::makeAdapter(a, 2, 2) // << " b: " << line << Util::makeAdapter(b, 3, 2) // << " c: " << line << Util::makeAdapter(c, 4, 2); //.. // Finally, we see the output: //.. // a: ------------------------------------------------------------------------ // [ // position = 3 // length = 7 // ] // b: ------------------------------------------------------------------------ // [ // position = 241 // length = 22 // ] // c: ------------------------------------------------------------------------ // [ // position = 23 // length = 17 // ] //.. // ///Example 3: Use in C++17 With CTAD ///- - - - - - - - - - - - - - - - - // Suppose you have a few 'bdlb::IdentSpan' objects that you want to print, // only you want to stream them with 'operator<<' and you want to specify // non-default values of 'level' and 'spacesPerLevel' to their streaming. //.. // const bdlb::IndexSpan a(3, 7), b(241, 22), c(23, 17); //.. // First, we create a line of dashes: //.. // const char * const line = "------------------------------------" // "------------------------------------\n"; //.. // Now, you call the constructor 'PrintAdapter' on the 'IndexSpan' objects to // stream and CTAD will create the right template specification: //.. // cout << " a: " << line << bdlb::PrintAdapter(&a, 2, 2) // << " b: " << line << bdlb::PrintAdapter(&b, 3, 2) // << " c: " << line << bdlb::PrintAdapter(&c, 4, 2); //.. // Finally, we see the output: //.. // a: ------------------------------------------------------------------------ // [ // position = 3 // length = 7 // ] // b: ------------------------------------------------------------------------ // [ // position = 241 // length = 22 // ] // c: ------------------------------------------------------------------------ // [ // position = 23 // length = 17 // ] //.. #include <bdlscm_version.h> #include <bdlb_printmethods.h> #include <bsl_ostream.h> namespace BloombergLP { namespace bdlb { // ================== // class PrintAdapter // ================== template <class TYPE> class PrintAdapter { // This 'class' provides an object that may be streamed with 'operator<<' // to give full control of the indentation format of the streaming. // DATA const TYPE *d_object_p; int d_level; int d_spacesPerLevel; public: // CREATORS explicit PrintAdapter(const TYPE *object, int level = 0, int spacesPerLevel = 4); // Create a print adapter object bound to the specified 'object', and // with the optionally specified 'level' and 'spacesPerLevel' // attributes, to be used when the 'PrintAdapter' object is streamed. // Unless 'level' is specified, a value of 0 is used, unless // 'spacesPerLevel' is specified, a value of 4 is used. // PrintAdapter(const PrintAdapter&) = default; // MANIPULATORS // PrintAdapter& operator=(const PrintAdapter&) = default; // ACCESSORS int level() const; // Return the 'level' attribute. const TYPE& object() const; // Return a reference to the object referred to by this print adapter. int spacesPerLevel() const; // Return the 'spacesPerLevel' attribute. }; // ====================== // class PrintAdapterUtil // ====================== struct PrintAdapterUtil { // This 'struct' provides a namespace for a function template that // facilitates the construction of a 'PrintAdapter' without having to // explicitly specify template arguments in C++03. Note that in C++17 and // later, CTAD may be used instead of this 'struct' to call the // 'PrintAdapter' constructor without having to explicitly specify the // template argument. // CLASS METHOD template <class TYPE> static PrintAdapter<TYPE> makeAdapter(const TYPE& object, int level = 0, int spacesPerLevel = 4); // Create and return a 'PrintAdapter' object, passing the constructor // the specified 'object', 'level', and 'spacesPerLevel'. }; // FREE OPERATORS template <class TYPE> bsl::ostream& operator<<(bsl::ostream& stream, const PrintAdapter<TYPE>& adapter); // Write the value of the specified 'object' to the specified output // 'stream' and return a non-'const' reference to 'stream'. If 'stream' is // not valid on entry, this operation has no effect. Note that this // human-readable format is not fully specified and can change without // notice. // ============================================================================ // INLINE FUNCTION DEFINITIONS // ============================================================================ // ------------ // PrintAdapter // ------------ // CREATORS template <class TYPE> inline PrintAdapter<TYPE>::PrintAdapter(const TYPE *object, int level, int spacesPerLevel) : d_object_p(object) , d_level(level) , d_spacesPerLevel(spacesPerLevel) {} // ACCESSORS template <class TYPE> inline int PrintAdapter<TYPE>::level() const { return d_level; } template <class TYPE> inline const TYPE& PrintAdapter<TYPE>::object() const { return *d_object_p; } template <class TYPE> inline int PrintAdapter<TYPE>::spacesPerLevel() const { return d_spacesPerLevel; } // FREE OPERATORS template <class TYPE> inline bsl::ostream& operator<<(bsl::ostream& stream, const PrintAdapter<TYPE>& adapter) // 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 'stream' is not valid on entry, this // operation has no effect. { return bdlb::PrintMethods::print(stream, adapter.object(), adapter.level(), adapter.spacesPerLevel()); } // ---------------- // PrintAdapterUtil // ---------------- // CLASS METHOD template <class TYPE> inline PrintAdapter<TYPE> PrintAdapterUtil::makeAdapter(const TYPE& object, int level, int spacesPerLevel) { return PrintAdapter<TYPE>(&object, level, spacesPerLevel); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2022 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------