1 | /* |
2 | * Copyright 2015-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #pragma once |
18 | |
19 | #include <type_traits> |
20 | |
21 | namespace folly { |
22 | |
23 | /// In functional programming, the degenerate case is often called "unit". In |
24 | /// C++, "void" is often the best analogue. However, because of the syntactic |
25 | /// special-casing required for void, it is frequently a liability for template |
26 | /// metaprogramming. So, instead of writing specializations to handle cases like |
27 | /// SomeContainer<void>, a library author may instead rule that out and simply |
28 | /// have library users use SomeContainer<Unit>. Contained values may be ignored. |
29 | /// Much easier. |
30 | /// |
31 | /// "void" is the type that admits of no values at all. It is not possible to |
32 | /// construct a value of this type. |
33 | /// "unit" is the type that admits of precisely one unique value. It is |
34 | /// possible to construct a value of this type, but it is always the same value |
35 | /// every time, so it is uninteresting. |
36 | struct Unit { |
37 | constexpr bool operator==(const Unit& /*other*/) const { |
38 | return true; |
39 | } |
40 | constexpr bool operator!=(const Unit& /*other*/) const { |
41 | return false; |
42 | } |
43 | }; |
44 | |
45 | constexpr Unit unit{}; |
46 | |
47 | template <typename T> |
48 | struct lift_unit { |
49 | using type = T; |
50 | }; |
51 | template <> |
52 | struct lift_unit<void> { |
53 | using type = Unit; |
54 | }; |
55 | template <typename T> |
56 | using lift_unit_t = typename lift_unit<T>::type; |
57 | |
58 | template <typename T> |
59 | struct drop_unit { |
60 | using type = T; |
61 | }; |
62 | template <> |
63 | struct drop_unit<Unit> { |
64 | using type = void; |
65 | }; |
66 | template <typename T> |
67 | using drop_unit_t = typename drop_unit<T>::type; |
68 | |
69 | } // namespace folly |
70 | |