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