1*9356374aSAndroid Build Coastguard Worker // Copyright 2023 The Abseil Authors
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker // The IfConstexpr and IfConstexprElse utilities in this file are meant to be
16*9356374aSAndroid Build Coastguard Worker // used to emulate `if constexpr` in pre-C++17 mode in library implementation.
17*9356374aSAndroid Build Coastguard Worker // The motivation is to allow for avoiding complex SFINAE.
18*9356374aSAndroid Build Coastguard Worker //
19*9356374aSAndroid Build Coastguard Worker // The functions passed in must depend on the type(s) of the object(s) that
20*9356374aSAndroid Build Coastguard Worker // require SFINAE. For example:
21*9356374aSAndroid Build Coastguard Worker // template<typename T>
22*9356374aSAndroid Build Coastguard Worker // int MaybeFoo(T& t) {
23*9356374aSAndroid Build Coastguard Worker // if constexpr (HasFoo<T>::value) return t.foo();
24*9356374aSAndroid Build Coastguard Worker // return 0;
25*9356374aSAndroid Build Coastguard Worker // }
26*9356374aSAndroid Build Coastguard Worker //
27*9356374aSAndroid Build Coastguard Worker // can be written in pre-C++17 as:
28*9356374aSAndroid Build Coastguard Worker //
29*9356374aSAndroid Build Coastguard Worker // template<typename T>
30*9356374aSAndroid Build Coastguard Worker // int MaybeFoo(T& t) {
31*9356374aSAndroid Build Coastguard Worker // int i = 0;
32*9356374aSAndroid Build Coastguard Worker // absl::utility_internal::IfConstexpr<HasFoo<T>::value>(
33*9356374aSAndroid Build Coastguard Worker // [&](const auto& fooer) { i = fooer.foo(); }, t);
34*9356374aSAndroid Build Coastguard Worker // return i;
35*9356374aSAndroid Build Coastguard Worker // }
36*9356374aSAndroid Build Coastguard Worker
37*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
38*9356374aSAndroid Build Coastguard Worker #define ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
39*9356374aSAndroid Build Coastguard Worker
40*9356374aSAndroid Build Coastguard Worker #include <tuple>
41*9356374aSAndroid Build Coastguard Worker #include <utility>
42*9356374aSAndroid Build Coastguard Worker
43*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
44*9356374aSAndroid Build Coastguard Worker
45*9356374aSAndroid Build Coastguard Worker namespace absl {
46*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
47*9356374aSAndroid Build Coastguard Worker
48*9356374aSAndroid Build Coastguard Worker namespace utility_internal {
49*9356374aSAndroid Build Coastguard Worker
50*9356374aSAndroid Build Coastguard Worker template <bool condition, typename TrueFunc, typename FalseFunc,
51*9356374aSAndroid Build Coastguard Worker typename... Args>
IfConstexprElse(TrueFunc && true_func,FalseFunc && false_func,Args &&...args)52*9356374aSAndroid Build Coastguard Worker auto IfConstexprElse(TrueFunc&& true_func, FalseFunc&& false_func,
53*9356374aSAndroid Build Coastguard Worker Args&&... args) {
54*9356374aSAndroid Build Coastguard Worker return std::get<condition>(std::forward_as_tuple(
55*9356374aSAndroid Build Coastguard Worker std::forward<FalseFunc>(false_func), std::forward<TrueFunc>(true_func)))(
56*9356374aSAndroid Build Coastguard Worker std::forward<Args>(args)...);
57*9356374aSAndroid Build Coastguard Worker }
58*9356374aSAndroid Build Coastguard Worker
59*9356374aSAndroid Build Coastguard Worker template <bool condition, typename Func, typename... Args>
IfConstexpr(Func && func,Args &&...args)60*9356374aSAndroid Build Coastguard Worker void IfConstexpr(Func&& func, Args&&... args) {
61*9356374aSAndroid Build Coastguard Worker IfConstexprElse<condition>(std::forward<Func>(func), [](auto&&...){},
62*9356374aSAndroid Build Coastguard Worker std::forward<Args>(args)...);
63*9356374aSAndroid Build Coastguard Worker }
64*9356374aSAndroid Build Coastguard Worker
65*9356374aSAndroid Build Coastguard Worker } // namespace utility_internal
66*9356374aSAndroid Build Coastguard Worker
67*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
68*9356374aSAndroid Build Coastguard Worker } // namespace absl
69*9356374aSAndroid Build Coastguard Worker
70*9356374aSAndroid Build Coastguard Worker #endif // ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
71