Commit a0b102c3 by Martijn Vels Committed by Copybara-Service

Add absl::is_constant_evaluated for pre-c++20 support

PiperOrigin-RevId: 503437019
Change-Id: I3630fec690f1472130fef21b16dfcd3c5208aa69
parent c611e5ce
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment