[meta] Add constexpr testing helper.
PiperOrigin-RevId: 846383067
Change-Id: Ia8dbbb805f59eb4cb5334290c3e24e0117777ca2
diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel
index 406e524..26468c6 100644
--- a/absl/meta/BUILD.bazel
+++ b/absl/meta/BUILD.bazel
@@ -35,6 +35,32 @@
licenses(["notice"])
cc_library(
+ name = "constexpr_testing",
+ testonly = 1,
+ hdrs = ["internal/constexpr_testing.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ "//absl/base:config",
+ ],
+)
+
+cc_test(
+ name = "constexpr_testing_test",
+ srcs = ["internal/constexpr_testing_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":constexpr_testing",
+ "@googletest//:gtest",
+ "@googletest//:gtest_main",
+ ],
+)
+
+cc_library(
name = "requires",
hdrs = ["internal/requires.h"],
copts = ABSL_DEFAULT_COPTS,
diff --git a/absl/meta/CMakeLists.txt b/absl/meta/CMakeLists.txt
index 20650cc..c98c360 100644
--- a/absl/meta/CMakeLists.txt
+++ b/absl/meta/CMakeLists.txt
@@ -16,6 +16,29 @@
absl_cc_library(
NAME
+ constexpr_testing_internal
+ HDRS
+ "internal/constexpr_testing.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::config
+)
+
+absl_cc_test(
+ NAME
+ constexpr_testing_test
+ SRCS
+ "internal/constexpr_testing_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::constexpr_testing_internal
+ GTest::gmock_main
+)
+
+absl_cc_library(
+ NAME
requires_internal
HDRS
"internal/requires.h"
diff --git a/absl/meta/internal/constexpr_testing.h b/absl/meta/internal/constexpr_testing.h
new file mode 100644
index 0000000..eddf64b
--- /dev/null
+++ b/absl/meta/internal/constexpr_testing.h
@@ -0,0 +1,73 @@
+// Copyright 2025 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_
+#define ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_
+
+#include <type_traits>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace meta_internal {
+
+// HasConstexprEvaluation([] { ... }) will evaluate to `true` if the
+// lambda can be evaluated in a constant expression and `false`
+// otherwise.
+// The return type of the lambda is not relevant, as long as the whole
+// evaluation works in a constant expression.
+template <typename F>
+constexpr bool HasConstexprEvaluation(F f);
+
+/// Implementation details below ///
+
+namespace internal_constexpr_evaluation {
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wuninitialized"
+#endif
+// This will give a constexpr instance of `F`.
+// This works for captureless lambdas because they have no state and the copy
+// constructor does not look at the input reference.
+template <typename F>
+constexpr F default_instance = default_instance<F>;
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+template <typename F>
+constexpr std::integral_constant<bool, (default_instance<F>(), true)> Tester(
+ int) {
+ return {};
+}
+
+template <typename S>
+constexpr std::false_type Tester(char) {
+ return {};
+}
+
+} // namespace internal_constexpr_evaluation
+
+template <typename F>
+constexpr bool HasConstexprEvaluation(F) {
+ return internal_constexpr_evaluation::Tester<F>(0);
+}
+
+} // namespace meta_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_
diff --git a/absl/meta/internal/constexpr_testing_test.cc b/absl/meta/internal/constexpr_testing_test.cc
new file mode 100644
index 0000000..50c8c53
--- /dev/null
+++ b/absl/meta/internal/constexpr_testing_test.cc
@@ -0,0 +1,40 @@
+// Copyright 2025 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/meta/internal/constexpr_testing.h"
+
+#include <map>
+#include <string_view>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+TEST(ConstexprTesting, Basic) {
+ using absl::meta_internal::HasConstexprEvaluation;
+
+ EXPECT_TRUE(HasConstexprEvaluation([] {}));
+ static constexpr int const_global = 7;
+ EXPECT_TRUE(HasConstexprEvaluation([] { return const_global; }));
+ EXPECT_TRUE(HasConstexprEvaluation([] { return 0; }));
+ EXPECT_TRUE(HasConstexprEvaluation([] { return std::string_view{}; }));
+
+ static int nonconst_global;
+ EXPECT_FALSE(HasConstexprEvaluation([] { return nonconst_global; }));
+ EXPECT_FALSE(HasConstexprEvaluation([] { std::abort(); }));
+ EXPECT_FALSE(HasConstexprEvaluation([] { return std::map<int, int>(); }));
+}
+
+} // namespace