1 // Copyright (C) 2003, Fernando Luis Cacciola Carballal.
2 // Copyright (C) 2014, Andrzej Krzemienski.
3 //
4 // Use, modification, and distribution is subject to the Boost Software
5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/lib/optional for documentation.
9 //
10 // You are welcome to contact the author at:
11 // fernando_cacciola@hotmail.com
12 //
13 #include <boost/core/ignore_unused.hpp>
14
15 #ifdef ENABLE_TRACE
16 #define TRACE(msg) std::cout << msg << std::endl ;
17 #else
18 #define TRACE(msg)
19 #endif
20
21 namespace boost {
22
assertion_failed(char const * expr,char const * func,char const * file,long)23 void assertion_failed (char const * expr, char const * func, char const * file, long )
24 {
25 using std::string ;
26 string msg = string("Boost assertion failure for \"")
27 + string(expr)
28 + string("\" at file \"")
29 + string(file)
30 + string("\" function \"")
31 + string(func)
32 + string("\"") ;
33
34 TRACE(msg);
35
36 throw std::logic_error(msg);
37 }
38
39 }
40
41 using boost::optional ;
42
43
44 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
45 using boost::swap ;
46 using boost::get ;
47 using boost::get_pointer ;
48 #endif
49
50 // MSVC6.0 does not support comparisons of optional against a literal null pointer value (0)
51 // via the safe_bool operator.
52 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1300) ) // 1300 == VC++ 7.1
53 #define BOOST_OPTIONAL_NO_NULL_COMPARE
54 #else
55 #define BOOST_OPTIONAL_NO_NULL_COMPARE // Andrzej: I also disable 0 comparison everywhere
56 #endif
57
58 #define ARG(T) (static_cast< T const* >(0))
59
60 //
61 // Helper class used to verify the lifetime managment of the values held by optional
62 //
63 class X
64 {
65 public :
66
X(int av)67 X ( int av ) : v(av)
68 {
69 ++ count ;
70
71 TRACE ( "X::X(" << av << "). this=" << this ) ;
72 }
73
X(X const & rhs)74 X ( X const& rhs ) : v(rhs.v)
75 {
76 pending_copy = false ;
77
78 TRACE ( "X::X( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
79
80 if ( throw_on_copy )
81 {
82 TRACE ( "throwing exception in X's copy ctor" ) ;
83 throw 0 ;
84 }
85
86 ++ count ;
87 }
88
~X()89 ~X()
90 {
91 pending_dtor = false ;
92
93 -- count ;
94
95 TRACE ( "X::~X(). v=" << v << " this=" << this );
96 }
97
operator =(X const & rhs)98 X& operator= ( X const& rhs )
99 {
100 pending_assign = false ;
101
102 if ( throw_on_assign )
103 {
104 TRACE ( "throwing exception in X's assignment" ) ;
105
106 v = -1 ;
107
108 throw 0 ;
109 }
110 else
111 {
112 v = rhs.v ;
113
114 TRACE ( "X::operator =( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
115 }
116 return *this ;
117 }
118
operator ==(X const & a,X const & b)119 friend bool operator == ( X const& a, X const& b )
120 { return a.v == b.v ; }
121
operator !=(X const & a,X const & b)122 friend bool operator != ( X const& a, X const& b )
123 { return a.v != b.v ; }
124
operator <(X const & a,X const & b)125 friend bool operator < ( X const& a, X const& b )
126 { return a.v < b.v ; }
127
V() const128 int V() const { return v ; }
V()129 int& V() { return v ; }
130
131 static int count ;
132 static bool pending_copy ;
133 static bool pending_dtor ;
134 static bool pending_assign ;
135 static bool throw_on_copy ;
136 static bool throw_on_assign ;
137
138 private :
139
140 int v ;
141
142 private :
143
144 X() ;
145 } ;
146
147
148 int X::count = 0 ;
149 bool X::pending_copy = false ;
150 bool X::pending_dtor = false ;
151 bool X::pending_assign = false ;
152 bool X::throw_on_copy = false ;
153 bool X::throw_on_assign = false ;
154
set_pending_copy(X const *)155 inline void set_pending_copy ( X const* ) { X::pending_copy = true ; }
set_pending_dtor(X const *)156 inline void set_pending_dtor ( X const* ) { X::pending_dtor = true ; }
set_pending_assign(X const *)157 inline void set_pending_assign ( X const* ) { X::pending_assign = true ; }
set_throw_on_copy(X const *)158 inline void set_throw_on_copy ( X const* ) { X::throw_on_copy = true ; }
set_throw_on_assign(X const *)159 inline void set_throw_on_assign ( X const* ) { X::throw_on_assign = true ; }
reset_throw_on_copy(X const *)160 inline void reset_throw_on_copy ( X const* ) { X::throw_on_copy = false ; }
reset_throw_on_assign(X const *)161 inline void reset_throw_on_assign ( X const* ) { X::throw_on_assign = false ; }
check_is_pending_copy(X const *)162 inline void check_is_pending_copy ( X const* ) { BOOST_TEST( X::pending_copy ) ; }
check_is_pending_dtor(X const *)163 inline void check_is_pending_dtor ( X const* ) { BOOST_TEST( X::pending_dtor ) ; }
check_is_pending_assign(X const *)164 inline void check_is_pending_assign ( X const* ) { BOOST_TEST( X::pending_assign ) ; }
check_is_not_pending_copy(X const *)165 inline void check_is_not_pending_copy ( X const* ) { BOOST_TEST( !X::pending_copy ) ; }
check_is_not_pending_dtor(X const *)166 inline void check_is_not_pending_dtor ( X const* ) { BOOST_TEST( !X::pending_dtor ) ; }
check_is_not_pending_assign(X const *)167 inline void check_is_not_pending_assign( X const* ) { BOOST_TEST( !X::pending_assign ) ; }
check_instance_count(int c,X const *)168 inline void check_instance_count ( int c, X const* ) { BOOST_TEST( X::count == c ) ; }
get_instance_count(X const *)169 inline int get_instance_count ( X const* ) { return X::count ; }
170
set_pending_copy(...)171 inline void set_pending_copy (...) {}
set_pending_dtor(...)172 inline void set_pending_dtor (...) {}
set_pending_assign(...)173 inline void set_pending_assign (...) {}
set_throw_on_copy(...)174 inline void set_throw_on_copy (...) {}
set_throw_on_assign(...)175 inline void set_throw_on_assign (...) {}
reset_throw_on_copy(...)176 inline void reset_throw_on_copy (...) {}
reset_throw_on_assign(...)177 inline void reset_throw_on_assign (...) {}
check_is_pending_copy(...)178 inline void check_is_pending_copy (...) {}
check_is_pending_dtor(...)179 inline void check_is_pending_dtor (...) {}
check_is_pending_assign(...)180 inline void check_is_pending_assign (...) {}
check_is_not_pending_copy(...)181 inline void check_is_not_pending_copy (...) {}
check_is_not_pending_dtor(...)182 inline void check_is_not_pending_dtor (...) {}
check_is_not_pending_assign(...)183 inline void check_is_not_pending_assign(...) {}
check_instance_count(...)184 inline void check_instance_count (...) {}
get_instance_count(...)185 inline int get_instance_count (...) { return 0 ; }
186
187
188 template<class T>
check_uninitialized_const(optional<T> const & opt)189 inline void check_uninitialized_const ( optional<T> const& opt )
190 {
191 #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
192 BOOST_TEST( opt == 0 ) ;
193 #endif
194 BOOST_TEST( !opt ) ;
195 BOOST_TEST( !get_pointer(opt) ) ;
196 BOOST_TEST( !opt.get_ptr() ) ;
197 BOOST_TEST( !opt.has_value() ) ;
198 BOOST_TEST( !opt.is_initialized() ) ;
199 BOOST_TEST( opt == boost::none ) ;
200 }
201 template<class T>
check_uninitialized(optional<T> & opt)202 inline void check_uninitialized ( optional<T>& opt )
203 {
204 #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
205 BOOST_TEST( opt == 0 ) ;
206 #endif
207 BOOST_TEST( !opt ) ;
208 BOOST_TEST( !get_pointer(opt) ) ;
209 BOOST_TEST( !opt.get_ptr() ) ;
210 BOOST_TEST( !opt.has_value() ) ;
211 BOOST_TEST( !opt.is_initialized() ) ;
212 BOOST_TEST( opt == boost::none ) ;
213
214 check_uninitialized_const(opt);
215 }
216
217 template<class T>
check_initialized_const(optional<T> const & opt)218 inline void check_initialized_const ( optional<T> const& opt )
219 {
220 BOOST_TEST( opt ) ;
221
222 #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
223 BOOST_TEST( opt != 0 ) ;
224 #endif
225
226 BOOST_TEST ( !!opt ) ;
227 BOOST_TEST ( get_pointer(opt) ) ;
228 BOOST_TEST ( opt.get_ptr() ) ;
229 BOOST_TEST ( opt.has_value() ) ;
230 BOOST_TEST ( opt.is_initialized() ) ;
231 BOOST_TEST ( opt != boost::none ) ;
232 }
233
234 template<class T>
check_initialized(optional<T> & opt)235 inline void check_initialized ( optional<T>& opt )
236 {
237 BOOST_TEST( opt ) ;
238
239 #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
240 BOOST_TEST( opt != 0 ) ;
241 #endif
242
243 BOOST_TEST ( !!opt ) ;
244 BOOST_TEST ( get_pointer(opt) ) ;
245 BOOST_TEST ( opt.get_ptr() ) ;
246 BOOST_TEST ( opt.has_value() ) ;
247 BOOST_TEST ( opt.is_initialized() ) ;
248 BOOST_TEST ( opt != boost::none ) ;
249
250 check_initialized_const(opt);
251 }
252
253 template<class T>
check_value_const(optional<T> const & opt,T const & v,T const & z)254 inline void check_value_const ( optional<T> const& opt, T const& v, T const& z )
255 {
256 BOOST_TEST( *opt == v ) ;
257 BOOST_TEST( *opt != z ) ;
258 BOOST_TEST( opt.get() == v ) ;
259 BOOST_TEST( opt.get() != z ) ;
260 BOOST_TEST( (*(opt.operator->()) == v) ) ;
261 BOOST_TEST( *get_pointer(opt) == v ) ;
262 }
263
264 template<class T>
check_value(optional<T> & opt,T const & v,T const & z)265 inline void check_value ( optional<T>& opt, T const& v, T const& z )
266 {
267 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // 1200 == VC++ 6.0
268 // For some reason, VC6.0 is creating a temporary while evaluating (*opt == v),
269 // so we need to turn throw on copy off first.
270 reset_throw_on_copy( ARG(T) ) ;
271 #endif
272
273 BOOST_TEST( *opt == v ) ;
274 BOOST_TEST( *opt != z ) ;
275 BOOST_TEST( opt.get() == v ) ;
276 BOOST_TEST( opt.get() != z ) ;
277 BOOST_TEST( (*(opt.operator->()) == v) ) ;
278 BOOST_TEST( *get_pointer(opt) == v ) ;
279
280 check_value_const(opt,v,z);
281 }
282
283
284