mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 20:14:23 +08:00
Add absl::is_constant_evaluated for pre-c++20 support
PiperOrigin-RevId: 503437019 Change-Id: I3630fec690f1472130fef21b16dfcd3c5208aa69
This commit is contained in:
committed by
Copybara-Service
parent
c611e5ce1d
commit
a0b102c35b
@@ -928,4 +928,15 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#define ABSL_INTERNAL_HAVE_ARM_NEON 1
|
||||
#endif
|
||||
|
||||
// ABSL_HAVE_CONSTANT_EVALUATED is used for compile-time detection of
|
||||
// constant evaluation support through `absl::is_constant_evaluated`.
|
||||
#ifdef ABSL_HAVE_CONSTANT_EVALUATED
|
||||
#error ABSL_HAVE_CONSTANT_EVALUATED cannot be directly set
|
||||
#endif
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
#define ABSL_HAVE_CONSTANT_EVALUATED 1
|
||||
#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
|
||||
#define ABSL_HAVE_CONSTANT_EVALUATED 1
|
||||
#endif
|
||||
|
||||
#endif // ABSL_BASE_CONFIG_H_
|
||||
|
||||
@@ -42,7 +42,9 @@ cc_test(
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":type_traits",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/time",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -34,6 +34,8 @@ absl_cc_test(
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::time
|
||||
absl::core_headers
|
||||
absl::type_traits
|
||||
GTest::gmock_main
|
||||
|
||||
@@ -844,6 +844,45 @@ template <class T>
|
||||
struct is_trivially_relocatable : std::integral_constant<bool, false> {};
|
||||
#endif
|
||||
|
||||
// absl::is_constant_evaluated()
|
||||
//
|
||||
// Detects whether the function call occurs within a constant-evaluated context.
|
||||
// Returns true if the evaluation of the call occurs within the evaluation of an
|
||||
// expression or conversion that is manifestly constant-evaluated; otherwise
|
||||
// returns false.
|
||||
//
|
||||
// This function is implemented in terms of `std::is_constant_evaluated` for
|
||||
// c++20 and up. For older c++ versions, the function is implemented in terms
|
||||
// of `__builtin_is_constant_evaluated` if available, otherwise the function
|
||||
// will fail to compile.
|
||||
//
|
||||
// Applications can inspect `ABSL_HAVE_CONSTANT_EVALUATED` at compile time
|
||||
// to check if this function is supported.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// constexpr MyClass::MyClass(int param) {
|
||||
// #ifdef ABSL_HAVE_CONSTANT_EVALUATED
|
||||
// if (!absl::is_constant_evaluated()) {
|
||||
// ABSL_LOG(INFO) << "MyClass(" << param << ")";
|
||||
// }
|
||||
// #endif // ABSL_HAVE_CONSTANT_EVALUATED
|
||||
// }
|
||||
//
|
||||
// Upstream documentation:
|
||||
//
|
||||
// http://en.cppreference.com/w/cpp/types/is_constant_evaluated
|
||||
// http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#:~:text=__builtin_is_constant_evaluated
|
||||
//
|
||||
#if defined(ABSL_HAVE_CONSTANT_EVALUATED)
|
||||
constexpr bool is_constant_evaluated() noexcept {
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
return std::is_constant_evaluated();
|
||||
#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
|
||||
return __builtin_is_constant_evaluated();
|
||||
#endif
|
||||
}
|
||||
#endif // ABSL_HAVE_CONSTANT_EVALUATED
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -1413,4 +1416,33 @@ TEST(TrivallyRelocatable, Sanity) {
|
||||
EXPECT_TRUE(absl::is_trivially_relocatable<TrivialAbi>::value);
|
||||
}
|
||||
|
||||
#ifdef ABSL_HAVE_CONSTANT_EVALUATED
|
||||
|
||||
constexpr int64_t NegateIfConstantEvaluated(int64_t i) {
|
||||
if (absl::is_constant_evaluated()) {
|
||||
return -i;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ABSL_HAVE_CONSTANT_EVALUATED
|
||||
|
||||
TEST(TrivallyRelocatable, is_constant_evaluated) {
|
||||
#ifdef ABSL_HAVE_CONSTANT_EVALUATED
|
||||
constexpr int64_t constant = NegateIfConstantEvaluated(42);
|
||||
EXPECT_EQ(constant, -42);
|
||||
|
||||
int64_t now = absl::ToUnixSeconds(absl::Now());
|
||||
int64_t not_constant = NegateIfConstantEvaluated(now);
|
||||
EXPECT_EQ(not_constant, now);
|
||||
|
||||
static int64_t const_init = NegateIfConstantEvaluated(42);
|
||||
EXPECT_EQ(const_init, -42);
|
||||
#else
|
||||
GTEST_SKIP() << "absl::is_constant_evaluated is not defined";
|
||||
#endif // ABSL_HAVE_CONSTANT_EVALUATED
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user