From b94e117faab7e0feb5c5e92b2bb7c9d1e16f2c5a Mon Sep 17 00:00:00 2001 From: Hong Shin Date: Tue, 21 May 2024 12:37:42 -0700 Subject: [PATCH] Port C++20 Requires to it's C++17 equivalent for reuse across protos PiperOrigin-RevId: 635894605 --- protos/BUILD | 6 ++++++ protos/requires.h | 17 +++++++++++++++++ protos_generator/tests/BUILD | 1 + protos_generator/tests/test_generated.cc | 8 ++------ 4 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 protos/requires.h diff --git a/protos/BUILD b/protos/BUILD index 0e0032c37b..76c287e4fb 100644 --- a/protos/BUILD +++ b/protos/BUILD @@ -167,3 +167,9 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_library( + name = "requires", + hdrs = ["requires.h"], + visibility = ["//visibility:public"], +) diff --git a/protos/requires.h b/protos/requires.h new file mode 100644 index 0000000000..f7ea016392 --- /dev/null +++ b/protos/requires.h @@ -0,0 +1,17 @@ +#ifndef THIRD_PARTY_UPB_PROTOS_REQUIRES_H_ +#define THIRD_PARTY_UPB_PROTOS_REQUIRES_H_ + +#include +namespace protos::internal { +// Ports C++20 `requires` to C++17. +// C++20 ideal: +// if constexpr (requires { t.foo(); }) { ... } +// Our C++17 stopgap solution: +// if constexpr (Requires([](auto x) -> decltype(x.foo()) {})) { ... } +template +constexpr bool Requires(F) { + return std::is_invocable_v; +} +} // namespace protos::internal + +#endif // THIRD_PARTY_UPB_PROTOS_REQUIRES_H_ diff --git a/protos_generator/tests/BUILD b/protos_generator/tests/BUILD index fabee7fe4a..98042ca09c 100644 --- a/protos_generator/tests/BUILD +++ b/protos_generator/tests/BUILD @@ -131,6 +131,7 @@ cc_test( "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "//protos", + "//protos:requires", "//upb:mem", "//protos:repeated_field", ], diff --git a/protos_generator/tests/test_generated.cc b/protos_generator/tests/test_generated.cc index 208a1be80a..61bd66fd6e 100644 --- a/protos_generator/tests/test_generated.cc +++ b/protos_generator/tests/test_generated.cc @@ -21,6 +21,7 @@ #include "protos/protos.h" #include "protos/repeated_field.h" #include "protos/repeated_field_iterator.h" +#include "protos/requires.h" #include "protos_generator/tests/child_model.upb.proto.h" #include "protos_generator/tests/no_package.upb.proto.h" #include "protos_generator/tests/test_model.upb.proto.h" @@ -29,6 +30,7 @@ namespace { +using ::protos::internal::Requires; using ::protos_generator::test::protos::ChildModel1; using ::protos_generator::test::protos::container_ext; using ::protos_generator::test::protos::ContainerExtension; @@ -44,12 +46,6 @@ using ::protos_generator::test::protos::theme; using ::protos_generator::test::protos::ThemeExtension; using ::testing::ElementsAre; -// C++17 port of C++20 `requires` -template -constexpr bool Requires(F) { - return std::is_invocable_v; -} - TEST(CppGeneratedCode, Constructor) { TestModel test_model; } TEST(CppGeneratedCode, MessageEnum) { EXPECT_EQ(5, TestModel_Category_IMAGES); }