Skip to content

Commit

Permalink
Support three-way comparison on Apple clang/libc++.
Browse files Browse the repository at this point in the history
* libc++ added std::lexicographical_compare_three_way only with
  version 17. Provide emulation for earlier versions.
  • Loading branch information
BenKaufmann authored and sjanel committed Apr 16, 2024
1 parent 6997111 commit 4031546
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
6 changes: 3 additions & 3 deletions include/amc/smallset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,17 +524,17 @@ class SmallSet {
if (o.isSmall()) {
// We are both small, we need to sort both containers
auto oSortedPtrs = ComputeSortedPtrVec(o._vec);
return std::lexicographical_compare_three_way(sortedPtrs.begin(), sortedPtrs.end(), oSortedPtrs.begin(),
return amc::lexicographical_compare_three_way(sortedPtrs.begin(), sortedPtrs.end(), oSortedPtrs.begin(),
oSortedPtrs.end(), Comp());
}
// we are small: as we do not order elements in the small container, we need to sort them.
return std::lexicographical_compare_three_way(sortedPtrs.begin(), sortedPtrs.end(), o._set.begin(), o._set.end(),
return amc::lexicographical_compare_three_way(sortedPtrs.begin(), sortedPtrs.end(), o._set.begin(), o._set.end(),
Comp());
}
if (o.isSmall()) {
// other is small: as we do not order elements in the small container, we need to sort them.
auto oSortedPtrs = ComputeSortedPtrVec(o._vec);
return std::lexicographical_compare_three_way(_set.begin(), _set.end(), oSortedPtrs.begin(), oSortedPtrs.end(),
return amc::lexicographical_compare_three_way(_set.begin(), _set.end(), oSortedPtrs.begin(), oSortedPtrs.end(),
Comp());
}
return _set <=> o._set;
Expand Down
44 changes: 44 additions & 0 deletions include/amc/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

#include <utility>

#include "config.hpp"

#if AMC_CXX20
#include <algorithm>
#include <compare>
#endif

namespace amc {

// Provides emulation of std::exchange if C++14 is not supported.
Expand All @@ -15,4 +22,41 @@ T exchange(T &obj, U &&new_value) {
return old_value;
}
#endif

#if AMC_CXX20
#if !defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 170000
using std::lexicographical_compare_three_way;
#else
// Adjusted from https://en.cppreference.com/w/cpp/algorithm/lexicographical_compare_three_way
template <class I1, class I2, class Cmp>
constexpr auto lexicographical_compare_three_way(I1 f1, I1 l1, I2 f2, I2 l2, Cmp comp) -> decltype(comp(*f1, *f2)) {
using ret_t = decltype(comp(*f1, *f2));
static_assert(std::disjunction_v<std::is_same<ret_t, std::strong_ordering>, std::is_same<ret_t, std::weak_ordering>,
std::is_same<ret_t, std::partial_ordering> >,
"The return type must be a comparison category type.");

for (; f1 != l1; ++f1, ++f2) {
if (f2 == l2) return std::strong_ordering::greater;
if (auto c = comp(*f1, *f2); c != 0) return c;
}
return (f2 == l2) <=> true;
}
#if _LIBCPP_VERSION >= 14000
using std::compare_three_way;
#else
struct compare_three_way {
using is_transparent = void;
template <class T, class U>
constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept(std::declval<T>() <=> std::declval<U>())) {
return static_cast<T&&>(t) <=> static_cast<U&&>(u);
}
};
#endif
template <class I1, class I2>
constexpr auto lexicographical_compare_three_way(I1 f1, I1 l1, I2 f2, I2 l2) {
return lexicographical_compare_three_way(f1, l1, f2, l2, amc::compare_three_way());
}
#endif
#endif

} // namespace amc
2 changes: 1 addition & 1 deletion include/amc/vectorcommon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1152,7 +1152,7 @@ class VectorImpl : public VectorDestr<T, Alloc, SizeType, WithInlineElements, Gr

#ifdef AMC_CXX20
auto operator<=>(const VectorImpl &o) const {
return std::lexicographical_compare_three_way(this->begin(), end(), o.begin(), o.end());
return amc::lexicographical_compare_three_way(this->begin(), end(), o.begin(), o.end());
}
#else
bool operator<(const VectorImpl &o) const {
Expand Down

0 comments on commit 4031546

Please sign in to comment.