1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #pragma once
7 
8 #include <type_traits>
9 
10 namespace folly {
11 
12 /// In functional programming, the degenerate case is often called "unit". In
13 /// C++, "void" is often the best analogue. However, because of the syntactic
14 /// special-casing required for void, it is frequently a liability for template
15 /// metaprogramming. So, instead of writing specializations to handle cases like
16 /// SomeContainer<void>, a library author may instead rule that out and simply
17 /// have library users use SomeContainer<Unit>. Contained values may be ignored.
18 /// Much easier.
19 ///
20 /// "void" is the type that admits of no values at all. It is not possible to
21 /// construct a value of this type.
22 /// "unit" is the type that admits of precisely one unique value. It is
23 /// possible to construct a value of this type, but it is always the same value
24 /// every time, so it is uninteresting.
25 struct Unit {
26   constexpr bool operator==(const Unit& /*other*/) const {
27     return true;
28   }
29   constexpr bool operator!=(const Unit& /*other*/) const {
30     return false;
31   }
32 };
33 
34 constexpr Unit unit{};
35 
36 template <typename T>
37 struct lift_unit {
38   using type = T;
39 };
40 template <>
41 struct lift_unit<void> {
42   using type = Unit;
43 };
44 template <typename T>
45 using lift_unit_t = typename lift_unit<T>::type;
46 
47 template <typename T>
48 struct drop_unit {
49   using type = T;
50 };
51 template <>
52 struct drop_unit<Unit> {
53   using type = void;
54 };
55 template <typename T>
56 using drop_unit_t = typename drop_unit<T>::type;
57 
58 } // namespace folly
59 
60