if_constexpr.h 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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. // The IfConstexpr and IfConstexprElse utilities in this file are meant to be
  15. // used to emulate `if constexpr` in pre-C++17 mode in library implementation.
  16. // The motivation is to allow for avoiding complex SFINAE.
  17. //
  18. // The functions passed in must depend on the type(s) of the object(s) that
  19. // require SFINAE. For example:
  20. // template<typename T>
  21. // int MaybeFoo(T& t) {
  22. // if constexpr (HasFoo<T>::value) return t.foo();
  23. // return 0;
  24. // }
  25. //
  26. // can be written in pre-C++17 as:
  27. //
  28. // template<typename T>
  29. // int MaybeFoo(T& t) {
  30. // int i = 0;
  31. // y_absl::utility_internal::IfConstexpr<HasFoo<T>::value>(
  32. // [&](const auto& fooer) { i = fooer.foo(); }, t);
  33. // return i;
  34. // }
  35. #ifndef Y_ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
  36. #define Y_ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
  37. #include <tuple>
  38. #include <utility>
  39. #include "y_absl/base/config.h"
  40. namespace y_absl {
  41. Y_ABSL_NAMESPACE_BEGIN
  42. namespace utility_internal {
  43. template <bool condition, typename TrueFunc, typename FalseFunc,
  44. typename... Args>
  45. auto IfConstexprElse(TrueFunc&& true_func, FalseFunc&& false_func,
  46. Args&&... args) {
  47. return std::get<condition>(std::forward_as_tuple(
  48. std::forward<FalseFunc>(false_func), std::forward<TrueFunc>(true_func)))(
  49. std::forward<Args>(args)...);
  50. }
  51. template <bool condition, typename Func, typename... Args>
  52. void IfConstexpr(Func&& func, Args&&... args) {
  53. IfConstexprElse<condition>(std::forward<Func>(func), [](auto&&...){},
  54. std::forward<Args>(args)...);
  55. }
  56. } // namespace utility_internal
  57. Y_ABSL_NAMESPACE_END
  58. } // namespace y_absl
  59. #endif // Y_ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_