/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef FOLLY_OPTIONAL_H_
-#define FOLLY_OPTIONAL_H_
+#pragma once
/*
* Optional - For conditional initialization of values, like boost::optional,
* }
*/
#include <cstddef>
+#include <functional>
+#include <new>
#include <stdexcept>
#include <type_traits>
#include <utility>
+#include <folly/Portability.h>
+
namespace folly {
namespace detail { struct NoneHelper {}; }
const None none = nullptr;
-/**
- * gcc-4.7 warns about use of uninitialized memory around the use of storage_
- * even though this is explicitly initialized at each point.
- */
-#if defined(__GNUC__) && !defined(__clang__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wuninitialized"
-# pragma GCC diagnostic ignored "-Wpragmas"
-# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif // __GNUC__
-
class OptionalEmptyException : public std::runtime_error {
public:
OptionalEmptyException()
return storage_.value;
}
- Value value() && {
+ Value&& value() && {
+ require_value();
+ return std::move(storage_.value);
+ }
+
+ const Value&& value() const&& {
require_value();
return std::move(storage_.value);
}
return hasValue();
}
- 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(); }
+ const Value&& operator*() const&& { return std::move(value()); }
+ Value&& operator*() && { return std::move(value()); }
const Value* operator->() const { return &value(); }
Value* operator->() { return &value(); }
}
struct StorageTriviallyDestructible {
- // uninitialized
- union { Value value; };
- bool hasValue;
+ // The union trick allows to initialize the Optional's memory,
+ // so that compiler/tools don't complain about uninitialized memory,
+ // without actually calling Value's default constructor.
+ // The rest of the implementation enforces that hasValue/value are
+ // synchronized.
+ union {
+ bool hasValue;
+ struct {
+ bool paddingForHasValue_[1];
+ Value value;
+ };
+ };
StorageTriviallyDestructible() : hasValue{false} {}
};
struct StorageNonTriviallyDestructible {
- // uninitialized
- union { Value value; };
- bool hasValue;
-
+ // See StorageTriviallyDestructible's union
+ union {
+ bool hasValue;
+ struct {
+ bool paddingForHasValue_[1];
+ Value value;
+ };
+ };
+
+ FOLLY_PUSH_WARNING
+ // These are both informational warnings, but they trigger rare enough
+ // that we've left them enabled.
+ FOLLY_MSVC_DISABLE_WARNING(4587) // constructor of .value is not called
+ FOLLY_MSVC_DISABLE_WARNING(4588) // destructor of .value is not called
StorageNonTriviallyDestructible() : hasValue{false} {}
-
~StorageNonTriviallyDestructible() {
clear();
}
+ FOLLY_POP_WARNING
void clear() {
if (hasValue) {
Storage storage_;
};
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-
template<class T>
const T* get_pointer(const Optional<T>& opt) {
return opt.get_pointer();
} // namespace folly
-#endif // FOLLY_OPTIONAL_H_
+// Allow usage of Optional<T> in std::unordered_map and std::unordered_set
+FOLLY_NAMESPACE_STD_BEGIN
+template <class T>
+struct hash<folly::Optional<T>> {
+ size_t operator()(folly::Optional<T> const& obj) const {
+ if (!obj.hasValue()) {
+ return 0;
+ }
+ return hash<typename remove_const<T>::type>()(*obj);
+ }
+};
+FOLLY_NAMESPACE_STD_END