• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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