1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 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 { return true; } 38 constexpr bool operator!=(const Unit& /*other*/) const { return false; } 39 }; 40 41 constexpr Unit unit{}; 42 43 template <typename T> 44 struct lift_unit { 45 using type = T; 46 }; 47 template <> 48 struct lift_unit<void> { 49 using type = Unit; 50 }; 51 template <typename T> 52 using lift_unit_t = typename lift_unit<T>::type; 53 54 template <typename T> 55 struct drop_unit { 56 using type = T; 57 }; 58 template <> 59 struct drop_unit<Unit> { 60 using type = void; 61 }; 62 template <typename T> 63 using drop_unit_t = typename drop_unit<T>::type; 64 65 } // namespace folly 66