/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* cout << *v << endl;
* }
*/
-#include <cassert>
#include <cstddef>
+#include <stdexcept>
#include <type_traits>
#include <utility>
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif // __GNUC__
+class OptionalEmptyException : public std::runtime_error {
+ public:
+ OptionalEmptyException()
+ : std::runtime_error("Empty Optional cannot be unwrapped") {}
+};
+
template<class Value>
class Optional {
public:
+ typedef Value value_type;
+
static_assert(!std::is_reference<Value>::value,
"Optional may not be used with reference types");
+ static_assert(!std::is_abstract<Value>::value,
+ "Optional may not be used with abstract types");
- Optional()
+ Optional() noexcept
: hasValue_(false) {
}
}
}
- const Value& value() const {
- assert(hasValue());
+ const Value& value() const& {
+ require_value();
return value_;
}
- Value& value() {
- assert(hasValue());
+ Value& value() & {
+ require_value();
return value_;
}
+ Value value() && {
+ require_value();
+ return std::move(value_);
+ }
+
+ const Value* get_pointer() const& { return hasValue_ ? &value_ : nullptr; }
+ Value* get_pointer() & { return hasValue_ ? &value_ : nullptr; }
+ Value* get_pointer() && = delete;
+
bool hasValue() const { return hasValue_; }
explicit operator bool() const {
return hasValue();
}
- const Value& operator*() const { return value(); }
- Value& operator*() { return value(); }
+ const Value& operator*() const& { return value(); }
+ Value& operator*() & { return value(); }
+ Value operator*() && { return std::move(value()); }
const Value* operator->() const { return &value(); }
Value* operator->() { return &value(); }
}
private:
+ void require_value() const {
+ if (!hasValue_) {
+ throw OptionalEmptyException();
+ }
+ }
+
template<class... Args>
void construct(Args&&... args) {
const void* ptr = &value_;
template<class T>
const T* get_pointer(const Optional<T>& opt) {
- return opt ? &opt.value() : nullptr;
+ return opt.get_pointer();
}
template<class T>
T* get_pointer(Optional<T>& opt) {
- return opt ? &opt.value() : nullptr;
+ return opt.get_pointer();
}
template<class T>
return !(a < b);
}
-// To supress comparability of Optional<T> with T, despite implicit conversion.
+// Suppress comparability of Optional<T> with T, despite implicit conversion.
template<class V> bool operator< (const Optional<V>&, const V& other) = delete;
template<class V> bool operator<=(const Optional<V>&, const V& other) = delete;
template<class V> bool operator>=(const Optional<V>&, const V& other) = delete;