Remove <glog/logging.h> from folly/Indestructible.h
authorYedidya Feldblum <yfeldblum@fb.com>
Sat, 7 Jan 2017 06:40:09 +0000 (22:40 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Sat, 7 Jan 2017 06:47:56 +0000 (22:47 -0800)
Summary:
[Folly] Remove `<glog/logging.h>` from `folly/Indestructible.h`.

This makes the header much lighter. And abort on invalid access (the use-case for `glog`) only in `!defined(NDEBUG)` mode.

Anti-Pattern Combined Mega-Diff Description:
* Add non-`explicit` default ctor.
* Disable ctor explicitly when underlying ctor would fail to compile. Not sure how useful it would be, but it makes type-traits work correctly for whatever that is worth.
* Switch boolean flag to `erased_{false}` so that it is zero-initializable, because that's better.

Reviewed By: ericniebler

Differential Revision: D4380469

fbshipit-source-id: a39cb7470f7ee678fa722778da587409f468d985

folly/Indestructible.h
folly/Makefile.am
folly/test/IndestructibleTest.cpp

index 686bbce3014b73fe94cd0fbc0323985446a18b34..285d9ed6a6d3529850de5ca31612aa5d3dcf9a36 100644 (file)
 
 #pragma once
 
+#include <cassert>
+#include <type_traits>
 #include <utility>
-#include <glog/logging.h>
-#include <folly/Likely.h>
-#include <folly/Portability.h>
 
 namespace folly {
 
@@ -60,10 +59,13 @@ template <typename T>
 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;
 
@@ -73,12 +75,12 @@ class Indestructible final {
   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() {
@@ -96,26 +98,25 @@ class Indestructible final {
 
  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};
 };
 }
index dd6e6bc0dc98f8749858900e7408d156241d0962..2fc98c82137d161ffe16258cd77cada7d67b1e87 100644 (file)
@@ -8,6 +8,7 @@ ACLOCAL_AMFLAGS = -I m4
 
 CLEANFILES =
 
+
 noinst_PROGRAMS = generate_fingerprint_tables
 generate_fingerprint_tables_SOURCES = build/GenerateFingerprintTables.cpp
 generate_fingerprint_tables_LDADD = libfollybase.la
index e01a2ba6925e1821b8e93aa1b2a302e60b8a9b9f..b5ca965690a4a22145b25e1af7a7b4cc2aa1c597 100644 (file)
@@ -75,6 +75,12 @@ TEST_F(IndestructibleTest, no_destruction) {
   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;
@@ -102,3 +108,14 @@ TEST_F(IndestructibleTest, move) {
   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));
+}