#pragma once
+#include <cassert>
+#include <type_traits>
#include <utility>
-#include <glog/logging.h>
-#include <folly/Likely.h>
-#include <folly/Portability.h>
namespace folly {
class Indestructible final {
public:
- template <typename... Args>
+ template <typename S = T, typename = decltype(S())>
+ constexpr Indestructible() noexcept(noexcept(T())) {}
+
+ template <typename... Args, typename = decltype(T(std::declval<Args&&>()...))>
explicit constexpr Indestructible(Args&&... args) noexcept(
std::is_nothrow_constructible<T, Args&&...>::value)
- : storage_(std::forward<Args>(args)...), inited_(true) {}
+ : storage_(std::forward<Args>(args)...) {}
~Indestructible() = default;
Indestructible(Indestructible&& other) noexcept(
std::is_nothrow_move_constructible<T>::value)
: storage_(std::move(other.storage_.value)) {
- other.inited_ = false;
+ other.erased_ = true;
}
Indestructible& operator=(Indestructible&& other) noexcept(
std::is_nothrow_move_assignable<T>::value) {
storage_.value = std::move(other.storage_.value);
- other.inited_ = false;
+ other.erased_ = true;
}
T* get() {
private:
void check() const {
- if (UNLIKELY(!inited_)) {
- fail();
- }
- }
-
- [[noreturn]] FOLLY_NOINLINE static void fail() {
- LOG(FATAL) << "Indestructible is not initialized";
+ assert(!erased_);
}
union Storage {
T value;
- template <typename... Args>
+ template <typename S = T, typename = decltype(S())>
+ constexpr Storage() noexcept(noexcept(T())) : value() {}
+
+ template <
+ typename... Args,
+ typename = decltype(T(std::declval<Args&&>()...))>
explicit constexpr Storage(Args&&... args)
: value(std::forward<Args>(args)...) {}
~Storage() {}
};
- Storage storage_;
- bool inited_{false};
+ Storage storage_{};
+ bool erased_{false};
};
}
EXPECT_EQ(1, state);
}
+TEST_F(IndestructibleTest, empty) {
+ static const Indestructible<map<string, int>> data;
+ auto& m = *data;
+ EXPECT_EQ(0, m.size());
+}
+
TEST_F(IndestructibleTest, move) {
int state = 0;
int value = 0;
EXPECT_EQ(1, state);
EXPECT_EQ(2, moves);
}
+
+TEST_F(IndestructibleTest, disabled_default_ctor) {
+ EXPECT_TRUE((std::is_constructible<Indestructible<int>>::value)) << "sanity";
+
+ struct Foo {
+ Foo(int) {}
+ };
+ EXPECT_FALSE((std::is_constructible<Indestructible<Foo>>::value));
+ EXPECT_FALSE((std::is_constructible<Indestructible<Foo>, Magic>::value));
+ EXPECT_TRUE((std::is_constructible<Indestructible<Foo>, int>::value));
+}