From 37ebde53cfcf400ef01b59c80ae3f72039cd90f2 Mon Sep 17 00:00:00 2001
From: Abseil Team <absl-team@google.com>
Date: Mon, 1 Jul 2024 11:33:54 -0700
Subject: 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
---
 absl/algorithm/BUILD.bazel       |  2 ++
 absl/algorithm/CMakeLists.txt    |  2 ++
 absl/algorithm/container.h       | 14 ++++++++------
 absl/algorithm/container_test.cc | 11 +++++++++++
 4 files changed, 23 insertions(+), 6 deletions(-)

(limited to 'absl/algorithm')

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
-- 
cgit v1.2.3