1 // $Header$
2 //
3 // Copyright (C) 2000 - 2004, by
4 //
5 // Carlo Wood, Run on IRC <carlo@alinoe.com>
6 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
7 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
8 //
9 // This file may be distributed under the terms of the Q Public License
10 // version 1.0 as appearing in the file LICENSE.QPL included in the
11 // packaging of this file.
12 //
13 
14 /** \file libcwd/cwprint.h
15  *
16  * \brief Definition of the utilities cwprint and cwprint_using.
17  *
18  * This header file provides the declaration and definition of two debug utility functions,
19  * intended to print objects to an ostream without using the \c operator<< inserter for
20  * that class, if any.
21  *
22  * \sa libcwd::cwprint
23  *  \n libcwd::cwprint_using
24  */
25 
26 #ifndef LIBCWD_CWPRINT_H
27 #define LIBCWD_CWPRINT_H
28 
29 namespace libcwd {
30 
31 //===================================================================================================
32 // cwprint
33 //
34 
35 template<class PRINTABLE_OBJECT>
36   class cwprint_tct {
37   private:
38     PRINTABLE_OBJECT const& M_printable_object;
39   public:
cwprint_tct(PRINTABLE_OBJECT const & printable_object)40     cwprint_tct(PRINTABLE_OBJECT const& printable_object) : M_printable_object(printable_object) { }
41 
42     friend
43     inline	// Must be defined inside the class declaration in order to avoid a compiler warning.
44     std::ostream&
45     operator<<(std::ostream& os, cwprint_tct<PRINTABLE_OBJECT> const& __cwprint)
46     {
47       __cwprint.M_printable_object.print_on(os);
48       return os;
49     }
50   };
51 
52 /**
53  * \interface libcwd::cwprint cwprint.h libcwd/cwprint.h
54  * \ingroup group_special
55  *
56  * \brief Print an object to a %debug stream without needing an operator<<.
57  *
58  * This utility can be used to print an object to a %debug stream without using
59  * the normal \c operator<< of that object (if any exists at all).&nbsp;
60  * The purpose is to allow the printing of objects to %debug streams in a \e different
61  * way then when you'd normally print them to say <CODE>std::cout</CODE>.
62  *
63  * The \a printable_object (see example below) must have the signature:
64  *
65  * \code
66  * class Class {
67  *   ...
68  * public:
69  *   void print_on(std::ostream& os) const;
70  * };
71  * \endcode
72  *
73  * \sa cwprint_using
74  *
75  * <b>Example:</b>
76  *
77  * \code
78  * Dout( dc::channel, cwprint(printable_object) );
79  * \endcode
80  *
81  * this will write \a printable_object to the %debug stream by
82  * calling the method \c print_on.
83  */
84 
85 template<class T>
86   inline
87   cwprint_tct<T>
cwprint(T const & printable_object)88   cwprint(T const& printable_object)
89   {
90     return cwprint_tct<T>(printable_object);
91   }
92 
93 //===================================================================================================
94 // cwprint_using
95 //
96 
97 template<class PRINTABLE_OBJECT>
98   class cwprint_using_tct {
99     typedef void (PRINTABLE_OBJECT::* print_on_method_t)(std::ostream&) const;
100   private:
101     PRINTABLE_OBJECT const& M_printable_object;
102     print_on_method_t M_print_on_method;
103   public:
cwprint_using_tct(PRINTABLE_OBJECT const & printable_object,print_on_method_t print_on_method)104     cwprint_using_tct(PRINTABLE_OBJECT const& printable_object, print_on_method_t print_on_method) :
105 	M_printable_object(printable_object), M_print_on_method(print_on_method) { }
106 
107     friend
108     inline	// Must be defined inside the class declaration in order to avoid a compiler warning.
109     std::ostream&
110     operator<<(std::ostream& os, cwprint_using_tct<PRINTABLE_OBJECT> __cwprint_using)
111     {
112       (__cwprint_using.M_printable_object.*__cwprint_using.M_print_on_method)(os);
113       return os;
114     }
115   };
116 
117 /**
118  * \interface libcwd::cwprint_using cwprint.h libcwd/cwprint.h
119  * \ingroup group_special
120  *
121  * \brief Print an object to an ostream using an arbitrary method of that object.
122  *
123  * This utility can be used to print an object to a %debug stream without using
124  * the normal \c operator<< of that object (if any exists at all).&nbsp;
125  * The purpose is to allow the printing of objects to %debug streams in a \e different
126  * way then when you'd normally print them to say <CODE>std::cout</CODE>.
127  *
128  * The \a object (see example below) must have the signature:
129  *
130  * \code
131  * class Class {
132  *   ...
133  * public:
134  *   void arbitrary_method_name(std::ostream& os) const;
135  * };
136  * \endcode
137  *
138  * \sa cwprint
139  *
140  * <b>Example:</b>
141  *
142  * \code
143  * Dout( dc::channel, cwprint_using(object, &Class::arbitrary_method_name) );
144  * \endcode
145  *
146  * this will write \a object to the %debug stream by
147  * calling the method \a arbitrary_method_name.
148  */
149 
150 // The use of T_OR_BASE_OF_T as extra parameter is a compiler bug around.
151 // Without it you'd run into bug
152 // http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=38
153 // when `print_on_method' is a method of the base class of T.
154 
155 template<class T, class T_OR_BASE_OF_T>
156   inline
157   cwprint_using_tct<T_OR_BASE_OF_T>
cwprint_using(T const & printable_object,void (T_OR_BASE_OF_T::* print_on_method)(std::ostream &)const)158   cwprint_using(T const& printable_object, void (T_OR_BASE_OF_T::*print_on_method)(std::ostream&) const)
159   {
160     T_OR_BASE_OF_T const& base(printable_object);
161     return cwprint_using_tct<T_OR_BASE_OF_T>(base, print_on_method);
162   }
163 
164 } // namespace libcwd
165 
166 #endif // LIBCWD_CWPRINT_H
167