Fix EventBaseLoopController destruction races
[folly.git] / folly / Optional.h
index dcc184aa585eafb0022dc0715580cb44696e59c6..1832009054bb3a42ea71981837083dc20f7e15d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -54,8 +54,8 @@
  *    cout << *v << endl;
  *  }
  */
-#include <cassert>
 #include <cstddef>
+#include <stdexcept>
 #include <type_traits>
 #include <utility>
 
@@ -82,13 +82,23 @@ const None none = nullptr;
 # 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) {
   }
 
@@ -203,24 +213,34 @@ class Optional {
     }
   }
 
-  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(); }
@@ -237,6 +257,12 @@ class Optional {
   }
 
  private:
+  void require_value() const {
+    if (!hasValue_) {
+      throw OptionalEmptyException();
+    }
+  }
+
   template<class... Args>
   void construct(Args&&... args) {
     const void* ptr = &value_;
@@ -256,12 +282,12 @@ class Optional {
 
 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>
@@ -338,7 +364,7 @@ bool operator>=(const Optional<V>& a, const Optional<V>& b) {
   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;