blob: 7e19e7050308647e9b811646f4e848d07df9f9ab [file] [log] [blame]
Abseil Teamf4c62462023-09-26 02:49:04 -07001// 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//
Aaron Jacobse022c802024-04-23 18:29:14 -070019// `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//
Abseil Teamf4c62462023-09-26 02:49:04 -070023// Before using this function, consider whether named function overloads would
24// be a better design.
Vitaly Goldshteyn6bf3c732024-03-06 02:38:50 -080025//
26// Note: absl::Overload requires C++17.
Aaron Jacobse022c802024-04-23 18:29:14 -070027//
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//
Abseil Teamf4c62462023-09-26 02:49:04 -070039
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
46namespace absl {
47ABSL_NAMESPACE_BEGIN
48
49#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
50 ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
51
Aaron Jacobse022c802024-04-23 18:29:14 -070052template <typename... T>
53struct 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 //
Abseil Team49c1f362024-05-24 14:10:10 -070065 constexpr explicit Overload(T... ts) : T(std::move(ts))... {}
Aaron Jacobse022c802024-04-23 18:29:14 -070066};
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//
71template <typename... T>
72Overload(T...) -> Overload<T...>;
73
Abseil Teamf4c62462023-09-26 02:49:04 -070074#else
Aaron Jacobse022c802024-04-23 18:29:14 -070075
Abseil Teamf4c62462023-09-26 02:49:04 -070076namespace functional_internal {
77template <typename T>
78constexpr bool kDependentFalse = false;
79}
80
81template <typename Dependent = int, typename... T>
82auto Overload(T&&...) {
83 static_assert(functional_internal::kDependentFalse<Dependent>,
84 "Overload is only usable with C++17 or above.");
85}
86
87#endif
Aaron Jacobse022c802024-04-23 18:29:14 -070088
Abseil Teamf4c62462023-09-26 02:49:04 -070089ABSL_NAMESPACE_END
90} // namespace absl
91
92#endif // ABSL_FUNCTIONAL_OVERLOAD_H_