diff options
author | Abseil Team <absl-team@google.com> | 2024-07-01 11:33:54 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-07-01 11:34:46 -0700 |
commit | 37ebde53cfcf400ef01b59c80ae3f72039cd90f2 (patch) | |
tree | 1977c5d4878e02cdaa96ed831f775e47bbd58f57 | |
parent | a27662352e9caafc264747562162a8a32ef36cb9 (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.bazel | 2 | ||||
-rw-r--r-- | absl/algorithm/CMakeLists.txt | 2 | ||||
-rw-r--r-- | absl/algorithm/container.h | 14 | ||||
-rw-r--r-- | absl/algorithm/container_test.cc | 11 | ||||
-rw-r--r-- | absl/base/config.h | 21 |
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 |