Commit 22e8caf3 authored by Tom Jackson's avatar Tom Jackson Committed by Sara Golemon

Making Optional throw exceptions instead of assert

Summary: I'm upgrading assertions to throws, since these are fatal in all circumstances. If something is explicitly `Optional`, it makes sense to fail loudly if it is misused in this manner.

Reviewed By: @yfeldblum

Differential Revision: D2247612
parent 59bdbbcc
...@@ -54,8 +54,8 @@ ...@@ -54,8 +54,8 @@
* cout << *v << endl; * cout << *v << endl;
* } * }
*/ */
#include <cassert>
#include <cstddef> #include <cstddef>
#include <stdexcept>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
...@@ -82,6 +82,12 @@ const None none = nullptr; ...@@ -82,6 +82,12 @@ const None none = nullptr;
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif // __GNUC__ #endif // __GNUC__
class OptionalEmptyException : public std::runtime_error {
public:
OptionalEmptyException()
: std::runtime_error("Empty Optional cannot be unwrapped") {}
};
template<class Value> template<class Value>
class Optional { class Optional {
public: public:
...@@ -206,15 +212,18 @@ class Optional { ...@@ -206,15 +212,18 @@ class Optional {
} }
const Value& value() const { const Value& value() const {
assert(hasValue()); require_value();
return value_; return value_;
} }
Value& value() { Value& value() {
assert(hasValue()); require_value();
return value_; return value_;
} }
Value* get_pointer() { return hasValue_ ? &value_ : nullptr; }
const Value* get_pointer() const { return hasValue_ ? &value_ : nullptr; }
bool hasValue() const { return hasValue_; } bool hasValue() const { return hasValue_; }
explicit operator bool() const { explicit operator bool() const {
...@@ -239,6 +248,12 @@ class Optional { ...@@ -239,6 +248,12 @@ class Optional {
} }
private: private:
void require_value() const {
if (!hasValue_) {
throw OptionalEmptyException();
}
}
template<class... Args> template<class... Args>
void construct(Args&&... args) { void construct(Args&&... args) {
const void* ptr = &value_; const void* ptr = &value_;
...@@ -258,12 +273,12 @@ class Optional { ...@@ -258,12 +273,12 @@ class Optional {
template<class T> template<class T>
const T* get_pointer(const Optional<T>& opt) { const T* get_pointer(const Optional<T>& opt) {
return opt ? &opt.value() : nullptr; return opt.get_pointer();
} }
template<class T> template<class T>
T* get_pointer(Optional<T>& opt) { T* get_pointer(Optional<T>& opt) {
return opt ? &opt.value() : nullptr; return opt.get_pointer();
} }
template<class T> template<class T>
......
...@@ -497,4 +497,9 @@ TEST(Optional, AssignmentContained) { ...@@ -497,4 +497,9 @@ TEST(Optional, AssignmentContained) {
} }
} }
TEST(Optional, Exceptions) {
Optional<int> empty;
EXPECT_THROW(empty.value(), OptionalEmptyException);
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment