1 // Copyright 2023 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: overload.h 17 // ----------------------------------------------------------------------------- 18 // 19 // `absl::Overload` is a functor that provides overloads based on the functors 20 // with which it is created. This can, for example, be used to locally define an 21 // anonymous visitor type for `std::visit` inside a function using lambdas. 22 // 23 // Before using this function, consider whether named function overloads would 24 // be a better design. 25 // 26 // Note: absl::Overload requires C++17. 27 // 28 // Example: 29 // 30 // std::variant<std::string, int32_t, int64_t> v(int32_t{1}); 31 // const size_t result = 32 // std::visit(absl::Overload{ 33 // [](const std::string& s) { return s.size(); }, 34 // [](const auto& s) { return sizeof(s); }, 35 // }, 36 // v); 37 // assert(result == 4); 38 // 39 40 #ifndef ABSL_FUNCTIONAL_OVERLOAD_H_ 41 #define ABSL_FUNCTIONAL_OVERLOAD_H_ 42 43 #include "absl/base/config.h" 44 #include "absl/meta/type_traits.h" 45 46 namespace absl { 47 ABSL_NAMESPACE_BEGIN 48 49 #if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ 50 ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L 51 52 template <typename... T> 53 struct Overload final : T... { 54 using T::operator()...; 55 56 // For historical reasons we want to support use that looks like a function 57 // call: 58 // 59 // absl::Overload(lambda_1, lambda_2) 60 // 61 // This works automatically in C++20 because we have support for parenthesized 62 // aggregate initialization. Before then we must provide a constructor that 63 // makes this work. 64 // 65 constexpr explicit Overload(T... ts) : T(std::move(ts))... {} 66 }; 67 68 // Before C++20, which added support for CTAD for aggregate types, we must also 69 // teach the compiler how to deduce the template arguments for Overload. 70 // 71 template <typename... T> 72 Overload(T...) -> Overload<T...>; 73 74 #else 75 76 namespace functional_internal { 77 template <typename T> 78 constexpr bool kDependentFalse = false; 79 } 80 81 template <typename Dependent = int, typename... T> 82 auto Overload(T&&...) { 83 static_assert(functional_internal::kDependentFalse<Dependent>, 84 "Overload is only usable with C++17 or above."); 85 } 86 87 #endif 88 89 ABSL_NAMESPACE_END 90 } // namespace absl 91 92 #endif // ABSL_FUNCTIONAL_OVERLOAD_H_ 93