Skip to content

Commit 074a32a

Browse files
Abseil Teamcopybara-github
authored andcommitted
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
1 parent eb46a63 commit 074a32a

File tree

3 files changed

+69
-27
lines changed

3 files changed

+69
-27
lines changed

absl/algorithm/container.h

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ using ContainerPointerType =
9999
// These are meant for internal use only.
100100

101101
template <typename C>
102-
ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {
102+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {
103103
return begin(c);
104104
}
105105

106106
template <typename C>
107-
ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {
107+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {
108108
return end(c);
109109
}
110110

@@ -147,7 +147,7 @@ bool c_linear_search(const C& c, EqualityComparable&& value) {
147147
// Container-based version of the <iterator> `std::distance()` function to
148148
// return the number of elements within a container.
149149
template <typename C>
150-
ABSL_CONSTEXPR_SINCE_CXX17
150+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
151151
container_algorithm_internal::ContainerDifferenceType<const C>
152152
c_distance(const C& c) {
153153
return std::distance(container_algorithm_internal::c_begin(c),
@@ -1533,17 +1533,19 @@ c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
15331533
// to return an iterator pointing to the element with the smallest value, using
15341534
// `operator<` to make the comparisons.
15351535
template <typename Sequence>
1536-
container_algorithm_internal::ContainerIter<Sequence> c_min_element(
1537-
Sequence& sequence) {
1536+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
1537+
container_algorithm_internal::ContainerIter<Sequence>
1538+
c_min_element(Sequence& sequence) {
15381539
return std::min_element(container_algorithm_internal::c_begin(sequence),
15391540
container_algorithm_internal::c_end(sequence));
15401541
}
15411542

15421543
// Overload of c_min_element() for performing a `comp` comparison other than
15431544
// `operator<`.
15441545
template <typename Sequence, typename LessThan>
1545-
container_algorithm_internal::ContainerIter<Sequence> c_min_element(
1546-
Sequence& sequence, LessThan&& comp) {
1546+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
1547+
container_algorithm_internal::ContainerIter<Sequence>
1548+
c_min_element(Sequence& sequence, LessThan&& comp) {
15471549
return std::min_element(container_algorithm_internal::c_begin(sequence),
15481550
container_algorithm_internal::c_end(sequence),
15491551
std::forward<LessThan>(comp));
@@ -1555,17 +1557,19 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
15551557
// to return an iterator pointing to the element with the largest value, using
15561558
// `operator<` to make the comparisons.
15571559
template <typename Sequence>
1558-
container_algorithm_internal::ContainerIter<Sequence> c_max_element(
1559-
Sequence& sequence) {
1560+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
1561+
container_algorithm_internal::ContainerIter<Sequence>
1562+
c_max_element(Sequence& sequence) {
15601563
return std::max_element(container_algorithm_internal::c_begin(sequence),
15611564
container_algorithm_internal::c_end(sequence));
15621565
}
15631566

15641567
// Overload of c_max_element() for performing a `comp` comparison other than
15651568
// `operator<`.
15661569
template <typename Sequence, typename LessThan>
1567-
container_algorithm_internal::ContainerIter<Sequence> c_max_element(
1568-
Sequence& sequence, LessThan&& comp) {
1570+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
1571+
container_algorithm_internal::ContainerIter<Sequence>
1572+
c_max_element(Sequence& sequence, LessThan&& comp) {
15691573
return std::max_element(container_algorithm_internal::c_begin(sequence),
15701574
container_algorithm_internal::c_end(sequence),
15711575
std::forward<LessThan>(comp));
@@ -1578,17 +1582,19 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
15781582
// smallest and largest values, respectively, using `operator<` to make the
15791583
// comparisons.
15801584
template <typename C>
1581-
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
1582-
C& c) {
1585+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
1586+
container_algorithm_internal::ContainerIterPairType<C, C>
1587+
c_minmax_element(C& c) {
15831588
return std::minmax_element(container_algorithm_internal::c_begin(c),
15841589
container_algorithm_internal::c_end(c));
15851590
}
15861591

15871592
// Overload of c_minmax_element() for performing `comp` comparisons other than
15881593
// `operator<`.
15891594
template <typename C, typename LessThan>
1590-
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
1591-
C& c, LessThan&& comp) {
1595+
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
1596+
container_algorithm_internal::ContainerIterPairType<C, C>
1597+
c_minmax_element(C& c, LessThan&& comp) {
15921598
return std::minmax_element(container_algorithm_internal::c_begin(c),
15931599
container_algorithm_internal::c_end(c),
15941600
std::forward<LessThan>(comp));

absl/algorithm/container_test.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,42 @@ TEST(ConstexprTest, Distance) {
11681168
// Works at compile time with constexpr containers.
11691169
static_assert(absl::c_distance(std::array<int, 3>()) == 3);
11701170
}
1171+
1172+
TEST(ConstexprTest, MinElement) {
1173+
constexpr std::array<int, 3> kArray = {1, 2, 3};
1174+
static_assert(*absl::c_min_element(kArray) == 1);
1175+
}
1176+
1177+
TEST(ConstexprTest, MinElementWithPredicate) {
1178+
constexpr std::array<int, 3> kArray = {1, 2, 3};
1179+
static_assert(*absl::c_min_element(kArray, std::greater<int>()) == 3);
1180+
}
1181+
1182+
TEST(ConstexprTest, MaxElement) {
1183+
constexpr std::array<int, 3> kArray = {1, 2, 3};
1184+
static_assert(*absl::c_max_element(kArray) == 3);
1185+
}
1186+
1187+
TEST(ConstexprTest, MaxElementWithPredicate) {
1188+
constexpr std::array<int, 3> kArray = {1, 2, 3};
1189+
static_assert(*absl::c_max_element(kArray, std::greater<int>()) == 1);
1190+
}
1191+
1192+
TEST(ConstexprTest, MinMaxElement) {
1193+
static constexpr std::array<int, 3> kArray = {1, 2, 3};
1194+
constexpr auto kMinMaxPair = absl::c_minmax_element(kArray);
1195+
static_assert(*kMinMaxPair.first == 1);
1196+
static_assert(*kMinMaxPair.second == 3);
1197+
}
1198+
1199+
TEST(ConstexprTest, MinMaxElementWithPredicate) {
1200+
static constexpr std::array<int, 3> kArray = {1, 2, 3};
1201+
constexpr auto kMinMaxPair =
1202+
absl::c_minmax_element(kArray, std::greater<int>());
1203+
static_assert(*kMinMaxPair.first == 3);
1204+
static_assert(*kMinMaxPair.second == 1);
1205+
}
1206+
11711207
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
11721208
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
11731209

absl/base/config.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -941,25 +941,25 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
941941
#define ABSL_HAVE_CONSTANT_EVALUATED 1
942942
#endif
943943

944-
// ABSL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr for
945-
// different C++ versions.
946-
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
947-
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201402L
948-
#define ABSL_CONSTEXPR_SINCE_CXX14 constexpr
949-
#else
950-
#define ABSL_CONSTEXPR_SINCE_CXX14
951-
#endif
944+
// ABSL_INTERNAL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr
945+
// for different C++ versions.
946+
//
947+
// These macros are an implementation detail and will be unconditionally removed
948+
// once the minimum supported C++ version catches up to a given version.
949+
//
950+
// For this reason, this symbol is considered INTERNAL and code outside of
951+
// Abseil must not use it.
952952
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
953953
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
954-
#define ABSL_CONSTEXPR_SINCE_CXX17 constexpr
954+
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 constexpr
955955
#else
956-
#define ABSL_CONSTEXPR_SINCE_CXX17
956+
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
957957
#endif
958958
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
959959
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
960-
#define ABSL_CONSTEXPR_SINCE_CXX20 constexpr
960+
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 constexpr
961961
#else
962-
#define ABSL_CONSTEXPR_SINCE_CXX20
962+
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
963963
#endif
964964

965965
// ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros

0 commit comments

Comments
 (0)