Commit 6e612d3d authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Cut extra template instantiations from Unit traits

Summary: [Folly] Cut extra template instantiations from `Unit` traits - namely, `std::conditional` and `std::is_same`. The behavior can be done directly, while each extra template instantiations imposes some small compile-time cost.

Reviewed By: Orvid

Differential Revision: D8178033

fbshipit-source-id: 22ba5ae810e2bca616e7db332c1f635e2520f3a7
parent 95016602
...@@ -34,21 +34,6 @@ namespace folly { ...@@ -34,21 +34,6 @@ namespace folly {
/// possible to construct a value of this type, but it is always the same value /// possible to construct a value of this type, but it is always the same value
/// every time, so it is uninteresting. /// every time, so it is uninteresting.
struct Unit { struct Unit {
// These are structs rather than type aliases because MSVC 2017 RC has
// trouble correctly resolving dependent expressions in type aliases
// in certain very specific contexts, including a couple where this is
// used. See the known issues section here for more info:
// https://blogs.msdn.microsoft.com/vcblog/2016/06/07/expression-sfinae-improvements-in-vs-2015-update-3/
template <typename T>
struct Lift : std::conditional<std::is_same<T, void>::value, Unit, T> {};
template <typename T>
using LiftT = typename Lift<T>::type;
template <typename T>
struct Drop : std::conditional<std::is_same<T, Unit>::value, void, T> {};
template <typename T>
using DropT = typename Drop<T>::type;
constexpr bool operator==(const Unit& /*other*/) const { constexpr bool operator==(const Unit& /*other*/) const {
return true; return true;
} }
...@@ -59,4 +44,26 @@ struct Unit { ...@@ -59,4 +44,26 @@ struct Unit {
constexpr Unit unit {}; constexpr Unit unit {};
template <typename T>
struct lift_unit {
using type = T;
};
template <>
struct lift_unit<void> {
using type = Unit;
};
template <typename T>
using lift_unit_t = typename lift_unit<T>::type;
template <typename T>
struct drop_unit {
using type = T;
};
template <>
struct drop_unit<Unit> {
using type = void;
};
template <typename T>
using drop_unit_t = typename drop_unit<T>::type;
} // namespace folly } // namespace folly
...@@ -64,9 +64,9 @@ class FutureExecutor : public ExecutorImpl { ...@@ -64,9 +64,9 @@ class FutureExecutor : public ExecutorImpl {
template <typename F> template <typename F>
typename std::enable_if< typename std::enable_if<
!folly::isFuture<invoke_result_t<F>>::value, !folly::isFuture<invoke_result_t<F>>::value,
folly::Future<typename folly::Unit::Lift<invoke_result_t<F>>::type>>::type folly::Future<typename folly::lift_unit<invoke_result_t<F>>::type>>::type
addFuture(F func) { addFuture(F func) {
using T = typename folly::Unit::Lift<invoke_result_t<F>>::type; using T = typename folly::lift_unit<invoke_result_t<F>>::type;
folly::Promise<T> promise; folly::Promise<T> promise;
auto future = promise.getFuture(); auto future = promise.getFuture();
ExecutorImpl::add( ExecutorImpl::add(
......
...@@ -23,9 +23,9 @@ namespace fibers { ...@@ -23,9 +23,9 @@ namespace fibers {
template <typename F> template <typename F>
auto FiberManager::addTaskFuture(F&& func) auto FiberManager::addTaskFuture(F&& func)
-> folly::Future<typename folly::Unit::Lift<invoke_result_t<F>>::type> { -> folly::Future<typename folly::lift_unit<invoke_result_t<F>>::type> {
using T = invoke_result_t<F>; using T = invoke_result_t<F>;
using FutureT = typename folly::Unit::Lift<T>::type; using FutureT = typename folly::lift_unit<T>::type;
folly::Promise<FutureT> p; folly::Promise<FutureT> p;
auto f = p.getFuture(); auto f = p.getFuture();
...@@ -39,8 +39,8 @@ auto FiberManager::addTaskFuture(F&& func) ...@@ -39,8 +39,8 @@ auto FiberManager::addTaskFuture(F&& func)
template <typename F> template <typename F>
auto FiberManager::addTaskRemoteFuture(F&& func) auto FiberManager::addTaskRemoteFuture(F&& func)
-> folly::Future<typename folly::Unit::Lift<invoke_result_t<F>>::type> { -> folly::Future<typename folly::lift_unit<invoke_result_t<F>>::type> {
folly::Promise<typename folly::Unit::Lift<invoke_result_t<F>>::type> p; folly::Promise<typename folly::lift_unit<invoke_result_t<F>>::type> p;
auto f = p.getFuture(); auto f = p.getFuture();
addTaskRemote( addTaskRemote(
[ p = std::move(p), func = std::forward<F>(func), this ]() mutable { [ p = std::move(p), func = std::forward<F>(func), this ]() mutable {
......
...@@ -206,7 +206,7 @@ class FiberManager : public ::folly::Executor { ...@@ -206,7 +206,7 @@ class FiberManager : public ::folly::Executor {
*/ */
template <typename F> template <typename F>
auto addTaskFuture(F&& func) auto addTaskFuture(F&& func)
-> folly::Future<typename folly::Unit::Lift<invoke_result_t<F>>::type>; -> folly::Future<typename folly::lift_unit<invoke_result_t<F>>::type>;
/** /**
* Add a new task to be executed. Safe to call from other threads. * Add a new task to be executed. Safe to call from other threads.
* *
...@@ -225,7 +225,7 @@ class FiberManager : public ::folly::Executor { ...@@ -225,7 +225,7 @@ class FiberManager : public ::folly::Executor {
*/ */
template <typename F> template <typename F>
auto addTaskRemoteFuture(F&& func) auto addTaskRemoteFuture(F&& func)
-> folly::Future<typename folly::Unit::Lift<invoke_result_t<F>>::type>; -> folly::Future<typename folly::lift_unit<invoke_result_t<F>>::type>;
// Executor interface calls addTaskRemote // Executor interface calls addTaskRemote
void add(folly::Func f) override { void add(folly::Func f) override {
......
...@@ -625,9 +625,9 @@ typename std:: ...@@ -625,9 +625,9 @@ typename std::
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!(isSemiFuture<invoke_result_t<F>>::value), !(isSemiFuture<invoke_result_t<F>>::value),
SemiFuture<Unit::LiftT<invoke_result_t<F>>>>::type SemiFuture<lift_unit_t<invoke_result_t<F>>>>::type
makeSemiFutureWith(F&& func) { makeSemiFutureWith(F&& func) {
using LiftedResult = Unit::LiftT<invoke_result_t<F>>; using LiftedResult = lift_unit_t<invoke_result_t<F>>;
return makeSemiFuture<LiftedResult>( return makeSemiFuture<LiftedResult>(
makeTryWith([&func]() mutable { return std::forward<F>(func)(); })); makeTryWith([&func]() mutable { return std::forward<F>(func)(); }));
} }
...@@ -1209,9 +1209,9 @@ typename std:: ...@@ -1209,9 +1209,9 @@ typename std::
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!(isFuture<invoke_result_t<F>>::value), !(isFuture<invoke_result_t<F>>::value),
Future<Unit::LiftT<invoke_result_t<F>>>>::type Future<lift_unit_t<invoke_result_t<F>>>>::type
makeFutureWith(F&& func) { makeFutureWith(F&& func) {
using LiftedResult = Unit::LiftT<invoke_result_t<F>>; using LiftedResult = lift_unit_t<invoke_result_t<F>>;
return makeFuture<LiftedResult>( return makeFuture<LiftedResult>(
makeTryWith([&func]() mutable { return std::forward<F>(func)(); })); makeTryWith([&func]() mutable { return std::forward<F>(func)(); }));
} }
......
...@@ -26,7 +26,7 @@ class SemiFuture; ...@@ -26,7 +26,7 @@ class SemiFuture;
template <typename T> template <typename T>
struct isSemiFuture : std::false_type { struct isSemiFuture : std::false_type {
using Inner = typename Unit::Lift<T>::type; using Inner = typename lift_unit<T>::type;
}; };
template <typename T> template <typename T>
...@@ -36,7 +36,7 @@ struct isSemiFuture<SemiFuture<T>> : std::true_type { ...@@ -36,7 +36,7 @@ struct isSemiFuture<SemiFuture<T>> : std::true_type {
template <typename T> template <typename T>
struct isFuture : std::false_type { struct isFuture : std::false_type {
using Inner = typename Unit::Lift<T>::type; using Inner = typename lift_unit<T>::type;
}; };
template <typename T> template <typename T>
...@@ -46,7 +46,7 @@ struct isFuture<Future<T>> : std::true_type { ...@@ -46,7 +46,7 @@ struct isFuture<Future<T>> : std::true_type {
template <typename T> template <typename T>
struct isFutureOrSemiFuture : std::false_type { struct isFutureOrSemiFuture : std::false_type {
using Inner = typename Unit::Lift<T>::type; using Inner = typename lift_unit<T>::type;
using Return = Inner; using Return = Inner;
}; };
......
...@@ -152,7 +152,7 @@ typename std:: ...@@ -152,7 +152,7 @@ typename std::
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!(isSemiFuture<invoke_result_t<F>>::value), !(isSemiFuture<invoke_result_t<F>>::value),
SemiFuture<typename Unit::Lift<invoke_result_t<F>>::type>>::type SemiFuture<typename lift_unit<invoke_result_t<F>>::type>>::type
makeSemiFutureWith(F&& func); makeSemiFutureWith(F&& func);
/// Make a failed Future from an exception_ptr. /// Make a failed Future from an exception_ptr.
...@@ -236,7 +236,7 @@ typename std:: ...@@ -236,7 +236,7 @@ typename std::
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!(isFuture<invoke_result_t<F>>::value), !(isFuture<invoke_result_t<F>>::value),
Future<typename Unit::Lift<invoke_result_t<F>>::type>>::type Future<typename lift_unit<invoke_result_t<F>>::type>>::type
makeFutureWith(F&& func); makeFutureWith(F&& func);
/// Make a failed Future from an exception_ptr. /// Make a failed Future from an exception_ptr.
......
...@@ -29,37 +29,37 @@ TEST(Unit, operatorNe) { ...@@ -29,37 +29,37 @@ TEST(Unit, operatorNe) {
} }
TEST(Unit, liftInt) { TEST(Unit, liftInt) {
using lifted = Unit::Lift<int>; using lifted = lift_unit_t<int>;
using actual = std::is_same<int, lifted::type>; using actual = std::is_same<int, lifted>;
EXPECT_TRUE(actual::value); EXPECT_TRUE(actual::value);
} }
TEST(Unit, liftUnit) { TEST(Unit, liftUnit) {
using lifted = Unit::Lift<Unit>; using lifted = lift_unit_t<Unit>;
using actual = std::is_same<Unit, lifted::type>; using actual = std::is_same<Unit, lifted>;
EXPECT_TRUE(actual::value); EXPECT_TRUE(actual::value);
} }
TEST(Unit, liftVoid) { TEST(Unit, liftVoid) {
using lifted = Unit::Lift<void>; using lifted = lift_unit_t<void>;
using actual = std::is_same<Unit, lifted::type>; using actual = std::is_same<Unit, lifted>;
EXPECT_TRUE(actual::value); EXPECT_TRUE(actual::value);
} }
TEST(Unit, dropInt) { TEST(Unit, dropInt) {
using dropped = Unit::Drop<int>; using dropped = drop_unit_t<int>;
using actual = std::is_same<int, dropped::type>; using actual = std::is_same<int, dropped>;
EXPECT_TRUE(actual::value); EXPECT_TRUE(actual::value);
} }
TEST(Unit, dropUnit) { TEST(Unit, dropUnit) {
using dropped = Unit::Drop<Unit>; using dropped = drop_unit_t<Unit>;
using actual = std::is_same<void, dropped::type>; using actual = std::is_same<void, dropped>;
EXPECT_TRUE(actual::value); EXPECT_TRUE(actual::value);
} }
TEST(Unit, dropVoid) { TEST(Unit, dropVoid) {
using dropped = Unit::Drop<void>; using dropped = drop_unit_t<void>;
using actual = std::is_same<void, dropped::type>; using actual = std::is_same<void, dropped>;
EXPECT_TRUE(actual::value); EXPECT_TRUE(actual::value);
} }
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