[meta] Add constexpr testing helper.

PiperOrigin-RevId: 846383067
Change-Id: Ia8dbbb805f59eb4cb5334290c3e24e0117777ca2
This commit is contained in:
Chris Kennelly
2025-12-18 12:57:29 -08:00
committed by Copybara-Service
parent 641721e94f
commit ab8fec82ff
4 changed files with 162 additions and 0 deletions

View File

@@ -34,6 +34,32 @@ package(
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"],

View File

@@ -14,6 +14,29 @@
# limitations under the License.
#
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

View File

@@ -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_

View File

@@ -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