Commit b29d023b authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by facebook-github-bot-0

ConditionallyExistent<typename>

Summary:
[Folly] `ConditionallyExistent<typename>`.

For when we need extra member fields in dbg builds, but want to save the space in opt builds. Or other situations along similar lines, but with perhaps another the statically-known condition.

Conditional compilation can have some nasty side-effects. Best to avoid it. Let the compiler see everything, rather than having the preprocessor ruin our day. Let the optimizer remove code that will never be called, after the compiler has seen it. Let us have a single AST in our source file, not one AST for dbg and one for opt, or other statically-known conditions.

Reviewed By: andriigrynenko

Differential Revision: D2879397

fb-gh-sync-id: d631141a984eebd46674f27a40a97f670eb33f54
parent e0f9b598
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <glog/logging.h>
#include <folly/Portability.h>
namespace folly {
template <typename T, bool Debug>
class ConditionallyExistent;
template <typename T>
class ConditionallyExistent<T, false> {
public:
static constexpr bool present() { return false; }
explicit ConditionallyExistent(const T&) {}
explicit ConditionallyExistent(T&&) {}
ConditionallyExistent(const ConditionallyExistent&) = delete;
ConditionallyExistent(ConditionallyExistent&&) = delete;
ConditionallyExistent& operator=(const ConditionallyExistent&) = delete;
ConditionallyExistent& operator=(ConditionallyExistent&&) = delete;
template <typename F>
void with(const F&&) {}
};
template <typename T>
class ConditionallyExistent<T, true> {
public:
static constexpr bool present() { return true; }
explicit ConditionallyExistent(const T& v) : value_(v) {}
explicit ConditionallyExistent(T&& v) : value_(std::move(v)) {}
ConditionallyExistent(const ConditionallyExistent&) = delete;
ConditionallyExistent(ConditionallyExistent&&) = delete;
ConditionallyExistent& operator=(const ConditionallyExistent&) = delete;
ConditionallyExistent& operator=(ConditionallyExistent&&) = delete;
template <typename F>
void with(F&& f) {
f(value_);
}
private:
T value_;
};
template <typename T>
using ExistentIfDebug = ConditionallyExistent<T, kIsDebug>;
}
......@@ -263,6 +263,7 @@ nobase_follyinclude_HEADERS = \
PicoSpinLock.h \
Portability.h \
portability/Syscall.h \
ConditionallyExistent.h \
Preprocessor.h \
ProducerConsumerQueue.h \
Random.h \
......
......@@ -334,6 +334,15 @@ typedef SSIZE_T ssize_t;
#endif
// Debug
namespace folly {
#ifdef NDEBUG
constexpr auto kIsDebug = false;
#else
constexpr auto kIsDebug = true;
#endif
}
// Endianness
namespace folly {
#ifdef _MSC_VER
......
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/ConditionallyExistent.h>
#include <gtest/gtest.h>
using namespace std;
using namespace folly;
namespace {
class ConditionallyExistentTest : public testing::Test {};
}
TEST_F(ConditionallyExistentTest, WhenConditionFalse) {
folly::ConditionallyExistent<string, false> foobar("hello world");
EXPECT_FALSE(foobar.present());
bool called = false;
foobar.with([&](const string&) { called = true; });
EXPECT_FALSE(called);
}
TEST_F(ConditionallyExistentTest, WhenConditionTrue) {
folly::ConditionallyExistent<string, true> foobar("hello world");
EXPECT_TRUE(foobar.present());
bool called = false;
foobar.with([&](const string&) { called = true; });
EXPECT_TRUE(called);
}
......@@ -159,6 +159,10 @@ string_test_SOURCES = StringTest.cpp
string_test_LDADD = libfollytestmain.la
TESTS += string_test
conditionally_existent_test_SOURCES = ConditionallyExistent.cpp
conditionally_existent_test_LDADD = libfollytestmain.la
TESTS += conditionally_existent_test
producer_consumer_queue_test_SOURCES = ProducerConsumerQueueTest.cpp
producer_consumer_queue_test_LDADD = libfollytestmain.la
TESTS += producer_consumer_queue_test
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment