aboutsummaryrefslogtreecommitdiffstats
path: root/src/catch2/internal/catch_optional.hpp
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-06-29 19:25:29 +0100
committerLexi Winter <lexi@le-fay.org>2025-06-29 19:25:29 +0100
commitbc524d70253a4ab2fe40c3ca3e5666e267c0a4d1 (patch)
tree1e629e7b46b1d9972a973bc93fd100bcebd395be /src/catch2/internal/catch_optional.hpp
downloadnihil-vendor/catch2.tar.gz
nihil-vendor/catch2.tar.bz2
Diffstat (limited to 'src/catch2/internal/catch_optional.hpp')
-rw-r--r--src/catch2/internal/catch_optional.hpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/catch2/internal/catch_optional.hpp b/src/catch2/internal/catch_optional.hpp
new file mode 100644
index 0000000..d1e953a
--- /dev/null
+++ b/src/catch2/internal/catch_optional.hpp
@@ -0,0 +1,117 @@
+
+// Copyright Catch2 Authors
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+
+// SPDX-License-Identifier: BSL-1.0
+#ifndef CATCH_OPTIONAL_HPP_INCLUDED
+#define CATCH_OPTIONAL_HPP_INCLUDED
+
+#include <catch2/internal/catch_move_and_forward.hpp>
+
+#include <cassert>
+
+namespace Catch {
+
+ // An optional type
+ template<typename T>
+ class Optional {
+ public:
+ Optional(): nullableValue( nullptr ) {}
+ ~Optional() { reset(); }
+
+ Optional( T const& _value ):
+ nullableValue( new ( storage ) T( _value ) ) {}
+ Optional( T&& _value ):
+ nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {}
+
+ Optional& operator=( T const& _value ) {
+ reset();
+ nullableValue = new ( storage ) T( _value );
+ return *this;
+ }
+ Optional& operator=( T&& _value ) {
+ reset();
+ nullableValue = new ( storage ) T( CATCH_MOVE( _value ) );
+ return *this;
+ }
+
+ Optional( Optional const& _other ):
+ nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {}
+ Optional( Optional&& _other ):
+ nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) )
+ : nullptr ) {}
+
+ Optional& operator=( Optional const& _other ) {
+ if ( &_other != this ) {
+ reset();
+ if ( _other ) { nullableValue = new ( storage ) T( *_other ); }
+ }
+ return *this;
+ }
+ Optional& operator=( Optional&& _other ) {
+ if ( &_other != this ) {
+ reset();
+ if ( _other ) {
+ nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) );
+ }
+ }
+ return *this;
+ }
+
+ void reset() {
+ if ( nullableValue ) { nullableValue->~T(); }
+ nullableValue = nullptr;
+ }
+
+ T& operator*() {
+ assert(nullableValue);
+ return *nullableValue;
+ }
+ T const& operator*() const {
+ assert(nullableValue);
+ return *nullableValue;
+ }
+ T* operator->() {
+ assert(nullableValue);
+ return nullableValue;
+ }
+ const T* operator->() const {
+ assert(nullableValue);
+ return nullableValue;
+ }
+
+ T valueOr( T const& defaultValue ) const {
+ return nullableValue ? *nullableValue : defaultValue;
+ }
+
+ bool some() const { return nullableValue != nullptr; }
+ bool none() const { return nullableValue == nullptr; }
+
+ bool operator !() const { return nullableValue == nullptr; }
+ explicit operator bool() const {
+ return some();
+ }
+
+ friend bool operator==(Optional const& a, Optional const& b) {
+ if (a.none() && b.none()) {
+ return true;
+ } else if (a.some() && b.some()) {
+ return *a == *b;
+ } else {
+ return false;
+ }
+ }
+ friend bool operator!=(Optional const& a, Optional const& b) {
+ return !( a == b );
+ }
+
+ private:
+ T* nullableValue;
+ alignas(alignof(T)) char storage[sizeof(T)];
+ };
+
+} // end namespace Catch
+
+#endif // CATCH_OPTIONAL_HPP_INCLUDED