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 {
/// possible to construct a value of this type, but it is always the same value
/// every time, so it is uninteresting.
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 {
return true;
}
......@@ -59,4 +44,26 @@ struct 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
......@@ -64,9 +64,9 @@ class FutureExecutor : public ExecutorImpl {
template <typename F>
typename std::enable_if<
!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) {
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;
auto future = promise.getFuture();
ExecutorImpl::add(
......
......@@ -23,9 +23,9 @@ namespace fibers {
template <typename F>
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 FutureT = typename folly::Unit::Lift<T>::type;
using FutureT = typename folly::lift_unit<T>::type;
folly::Promise<FutureT> p;
auto f = p.getFuture();
......@@ -39,8 +39,8 @@ auto FiberManager::addTaskFuture(F&& func)
template <typename F>
auto FiberManager::addTaskRemoteFuture(F&& func)
-> folly::Future<typename folly::Unit::Lift<invoke_result_t<F>>::type> {
folly::Promise<typename folly::Unit::Lift<invoke_result_t<F>>::type> p;
-> folly::Future<typename folly::lift_unit<invoke_result_t<F>>::type> {
folly::Promise<typename folly::lift_unit<invoke_result_t<F>>::type> p;
auto f = p.getFuture();
addTaskRemote(
[ p = std::move(p), func = std::forward<F>(func), this ]() mutable {
......
......@@ -206,7 +206,7 @@ class FiberManager : public ::folly::Executor {
*/
template <typename F>
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.
*
......@@ -225,7 +225,7 @@ class FiberManager : public ::folly::Executor {
*/
template <typename F>
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
void add(folly::Func f) override {
......
......@@ -625,9 +625,9 @@ typename std::
template <class F>
typename std::enable_if<
!(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) {
using LiftedResult = Unit::LiftT<invoke_result_t<F>>;
using LiftedResult = lift_unit_t<invoke_result_t<F>>;
return makeSemiFuture<LiftedResult>(
makeTryWith([&func]() mutable { return std::forward<F>(func)(); }));
}
......@@ -1209,9 +1209,9 @@ typename std::
template <class F>
typename std::enable_if<
!(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) {
using LiftedResult = Unit::LiftT<invoke_result_t<F>>;
using LiftedResult = lift_unit_t<invoke_result_t<F>>;
return makeFuture<LiftedResult>(
makeTryWith([&func]() mutable { return std::forward<F>(func)(); }));
}
......
......@@ -26,7 +26,7 @@ class SemiFuture;
template <typename T>
struct isSemiFuture : std::false_type {
using Inner = typename Unit::Lift<T>::type;
using Inner = typename lift_unit<T>::type;
};
template <typename T>
......@@ -36,7 +36,7 @@ struct isSemiFuture<SemiFuture<T>> : std::true_type {
template <typename T>
struct isFuture : std::false_type {
using Inner = typename Unit::Lift<T>::type;
using Inner = typename lift_unit<T>::type;
};
template <typename T>
......@@ -46,7 +46,7 @@ struct isFuture<Future<T>> : std::true_type {
template <typename T>
struct isFutureOrSemiFuture : std::false_type {
using Inner = typename Unit::Lift<T>::type;
using Inner = typename lift_unit<T>::type;
using Return = Inner;
};
......
......@@ -152,7 +152,7 @@ typename std::
template <class F>
typename std::enable_if<
!(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);
/// Make a failed Future from an exception_ptr.
......@@ -236,7 +236,7 @@ typename std::
template <class F>
typename std::enable_if<
!(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);
/// Make a failed Future from an exception_ptr.
......
......@@ -29,37 +29,37 @@ TEST(Unit, operatorNe) {
}
TEST(Unit, liftInt) {
using lifted = Unit::Lift<int>;
using actual = std::is_same<int, lifted::type>;
using lifted = lift_unit_t<int>;
using actual = std::is_same<int, lifted>;
EXPECT_TRUE(actual::value);
}
TEST(Unit, liftUnit) {
using lifted = Unit::Lift<Unit>;
using actual = std::is_same<Unit, lifted::type>;
using lifted = lift_unit_t<Unit>;
using actual = std::is_same<Unit, lifted>;
EXPECT_TRUE(actual::value);
}
TEST(Unit, liftVoid) {
using lifted = Unit::Lift<void>;
using actual = std::is_same<Unit, lifted::type>;
using lifted = lift_unit_t<void>;
using actual = std::is_same<Unit, lifted>;
EXPECT_TRUE(actual::value);
}
TEST(Unit, dropInt) {
using dropped = Unit::Drop<int>;
using actual = std::is_same<int, dropped::type>;
using dropped = drop_unit_t<int>;
using actual = std::is_same<int, dropped>;
EXPECT_TRUE(actual::value);
}
TEST(Unit, dropUnit) {
using dropped = Unit::Drop<Unit>;
using actual = std::is_same<void, dropped::type>;
using dropped = drop_unit_t<Unit>;
using actual = std::is_same<void, dropped>;
EXPECT_TRUE(actual::value);
}
TEST(Unit, dropVoid) {
using dropped = Unit::Drop<void>;
using actual = std::is_same<void, dropped::type>;
using dropped = drop_unit_t<void>;
using actual = std::is_same<void, dropped>;
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