* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#pragma once
+
+#include <type_traits>
+
namespace folly {
/// In functional programming, the degenerate case is often called "unit". In
/// You can ignore the actual value, and we port some of the syntactic
/// niceties like setValue() instead of setValue(Unit{}).
struct Unit {
- /// Lift type T into Unit. This is the definition for all non-void types.
- template <class T> struct Lift : public std::false_type {
- using type = T;
- };
- template <class T> struct Drop : public std::false_type {
- using type = T;
- };
+ template <typename T>
+ using Lift = std::conditional<std::is_same<T, void>::value, Unit, T>;
+ template <typename T>
+ using Drop = std::conditional<std::is_same<T, Unit>::value, void, T>;
+
bool operator==(const Unit& /*other*/) const { return true; }
bool operator!=(const Unit& /*other*/) const { return false; }
};
-// Lift void into Unit.
-template <>
-struct Unit::Lift<void> : public std::true_type {
- using type = Unit;
-};
-
-// Lift Unit into Unit (identity).
-template <>
-struct Unit::Lift<Unit> : public std::true_type {
- using type = Unit;
-};
-
-// Drop Unit into void.
-template <>
-struct Unit::Drop<Unit> : public std::true_type {
- using type = void;
-};
-
-// Drop void into void (identity).
-template <>
-struct Unit::Drop<void> : public std::true_type {
- using type = void;
-};
-
-template <class T>
-struct is_void_or_unit : public Unit::Lift<T>
-{};
-
constexpr Unit unit {};
}
#include <gtest/gtest.h>
#include <folly/futures/Future.h>
+#include <folly/futures/Unit.h>
using namespace folly;
EXPECT_FALSE(Unit{} != Unit{});
}
-TEST(Unit, voidOrUnit) {
- EXPECT_TRUE(is_void_or_unit<Unit>::value);
- EXPECT_TRUE(is_void_or_unit<Unit>::value);
- EXPECT_FALSE(is_void_or_unit<int>::value);
-}
-
TEST(Unit, promiseSetValue) {
Promise<Unit> p;
p.setValue();
}
TEST(Unit, liftInt) {
- using Lifted = Unit::Lift<int>;
- EXPECT_FALSE(Lifted::value);
- auto v = std::is_same<int, Lifted::type>::value;
- EXPECT_TRUE(v);
+ using lifted = Unit::Lift<int>;
+ using actual = std::is_same<int, lifted::type>;
+ EXPECT_TRUE(actual::value);
+}
+
+TEST(Unit, liftUnit) {
+ using lifted = Unit::Lift<Unit>;
+ using actual = std::is_same<Unit, lifted::type>;
+ EXPECT_TRUE(actual::value);
}
TEST(Unit, liftVoid) {
- using Lifted = Unit::Lift<Unit>;
- EXPECT_TRUE(Lifted::value);
- auto v = std::is_same<Unit, Lifted::type>::value;
- EXPECT_TRUE(v);
+ using lifted = Unit::Lift<void>;
+ using actual = std::is_same<Unit, lifted::type>;
+ EXPECT_TRUE(actual::value);
}
TEST(Unit, dropInt) {
- using dropped = typename Unit::Drop<int>;
- EXPECT_FALSE(dropped::value);
- EXPECT_TRUE((std::is_same<int, dropped::type>::value));
+ using dropped = Unit::Drop<int>;
+ using actual = std::is_same<int, dropped::type>;
+ EXPECT_TRUE(actual::value);
}
TEST(Unit, dropUnit) {
- using dropped = typename Unit::Drop<Unit>;
- EXPECT_TRUE(dropped::value);
- EXPECT_TRUE((std::is_void<dropped::type>::value));
+ using dropped = Unit::Drop<Unit>;
+ using actual = std::is_same<void, dropped::type>;
+ EXPECT_TRUE(actual::value);
}
TEST(Unit, dropVoid) {
- using dropped = typename Unit::Drop<void>;
- EXPECT_TRUE(dropped::value);
- EXPECT_TRUE((std::is_void<dropped::type>::value));
+ using dropped = Unit::Drop<void>;
+ using actual = std::is_same<void, dropped::type>;
+ EXPECT_TRUE(actual::value);
}
TEST(Unit, futureToUnit) {