]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/CheckReturn.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / CheckReturn.h
1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2007 by Rich Sposato
4 // Permission to use, copy, modify, distribute and sell this software for any
5 //     purpose is hereby granted without fee, provided that the above copyright
6 //     notice appear in all copies and that both that copyright notice and this
7 //     permission notice appear in supporting documentation.
8 // The author makes no representations about the
9 //     suitability of this software for any purpose. It is provided "as is"
10 //     without express or implied warranty.
11 ////////////////////////////////////////////////////////////////////////////////
12
13 #ifndef LOKI_CHECK_RETURN_INC_
14 #define LOKI_CHECK_RETURN_INC_
15
16 // $Id$
17
18
19 #include <assert.h>
20 #include <stdio.h>
21 #include <stdexcept>
22
23
24 namespace Loki
25 {
26
27 // ----------------------------------------------------------------------------
28
29 ////////////////////////////////////////////////////////////////////////////////
30 ///  \class CheckReturn
31 ///
32 ///  \par Purpose
33 ///  C++ provides no mechanism within the language itself to force code to
34 ///  check the return value from a function call.  This simple class provides
35 ///  a mechanism by which programmers can force calling functions to check the
36 ///  return value.  Or at least make them consciously choose to disregard the
37 ///  return value.  If the calling function fails to use or store the return
38 ///  value, the destructor calls the OnError policy.
39 ///
40 ///  \par Template Parameters
41 ///  CheckReturn has two template parameters, Value and OnError.
42 ///  - Value is the return type from the function.  CheckReturn stores a copy of
43 ///  it rather than a reference or pointer since return value could be local to
44 ///  a function.  CheckReturn works best when the return type is a built-in
45 ///  primitive (bool, int, etc...) a pointer, or an enum (such as an error
46 ///  condition enum).  It can work with other types that have cheap copy
47 ///  operations.
48 ///  - OnError is a policy class indicating how to handle the situation when a
49 ///  caller does not check or copy the returned value.  Loki provides some
50 ///  policy classs and you may also write your own.  For example, you can write
51 ///  a policy to create a message box when the function ignores the return value.
52 ///  That would quickly tell you places where code ignores the function call.
53 ///  If your write your own, you only need a templated class or struct with a
54 ///  public function named "run" that accepts a reference to a const value.
55 ///
56 /// @par Provided Policy Classes
57 ///  - IgnoreReturnValue Deliberately ignores when the caller ignores the return value.
58 ///  - TriggerAssert Asserts in debug builds if the caller ignores the return value.
59 ///  - FprintfStderr Prints out an error message if the caller ignores the return value.
60 ///  - ThrowTheValue Throws the ignored value as an exception.
61 ///  - ThrowLogicError Throws a logic_error exception to indicate a programming error.
62 ////////////////////////////////////////////////////////////////////////////////
63
64
65 template<class T>
66 struct IgnoreReturnValue
67 {
68         static void run(const T &)
69         {
70                 /// Do nothing at all.
71         }
72 };
73
74 template<class T>
75 struct ThrowTheValue
76 {
77         static void run(const T &value )
78         {
79                 throw value;
80         }
81 };
82
83 template<class T>
84 struct ThrowLogicError
85 {
86         static void run( const T & )
87         {
88                 throw ::std::logic_error( "CheckReturn: return value was not checked.\n" );
89         }
90 };
91
92 template<class T>
93 struct TriggerAssert
94 {
95         static void run(const T &)
96         {
97                 assert( 0 );
98         }
99 };
100
101 template<class T>
102 struct FprintfStderr
103 {
104         static void run(const T &)
105         {
106                 fprintf(stderr, "CheckReturn: return value was not checked.\n");
107         }
108 };
109
110
111
112 template < class Value , template<class> class OnError = TriggerAssert >
113 class CheckReturn
114 {
115 public:
116
117         /// Conversion constructor changes Value type to CheckReturn type.
118         inline CheckReturn( const Value &value ) :
119                 m_value( value ), m_checked( false ) {}
120
121         /// Copy-constructor allows functions to call another function within the
122         /// return statement.  The other CheckReturn's m_checked flag is set since
123         /// its duty has been passed to the m_checked flag in this one.
124         inline CheckReturn( const CheckReturn &that ) :
125                 m_value( that.m_value ), m_checked( false )
126         {
127                 that.m_checked = true;
128         }
129
130         /// Destructor checks if return value was used.
131         inline ~CheckReturn( void )
132         {
133                 // If m_checked is false, then a function failed to check the
134                 // return value from a function call.
135                 if (!m_checked)
136                         OnError<Value>::run(m_value);
137         }
138
139         /// Conversion operator changes CheckReturn back to Value type.
140         inline operator Value ( void )
141         {
142                 m_checked = true;
143                 return m_value;
144         }
145
146 private:
147         /// Default constructor not implemented.
148         CheckReturn( void );
149
150         /// Copy-assignment operator not implemented.
151         CheckReturn &operator = ( const CheckReturn &that );
152
153         /// Copy of returned value.
154         Value m_value;
155
156         /// Flag for whether calling function checked return value yet.
157         mutable bool m_checked;
158 };
159
160 // ----------------------------------------------------------------------------
161
162 } // namespace Loki
163
164 #endif // end file guardian
165
166 // $Log$
167