1 /* 2 * Copyright 2022 The Android Open Source Project 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 #include <utility> 21 22 namespace android::ftl { 23 24 // The unit type, and its only value. 25 constexpr struct Unit { 26 } unit; 27 28 constexpr bool operator==(Unit, Unit) { 29 return true; 30 } 31 32 constexpr bool operator!=(Unit, Unit) { 33 return false; 34 } 35 36 // Adapts a function object F to return Unit. The return value of F is ignored. 37 // 38 // As a practical use, the function passed to ftl::Optional<T>::transform is not allowed to return 39 // void (cf. https://wg21.link/P0798R8#mapping-functions-returning-void), but may return Unit if 40 // only its side effects are meaningful: 41 // 42 // ftl::Optional opt = "food"s; 43 // opt.transform(ftl::unit_fn([](std::string& str) { str.pop_back(); })); 44 // assert(opt == "foo"s); 45 // 46 template <typename F> 47 struct UnitFn { 48 F f; 49 50 template <typename... Args> operatorUnitFn51 Unit operator()(Args&&... args) { 52 return f(std::forward<Args>(args)...), unit; 53 } 54 }; 55 56 template <typename F> 57 constexpr auto unit_fn(F&& f) -> UnitFn<std::decay_t<F>> { 58 return {std::forward<F>(f)}; 59 } 60 61 namespace details { 62 63 // Identity function for all T except Unit, which maps to void. 64 template <typename T> 65 struct UnitToVoid { 66 template <typename U> fromUnitToVoid67 static auto from(U&& value) { 68 return value; 69 } 70 }; 71 72 template <> 73 struct UnitToVoid<Unit> { 74 template <typename U> 75 static void from(U&&) {} 76 }; 77 78 } // namespace details 79 } // namespace android::ftl 80