summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2024-07-01 11:33:54 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2024-07-01 11:34:46 -0700
commit37ebde53cfcf400ef01b59c80ae3f72039cd90f2 (patch)
tree1977c5d4878e02cdaa96ed831f775e47bbd58f57
parenta27662352e9caafc264747562162a8a32ef36cb9 (diff)
Make c_begin, c_end, and c_distance conditionally constexpr.
This allows them to be used in constexpr expressions, such as the following: ``` constexpr int distance = absl::c_distance(std::array<int, 3>()); ``` Requires at least C++17 to be constexpr. PiperOrigin-RevId: 648435141 Change-Id: I8136e351a6dc4c25f06ef895fb449f4f11048480
-rw-r--r--absl/algorithm/BUILD.bazel2
-rw-r--r--absl/algorithm/CMakeLists.txt2
-rw-r--r--absl/algorithm/container.h14
-rw-r--r--absl/algorithm/container_test.cc11
-rw-r--r--absl/base/config.h21
5 files changed, 44 insertions, 6 deletions
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index ddf9e11f..f20e7290 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -65,6 +65,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":algorithm",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:nullability",
"//absl/meta:type_traits",
@@ -79,6 +80,7 @@ cc_test(
deps = [
":container",
"//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
"//absl/types:span",
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index 5577164d..252b6b20 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -48,6 +48,7 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::algorithm
+ absl::config
absl::core_headers
absl::meta
absl::nullability
@@ -64,6 +65,7 @@ absl_cc_test(
DEPS
absl::algorithm_container
absl::base
+ absl::config
absl::core_headers
absl::memory
absl::span
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 5a025e46..352ac46c 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -52,6 +52,7 @@
#include <vector>
#include "absl/algorithm/algorithm.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/meta/type_traits.h"
@@ -93,17 +94,17 @@ using ContainerPointerType =
// using std::end;
// std::foo(begin(c), end(c));
// becomes
-// std::foo(container_algorithm_internal::begin(c),
-// container_algorithm_internal::end(c));
+// std::foo(container_algorithm_internal::c_begin(c),
+// container_algorithm_internal::c_end(c));
// These are meant for internal use only.
template <typename C>
-ContainerIter<C> c_begin(C& c) {
+ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {
return begin(c);
}
template <typename C>
-ContainerIter<C> c_end(C& c) {
+ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {
return end(c);
}
@@ -146,8 +147,9 @@ bool c_linear_search(const C& c, EqualityComparable&& value) {
// Container-based version of the <iterator> `std::distance()` function to
// return the number of elements within a container.
template <typename C>
-container_algorithm_internal::ContainerDifferenceType<const C> c_distance(
- const C& c) {
+ABSL_CONSTEXPR_SINCE_CXX17
+ container_algorithm_internal::ContainerDifferenceType<const C>
+ c_distance(const C& c) {
return std::distance(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c));
}
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 7e54e2b2..e5e2bf3d 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -15,6 +15,7 @@
#include "absl/algorithm/container.h"
#include <algorithm>
+#include <array>
#include <functional>
#include <initializer_list>
#include <iterator>
@@ -31,6 +32,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/casts.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/types/span.h"
@@ -1160,4 +1162,13 @@ TEST(MutatingTest, PermutationOperations) {
EXPECT_EQ(initial, permuted);
}
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+TEST(ConstexprTest, Distance) {
+ // Works at compile time with constexpr containers.
+ static_assert(absl::c_distance(std::array<int, 3>()) == 3);
+}
+#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
+ // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+
} // namespace
diff --git a/absl/base/config.h b/absl/base/config.h
index a8f2eab5..13263f9d 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -941,6 +941,27 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_HAVE_CONSTANT_EVALUATED 1
#endif
+// ABSL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr for
+// different C++ versions.
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201402L
+#define ABSL_CONSTEXPR_SINCE_CXX14 constexpr
+#else
+#define ABSL_CONSTEXPR_SINCE_CXX14
+#endif
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+#define ABSL_CONSTEXPR_SINCE_CXX17 constexpr
+#else
+#define ABSL_CONSTEXPR_SINCE_CXX17
+#endif
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#define ABSL_CONSTEXPR_SINCE_CXX20 constexpr
+#else
+#define ABSL_CONSTEXPR_SINCE_CXX20
+#endif
+
// ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros
// into an integer that can be compared against.
#ifdef ABSL_INTERNAL_EMSCRIPTEN_VERSION