Skip to content

Commit ab8fec8

Browse files
ckennellycopybara-github
authored andcommitted
[meta] Add constexpr testing helper.
PiperOrigin-RevId: 846383067 Change-Id: Ia8dbbb805f59eb4cb5334290c3e24e0117777ca2
1 parent 641721e commit ab8fec8

File tree

4 files changed

+162
-0
lines changed

4 files changed

+162
-0
lines changed

absl/meta/BUILD.bazel

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,32 @@ package(
3434

3535
licenses(["notice"])
3636

37+
cc_library(
38+
name = "constexpr_testing",
39+
testonly = 1,
40+
hdrs = ["internal/constexpr_testing.h"],
41+
copts = ABSL_DEFAULT_COPTS,
42+
linkopts = ABSL_DEFAULT_LINKOPTS,
43+
visibility = [
44+
"//absl:__subpackages__",
45+
],
46+
deps = [
47+
"//absl/base:config",
48+
],
49+
)
50+
51+
cc_test(
52+
name = "constexpr_testing_test",
53+
srcs = ["internal/constexpr_testing_test.cc"],
54+
copts = ABSL_TEST_COPTS,
55+
linkopts = ABSL_DEFAULT_LINKOPTS,
56+
deps = [
57+
":constexpr_testing",
58+
"@googletest//:gtest",
59+
"@googletest//:gtest_main",
60+
],
61+
)
62+
3763
cc_library(
3864
name = "requires",
3965
hdrs = ["internal/requires.h"],

absl/meta/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,29 @@
1414
# limitations under the License.
1515
#
1616

17+
absl_cc_library(
18+
NAME
19+
constexpr_testing_internal
20+
HDRS
21+
"internal/constexpr_testing.h"
22+
COPTS
23+
${ABSL_DEFAULT_COPTS}
24+
DEPS
25+
absl::config
26+
)
27+
28+
absl_cc_test(
29+
NAME
30+
constexpr_testing_test
31+
SRCS
32+
"internal/constexpr_testing_test.cc"
33+
COPTS
34+
${ABSL_TEST_COPTS}
35+
DEPS
36+
absl::constexpr_testing_internal
37+
GTest::gmock_main
38+
)
39+
1740
absl_cc_library(
1841
NAME
1942
requires_internal
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2025 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+
15+
#ifndef ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_
16+
#define ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_
17+
18+
#include <type_traits>
19+
20+
#include "absl/base/config.h"
21+
22+
namespace absl {
23+
ABSL_NAMESPACE_BEGIN
24+
namespace meta_internal {
25+
26+
// HasConstexprEvaluation([] { ... }) will evaluate to `true` if the
27+
// lambda can be evaluated in a constant expression and `false`
28+
// otherwise.
29+
// The return type of the lambda is not relevant, as long as the whole
30+
// evaluation works in a constant expression.
31+
template <typename F>
32+
constexpr bool HasConstexprEvaluation(F f);
33+
34+
/// Implementation details below ///
35+
36+
namespace internal_constexpr_evaluation {
37+
38+
#ifdef __clang__
39+
#pragma clang diagnostic push
40+
#pragma clang diagnostic ignored "-Wuninitialized"
41+
#endif
42+
// This will give a constexpr instance of `F`.
43+
// This works for captureless lambdas because they have no state and the copy
44+
// constructor does not look at the input reference.
45+
template <typename F>
46+
constexpr F default_instance = default_instance<F>;
47+
#ifdef __clang__
48+
#pragma clang diagnostic pop
49+
#endif
50+
51+
template <typename F>
52+
constexpr std::integral_constant<bool, (default_instance<F>(), true)> Tester(
53+
int) {
54+
return {};
55+
}
56+
57+
template <typename S>
58+
constexpr std::false_type Tester(char) {
59+
return {};
60+
}
61+
62+
} // namespace internal_constexpr_evaluation
63+
64+
template <typename F>
65+
constexpr bool HasConstexprEvaluation(F) {
66+
return internal_constexpr_evaluation::Tester<F>(0);
67+
}
68+
69+
} // namespace meta_internal
70+
ABSL_NAMESPACE_END
71+
} // namespace absl
72+
73+
#endif // ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2025 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+
15+
#include "absl/meta/internal/constexpr_testing.h"
16+
17+
#include <map>
18+
#include <string_view>
19+
20+
#include "gmock/gmock.h"
21+
#include "gtest/gtest.h"
22+
23+
namespace {
24+
25+
TEST(ConstexprTesting, Basic) {
26+
using absl::meta_internal::HasConstexprEvaluation;
27+
28+
EXPECT_TRUE(HasConstexprEvaluation([] {}));
29+
static constexpr int const_global = 7;
30+
EXPECT_TRUE(HasConstexprEvaluation([] { return const_global; }));
31+
EXPECT_TRUE(HasConstexprEvaluation([] { return 0; }));
32+
EXPECT_TRUE(HasConstexprEvaluation([] { return std::string_view{}; }));
33+
34+
static int nonconst_global;
35+
EXPECT_FALSE(HasConstexprEvaluation([] { return nonconst_global; }));
36+
EXPECT_FALSE(HasConstexprEvaluation([] { std::abort(); }));
37+
EXPECT_FALSE(HasConstexprEvaluation([] { return std::map<int, int>(); }));
38+
}
39+
40+
} // namespace

0 commit comments

Comments
 (0)