xref: /aosp_15_r20/frameworks/native/include/ftl/details/match.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2022 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #pragma once
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <type_traits>
20*38e8c45fSAndroid Build Coastguard Worker #include <variant>
21*38e8c45fSAndroid Build Coastguard Worker 
22*38e8c45fSAndroid Build Coastguard Worker namespace android::ftl::details {
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker template <typename... Ms>
25*38e8c45fSAndroid Build Coastguard Worker struct Matcher : Ms... {
26*38e8c45fSAndroid Build Coastguard Worker   using Ms::operator()...;
27*38e8c45fSAndroid Build Coastguard Worker };
28*38e8c45fSAndroid Build Coastguard Worker 
29*38e8c45fSAndroid Build Coastguard Worker // Deduction guide.
30*38e8c45fSAndroid Build Coastguard Worker template <typename... Ms>
31*38e8c45fSAndroid Build Coastguard Worker Matcher(Ms...) -> Matcher<Ms...>;
32*38e8c45fSAndroid Build Coastguard Worker 
33*38e8c45fSAndroid Build Coastguard Worker template <typename Matcher, typename... Ts>
34*38e8c45fSAndroid Build Coastguard Worker constexpr bool is_exhaustive_match_v = (std::is_invocable_v<Matcher, Ts> && ...);
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker template <typename...>
37*38e8c45fSAndroid Build Coastguard Worker struct Match;
38*38e8c45fSAndroid Build Coastguard Worker 
39*38e8c45fSAndroid Build Coastguard Worker template <typename T, typename U, typename... Ts>
40*38e8c45fSAndroid Build Coastguard Worker struct Match<T, U, Ts...> {
41*38e8c45fSAndroid Build Coastguard Worker   template <typename Variant, typename Matcher>
42*38e8c45fSAndroid Build Coastguard Worker   static decltype(auto) match(Variant& variant, const Matcher& matcher) {
43*38e8c45fSAndroid Build Coastguard Worker     if (auto* const ptr = std::get_if<T>(&variant)) {
44*38e8c45fSAndroid Build Coastguard Worker       return matcher(*ptr);
45*38e8c45fSAndroid Build Coastguard Worker     } else {
46*38e8c45fSAndroid Build Coastguard Worker       return Match<U, Ts...>::match(variant, matcher);
47*38e8c45fSAndroid Build Coastguard Worker     }
48*38e8c45fSAndroid Build Coastguard Worker   }
49*38e8c45fSAndroid Build Coastguard Worker };
50*38e8c45fSAndroid Build Coastguard Worker 
51*38e8c45fSAndroid Build Coastguard Worker template <typename T>
52*38e8c45fSAndroid Build Coastguard Worker struct Match<T> {
53*38e8c45fSAndroid Build Coastguard Worker   template <typename Variant, typename Matcher>
54*38e8c45fSAndroid Build Coastguard Worker   static decltype(auto) match(Variant& variant, const Matcher& matcher) {
55*38e8c45fSAndroid Build Coastguard Worker     return matcher(std::get<T>(variant));
56*38e8c45fSAndroid Build Coastguard Worker   }
57*38e8c45fSAndroid Build Coastguard Worker };
58*38e8c45fSAndroid Build Coastguard Worker 
59*38e8c45fSAndroid Build Coastguard Worker }  // namespace android::ftl::details
60