| 4306 | // An optional type |
| 4307 | template<typename T> |
| 4308 | class Option { |
| 4309 | public: |
| 4310 | Option() : nullableValue( nullptr ) {} |
| 4311 | Option( T const& _value ) |
| 4312 | : nullableValue( new( storage ) T( _value ) ) |
| 4313 | {} |
| 4314 | Option( Option const& _other ) |
| 4315 | : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) |
| 4316 | {} |
| 4317 | |
| 4318 | ~Option() { |
| 4319 | reset(); |
| 4320 | } |
| 4321 | |
| 4322 | Option& operator= ( Option const& _other ) { |
| 4323 | if( &_other != this ) { |
| 4324 | reset(); |
| 4325 | if( _other ) |
| 4326 | nullableValue = new( storage ) T( *_other ); |
| 4327 | } |
| 4328 | return *this; |
| 4329 | } |
| 4330 | Option& operator = ( T const& _value ) { |
| 4331 | reset(); |
| 4332 | nullableValue = new( storage ) T( _value ); |
| 4333 | return *this; |
| 4334 | } |
| 4335 | |
| 4336 | void reset() { |
| 4337 | if( nullableValue ) |
| 4338 | nullableValue->~T(); |
| 4339 | nullableValue = nullptr; |
| 4340 | } |
| 4341 | |
| 4342 | T& operator*() { return *nullableValue; } |
| 4343 | T const& operator*() const { return *nullableValue; } |
| 4344 | T* operator->() { return nullableValue; } |
| 4345 | const T* operator->() const { return nullableValue; } |
| 4346 | |
| 4347 | T valueOr( T const& defaultValue ) const { |
| 4348 | return nullableValue ? *nullableValue : defaultValue; |
| 4349 | } |
| 4350 | |
| 4351 | bool some() const { return nullableValue != nullptr; } |
| 4352 | bool none() const { return nullableValue == nullptr; } |
| 4353 | |
| 4354 | bool operator !() const { return nullableValue == nullptr; } |
| 4355 | explicit operator bool() const { |
| 4356 | return some(); |
| 4357 | } |
| 4358 | |
| 4359 | private: |
| 4360 | T *nullableValue; |
| 4361 | alignas(alignof(T)) char storage[sizeof(T)]; |
| 4362 | }; |
| 4363 | |
| 4364 | } // end namespace Catch |
| 4365 | |