Commit 074a32af by Abseil Team Committed by Copybara-Service

Mark c_min_element, c_max_element, and c_minmax_element as constexpr in C++17.

This allows them to be used in constant expressions, such as static_asserts.

PiperOrigin-RevId: 649292841
Change-Id: I76e31a94b933fa357276fee534b81c00c28c8b23
parent eb46a63d
...@@ -99,12 +99,12 @@ using ContainerPointerType = ...@@ -99,12 +99,12 @@ using ContainerPointerType =
// These are meant for internal use only. // These are meant for internal use only.
template <typename C> template <typename C>
ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) { ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {
return begin(c); return begin(c);
} }
template <typename C> template <typename C>
ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) { ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {
return end(c); return end(c);
} }
...@@ -147,7 +147,7 @@ bool c_linear_search(const C& c, EqualityComparable&& value) { ...@@ -147,7 +147,7 @@ bool c_linear_search(const C& c, EqualityComparable&& value) {
// Container-based version of the <iterator> `std::distance()` function to // Container-based version of the <iterator> `std::distance()` function to
// return the number of elements within a container. // return the number of elements within a container.
template <typename C> template <typename C>
ABSL_CONSTEXPR_SINCE_CXX17 ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
container_algorithm_internal::ContainerDifferenceType<const C> container_algorithm_internal::ContainerDifferenceType<const C>
c_distance(const C& c) { c_distance(const C& c) {
return std::distance(container_algorithm_internal::c_begin(c), return std::distance(container_algorithm_internal::c_begin(c),
...@@ -1533,8 +1533,9 @@ c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) { ...@@ -1533,8 +1533,9 @@ c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
// to return an iterator pointing to the element with the smallest value, using // to return an iterator pointing to the element with the smallest value, using
// `operator<` to make the comparisons. // `operator<` to make the comparisons.
template <typename Sequence> template <typename Sequence>
container_algorithm_internal::ContainerIter<Sequence> c_min_element( ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
Sequence& sequence) { container_algorithm_internal::ContainerIter<Sequence>
c_min_element(Sequence& sequence) {
return std::min_element(container_algorithm_internal::c_begin(sequence), return std::min_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence)); container_algorithm_internal::c_end(sequence));
} }
...@@ -1542,8 +1543,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element( ...@@ -1542,8 +1543,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
// Overload of c_min_element() for performing a `comp` comparison other than // Overload of c_min_element() for performing a `comp` comparison other than
// `operator<`. // `operator<`.
template <typename Sequence, typename LessThan> template <typename Sequence, typename LessThan>
container_algorithm_internal::ContainerIter<Sequence> c_min_element( ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
Sequence& sequence, LessThan&& comp) { container_algorithm_internal::ContainerIter<Sequence>
c_min_element(Sequence& sequence, LessThan&& comp) {
return std::min_element(container_algorithm_internal::c_begin(sequence), return std::min_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_end(sequence),
std::forward<LessThan>(comp)); std::forward<LessThan>(comp));
...@@ -1555,8 +1557,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element( ...@@ -1555,8 +1557,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
// to return an iterator pointing to the element with the largest value, using // to return an iterator pointing to the element with the largest value, using
// `operator<` to make the comparisons. // `operator<` to make the comparisons.
template <typename Sequence> template <typename Sequence>
container_algorithm_internal::ContainerIter<Sequence> c_max_element( ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
Sequence& sequence) { container_algorithm_internal::ContainerIter<Sequence>
c_max_element(Sequence& sequence) {
return std::max_element(container_algorithm_internal::c_begin(sequence), return std::max_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence)); container_algorithm_internal::c_end(sequence));
} }
...@@ -1564,8 +1567,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element( ...@@ -1564,8 +1567,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// Overload of c_max_element() for performing a `comp` comparison other than // Overload of c_max_element() for performing a `comp` comparison other than
// `operator<`. // `operator<`.
template <typename Sequence, typename LessThan> template <typename Sequence, typename LessThan>
container_algorithm_internal::ContainerIter<Sequence> c_max_element( ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
Sequence& sequence, LessThan&& comp) { container_algorithm_internal::ContainerIter<Sequence>
c_max_element(Sequence& sequence, LessThan&& comp) {
return std::max_element(container_algorithm_internal::c_begin(sequence), return std::max_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_end(sequence),
std::forward<LessThan>(comp)); std::forward<LessThan>(comp));
...@@ -1578,8 +1582,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element( ...@@ -1578,8 +1582,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// smallest and largest values, respectively, using `operator<` to make the // smallest and largest values, respectively, using `operator<` to make the
// comparisons. // comparisons.
template <typename C> template <typename C>
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element( ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
C& c) { container_algorithm_internal::ContainerIterPairType<C, C>
c_minmax_element(C& c) {
return std::minmax_element(container_algorithm_internal::c_begin(c), return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c)); container_algorithm_internal::c_end(c));
} }
...@@ -1587,8 +1592,9 @@ container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element( ...@@ -1587,8 +1592,9 @@ container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
// Overload of c_minmax_element() for performing `comp` comparisons other than // Overload of c_minmax_element() for performing `comp` comparisons other than
// `operator<`. // `operator<`.
template <typename C, typename LessThan> template <typename C, typename LessThan>
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element( ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
C& c, LessThan&& comp) { container_algorithm_internal::ContainerIterPairType<C, C>
c_minmax_element(C& c, LessThan&& comp) {
return std::minmax_element(container_algorithm_internal::c_begin(c), return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c), container_algorithm_internal::c_end(c),
std::forward<LessThan>(comp)); std::forward<LessThan>(comp));
......
...@@ -1168,6 +1168,42 @@ TEST(ConstexprTest, Distance) { ...@@ -1168,6 +1168,42 @@ TEST(ConstexprTest, Distance) {
// Works at compile time with constexpr containers. // Works at compile time with constexpr containers.
static_assert(absl::c_distance(std::array<int, 3>()) == 3); static_assert(absl::c_distance(std::array<int, 3>()) == 3);
} }
TEST(ConstexprTest, MinElement) {
constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(*absl::c_min_element(kArray) == 1);
}
TEST(ConstexprTest, MinElementWithPredicate) {
constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(*absl::c_min_element(kArray, std::greater<int>()) == 3);
}
TEST(ConstexprTest, MaxElement) {
constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(*absl::c_max_element(kArray) == 3);
}
TEST(ConstexprTest, MaxElementWithPredicate) {
constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(*absl::c_max_element(kArray, std::greater<int>()) == 1);
}
TEST(ConstexprTest, MinMaxElement) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
constexpr auto kMinMaxPair = absl::c_minmax_element(kArray);
static_assert(*kMinMaxPair.first == 1);
static_assert(*kMinMaxPair.second == 3);
}
TEST(ConstexprTest, MinMaxElementWithPredicate) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
constexpr auto kMinMaxPair =
absl::c_minmax_element(kArray, std::greater<int>());
static_assert(*kMinMaxPair.first == 3);
static_assert(*kMinMaxPair.second == 1);
}
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && #endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
......
...@@ -941,25 +941,25 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || ...@@ -941,25 +941,25 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_HAVE_CONSTANT_EVALUATED 1 #define ABSL_HAVE_CONSTANT_EVALUATED 1
#endif #endif
// ABSL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr for // ABSL_INTERNAL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr
// different C++ versions. // for different C++ versions.
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ //
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201402L // These macros are an implementation detail and will be unconditionally removed
#define ABSL_CONSTEXPR_SINCE_CXX14 constexpr // once the minimum supported C++ version catches up to a given version.
#else //
#define ABSL_CONSTEXPR_SINCE_CXX14 // For this reason, this symbol is considered INTERNAL and code outside of
#endif // Abseil must not use it.
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ #if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
#define ABSL_CONSTEXPR_SINCE_CXX17 constexpr #define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 constexpr
#else #else
#define ABSL_CONSTEXPR_SINCE_CXX17 #define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
#endif #endif
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ #if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
#define ABSL_CONSTEXPR_SINCE_CXX20 constexpr #define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 constexpr
#else #else
#define ABSL_CONSTEXPR_SINCE_CXX20 #define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
#endif #endif
// ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros // ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros
......
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