summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--absl/container/BUILD.bazel1
-rw-r--r--absl/container/CMakeLists.txt2
-rw-r--r--absl/container/inlined_vector.h2
-rw-r--r--absl/container/internal/inlined_vector.h8
-rw-r--r--absl/container/internal/test_instance_tracker.h10
-rw-r--r--absl/container/internal/test_instance_tracker_test.cc2
-rw-r--r--absl/copts/GENERATED_AbseilCopts.cmake2
-rw-r--r--absl/copts/GENERATED_copts.bzl2
-rw-r--r--absl/copts/copts.py2
-rw-r--r--absl/hash/BUILD.bazel2
-rw-r--r--absl/time/internal/cctz/include/cctz/civil_time_detail.h38
-rw-r--r--absl/time/internal/cctz/src/cctz_benchmark.cc50
-rw-r--r--absl/types/BUILD.bazel24
-rw-r--r--absl/types/CMakeLists.txt26
-rw-r--r--absl/types/compare.h506
-rw-r--r--absl/types/compare_test.cc315
-rwxr-xr-xci/linux_clang-latest_libcxx_bazel.sh2
-rwxr-xr-xci/linux_clang-latest_libstdcxx_bazel.sh2
18 files changed, 982 insertions, 14 deletions
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index f25a9ff9..0488857e 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -213,6 +213,7 @@ cc_library(
visibility = [
"//absl:__subpackages__",
],
+ deps = ["//absl/types:compare"],
)
cc_test(
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 9531d7f9..1e203dbf 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -204,6 +204,8 @@ absl_cc_library(
"internal/test_instance_tracker.cc"
COPTS
${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::compare
TESTONLY
)
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 34e9aa0a..16865272 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -69,7 +69,7 @@ class InlinedVector {
static_assert(
N > 0, "InlinedVector cannot be instantiated with `0` inlined elements.");
- using Storage = inlined_vector_internal::Storage<InlinedVector>;
+ using Storage = inlined_vector_internal::Storage<T, N, A>;
using AllocatorTraits = typename Storage::AllocatorTraits;
template <typename Iterator>
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
index b8b4f4ce..6a5a75be 100644
--- a/absl/container/internal/inlined_vector.h
+++ b/absl/container/internal/inlined_vector.h
@@ -31,12 +31,8 @@ using IsAtLeastForwardIterator = std::is_convertible<
typename std::iterator_traits<Iterator>::iterator_category,
std::forward_iterator_tag>;
-template <typename InlinedVector>
-class Storage;
-
-template <template <typename, size_t, typename> class InlinedVector, typename T,
- size_t N, typename A>
-class Storage<InlinedVector<T, N, A>> {
+template <typename T, size_t N, typename A>
+class Storage {
public:
using allocator_type = A;
using value_type = typename allocator_type::value_type;
diff --git a/absl/container/internal/test_instance_tracker.h b/absl/container/internal/test_instance_tracker.h
index 032d16d3..3d4b2980 100644
--- a/absl/container/internal/test_instance_tracker.h
+++ b/absl/container/internal/test_instance_tracker.h
@@ -18,6 +18,8 @@
#include <cstdlib>
#include <ostream>
+#include "absl/types/compare.h"
+
namespace absl {
namespace test_internal {
@@ -96,6 +98,14 @@ class BaseCountedInstance {
return value_ >= x.value_;
}
+ absl::weak_ordering compare(const BaseCountedInstance& x) const {
+ ++num_comparisons_;
+ return value_ < x.value_
+ ? absl::weak_ordering::less
+ : value_ == x.value_ ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+ }
+
int value() const {
if (!is_live_) std::abort();
return value_;
diff --git a/absl/container/internal/test_instance_tracker_test.cc b/absl/container/internal/test_instance_tracker_test.cc
index 091f428d..1c6a4fa7 100644
--- a/absl/container/internal/test_instance_tracker_test.cc
+++ b/absl/container/internal/test_instance_tracker_test.cc
@@ -174,6 +174,8 @@ TEST(TestInstanceTracker, Comparisons) {
EXPECT_EQ(5, tracker.comparisons());
EXPECT_FALSE(one >= two);
EXPECT_EQ(6, tracker.comparisons());
+ EXPECT_TRUE(one.compare(two) < 0); // NOLINT
+ EXPECT_EQ(7, tracker.comparisons());
tracker.ResetCopiesMovesSwaps();
EXPECT_EQ(0, tracker.comparisons());
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
index f968ba72..c4948d42 100644
--- a/absl/copts/GENERATED_AbseilCopts.cmake
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -41,6 +41,7 @@ list(APPEND ABSL_CLANG_CL_FLAGS
"-Wno-unreachable-code"
"-Wno-unused-macros"
"-Wno-weak-vtables"
+ "-Wno-zero-as-null-pointer-constant"
"-Wbitfield-enum-conversion"
"-Wbool-conversion"
"-Wconstant-conversion"
@@ -149,6 +150,7 @@ list(APPEND ABSL_LLVM_FLAGS
"-Wno-unreachable-code"
"-Wno-unused-macros"
"-Wno-weak-vtables"
+ "-Wno-zero-as-null-pointer-constant"
"-Wbitfield-enum-conversion"
"-Wbool-conversion"
"-Wconstant-conversion"
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
index 2b4790a8..422b3a9b 100644
--- a/absl/copts/GENERATED_copts.bzl
+++ b/absl/copts/GENERATED_copts.bzl
@@ -42,6 +42,7 @@ ABSL_CLANG_CL_FLAGS = [
"-Wno-unreachable-code",
"-Wno-unused-macros",
"-Wno-weak-vtables",
+ "-Wno-zero-as-null-pointer-constant",
"-Wbitfield-enum-conversion",
"-Wbool-conversion",
"-Wconstant-conversion",
@@ -150,6 +151,7 @@ ABSL_LLVM_FLAGS = [
"-Wno-unreachable-code",
"-Wno-unused-macros",
"-Wno-weak-vtables",
+ "-Wno-zero-as-null-pointer-constant",
"-Wbitfield-enum-conversion",
"-Wbool-conversion",
"-Wconstant-conversion",
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
index 8a0ecf6b..5bede34c 100644
--- a/absl/copts/copts.py
+++ b/absl/copts/copts.py
@@ -70,6 +70,8 @@ LLVM_DISABLE_WARNINGS_FLAGS = [
# Causes warnings on include guards
"-Wno-unused-macros",
"-Wno-weak-vtables",
+ # Causes warnings on usage of types/compare.h comparison operators.
+ "-Wno-zero-as-null-pointer-constant",
###
# Implicit conversion warnings turned off by -Wno-conversion
# which are re-enabled below.
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel
index 8c2daf70..e1e6eae8 100644
--- a/absl/hash/BUILD.bazel
+++ b/absl/hash/BUILD.bazel
@@ -35,10 +35,10 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":city",
"//absl/base:core_headers",
"//absl/base:endian",
"//absl/container:fixed_array",
+ "//absl/hash:city",
"//absl/meta:type_traits",
"//absl/numeric:int128",
"//absl/strings",
diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index bb191b3f..3e243403 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -555,13 +555,43 @@ CONSTEXPR_F weekday get_weekday(const civil_day& cd) noexcept {
////////////////////////////////////////////////////////////////////////
CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept {
- do { cd += 1; } while (get_weekday(cd) != wd);
- return cd;
+ CONSTEXPR_D weekday k_weekdays_forw[14] = {
+ weekday::monday, weekday::tuesday, weekday::wednesday,
+ weekday::thursday, weekday::friday, weekday::saturday,
+ weekday::sunday, weekday::monday, weekday::tuesday,
+ weekday::wednesday, weekday::thursday, weekday::friday,
+ weekday::saturday, weekday::sunday,
+ };
+ weekday base = get_weekday(cd);
+ for (int i = 0;; ++i) {
+ if (base == k_weekdays_forw[i]) {
+ for (int j = i + 1;; ++j) {
+ if (wd == k_weekdays_forw[j]) {
+ return cd + (j - i);
+ }
+ }
+ }
+ }
}
CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept {
- do { cd -= 1; } while (get_weekday(cd) != wd);
- return cd;
+ CONSTEXPR_D weekday k_weekdays_back[14] = {
+ weekday::sunday, weekday::saturday, weekday::friday,
+ weekday::thursday, weekday::wednesday, weekday::tuesday,
+ weekday::monday, weekday::sunday, weekday::saturday,
+ weekday::friday, weekday::thursday, weekday::wednesday,
+ weekday::tuesday, weekday::monday,
+ };
+ weekday base = get_weekday(cd);
+ for (int i = 0;; ++i) {
+ if (base == k_weekdays_back[i]) {
+ for (int j = i + 1;; ++j) {
+ if (wd == k_weekdays_back[j]) {
+ return cd - (j - i);
+ }
+ }
+ }
+ }
}
CONSTEXPR_F int get_yearday(const civil_day& cd) noexcept {
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
index 445366ea..a40f504e 100644
--- a/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -47,6 +47,56 @@ void BM_Step_Days(benchmark::State& state) {
}
BENCHMARK(BM_Step_Days);
+void BM_GetWeekday(benchmark::State& state) {
+ const cctz::civil_day c(2014, 8, 22);
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::get_weekday(c));
+ }
+}
+BENCHMARK(BM_GetWeekday);
+
+void BM_NextWeekday(benchmark::State& state) {
+ const cctz::civil_day kStart(2014, 8, 22);
+ const cctz::civil_day kDays[7] = {
+ kStart + 0, kStart + 1, kStart + 2, kStart + 3,
+ kStart + 4, kStart + 5, kStart + 6,
+ };
+ const cctz::weekday kWeekdays[7] = {
+ cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday,
+ cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday,
+ cctz::weekday::sunday,
+ };
+ while (state.KeepRunningBatch(7 * 7)) {
+ for (const auto from : kDays) {
+ for (const auto to : kWeekdays) {
+ benchmark::DoNotOptimize(cctz::next_weekday(from, to));
+ }
+ }
+ }
+}
+BENCHMARK(BM_NextWeekday);
+
+void BM_PrevWeekday(benchmark::State& state) {
+ const cctz::civil_day kStart(2014, 8, 22);
+ const cctz::civil_day kDays[7] = {
+ kStart + 0, kStart + 1, kStart + 2, kStart + 3,
+ kStart + 4, kStart + 5, kStart + 6,
+ };
+ const cctz::weekday kWeekdays[7] = {
+ cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday,
+ cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday,
+ cctz::weekday::sunday,
+ };
+ while (state.KeepRunningBatch(7 * 7)) {
+ for (const auto from : kDays) {
+ for (const auto to : kWeekdays) {
+ benchmark::DoNotOptimize(cctz::prev_weekday(from, to));
+ }
+ }
+ }
+}
+BENCHMARK(BM_PrevWeekday);
+
const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index a2548718..134f9f22 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -308,3 +308,27 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
+
+cc_library(
+ name = "compare",
+ hdrs = ["compare.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ deps = [
+ "//absl/base:core_headers",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_test(
+ name = "compare_test",
+ size = "small",
+ srcs = [
+ "compare_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ deps = [
+ ":compare",
+ "//absl/base",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index 9da94eb5..4ce685da 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -299,6 +299,32 @@ absl_cc_test(
gmock_main
)
+absl_cc_library(
+ NAME
+ compare
+ HDRS
+ "compare.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::core_headers
+ absl::type_traits
+ PUBLIC
+)
+
+absl_cc_test(
+ NAME
+ compare_test
+ SRCS
+ "compare_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::base
+ absl::compare
+ gmock_main
+)
+
# TODO(cohenjon,zhangxy) Figure out why this test is failing on gcc 4.8
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
else()
diff --git a/absl/types/compare.h b/absl/types/compare.h
new file mode 100644
index 00000000..7fed3081
--- /dev/null
+++ b/absl/types/compare.h
@@ -0,0 +1,506 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// compare.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::weak_equality`, `absl::strong_equality`,
+// `absl::partial_ordering`, `absl::weak_ordering`, and `absl::strong_ordering`
+// types for storing the results of three way comparisons.
+//
+// Example:
+// absl::weak_ordering compare(const std::string& a, const std::string& b);
+//
+// These are C++11 compatible versions of the C++20 corresponding types
+// (`std::weak_equality`, etc.) and are designed to be drop-in replacements
+// for code compliant with C++20.
+
+#ifndef ABSL_TYPES_COMPARE_H_
+#define ABSL_TYPES_COMPARE_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <type_traits>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+namespace compare_internal {
+
+using value_type = int8_t;
+
+template <typename T>
+struct Fail {
+ static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
+};
+
+// We need the NullPtrT template to avoid triggering the modernize-use-nullptr
+// ClangTidy warning in user code.
+template <typename NullPtrT = std::nullptr_t>
+struct OnlyLiteralZero {
+ constexpr OnlyLiteralZero(NullPtrT) noexcept {} // NOLINT
+
+ // Fails compilation when `nullptr` or integral type arguments other than
+ // `int` are passed. This constructor doesn't accept `int` because literal `0`
+ // has type `int`. Literal `0` arguments will be implicitly converted to
+ // `std::nullptr_t` and accepted by the above constructor, while other `int`
+ // arguments will fail to be converted and cause compilation failure.
+ template <
+ typename T,
+ typename = typename std::enable_if<
+ std::is_same<T, std::nullptr_t>::value ||
+ (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type,
+ typename = typename Fail<T>::type>
+ OnlyLiteralZero(T); // NOLINT
+};
+
+enum class eq : value_type {
+ equal = 0,
+ equivalent = equal,
+ nonequal = 1,
+ nonequivalent = nonequal,
+};
+
+enum class ord : value_type { less = -1, greater = 1 };
+
+enum class ncmp : value_type { unordered = -127 };
+
+// These template base classes allow for defining the values of the constants
+// in the header file (for performance) without using inline variables (which
+// aren't available in C++11).
+template <typename T>
+struct weak_equality_base {
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T nonequivalent;
+};
+template <typename T>
+const T weak_equality_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T weak_equality_base<T>::nonequivalent(eq::nonequivalent);
+
+template <typename T>
+struct strong_equality_base {
+ ABSL_CONST_INIT static const T equal;
+ ABSL_CONST_INIT static const T nonequal;
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T nonequivalent;
+};
+template <typename T>
+const T strong_equality_base<T>::equal(eq::equal);
+template <typename T>
+const T strong_equality_base<T>::nonequal(eq::nonequal);
+template <typename T>
+const T strong_equality_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T strong_equality_base<T>::nonequivalent(eq::nonequivalent);
+
+template <typename T>
+struct partial_ordering_base {
+ ABSL_CONST_INIT static const T less;
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T greater;
+ ABSL_CONST_INIT static const T unordered;
+};
+template <typename T>
+const T partial_ordering_base<T>::less(ord::less);
+template <typename T>
+const T partial_ordering_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T partial_ordering_base<T>::greater(ord::greater);
+template <typename T>
+const T partial_ordering_base<T>::unordered(ncmp::unordered);
+
+template <typename T>
+struct weak_ordering_base {
+ ABSL_CONST_INIT static const T less;
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T greater;
+};
+template <typename T>
+const T weak_ordering_base<T>::less(ord::less);
+template <typename T>
+const T weak_ordering_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T weak_ordering_base<T>::greater(ord::greater);
+
+template <typename T>
+struct strong_ordering_base {
+ ABSL_CONST_INIT static const T less;
+ ABSL_CONST_INIT static const T equal;
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T greater;
+};
+template <typename T>
+const T strong_ordering_base<T>::less(ord::less);
+template <typename T>
+const T strong_ordering_base<T>::equal(eq::equal);
+template <typename T>
+const T strong_ordering_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T strong_ordering_base<T>::greater(ord::greater);
+
+} // namespace compare_internal
+
+class weak_equality
+ : public compare_internal::weak_equality_base<weak_equality> {
+ explicit constexpr weak_equality(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::weak_equality_base<weak_equality>;
+
+ public:
+ // Comparisons
+ friend constexpr bool operator==(
+ weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ weak_equality v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ weak_equality v) noexcept {
+ return 0 != v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+class strong_equality
+ : public compare_internal::strong_equality_base<strong_equality> {
+ explicit constexpr strong_equality(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::strong_equality_base<strong_equality>;
+
+ public:
+ // Conversion
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ strong_equality v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ strong_equality v) noexcept {
+ return 0 != v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+class partial_ordering
+ : public compare_internal::partial_ordering_base<partial_ordering> {
+ explicit constexpr partial_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr partial_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::partial_ordering_base<partial_ordering>;
+
+ constexpr bool is_ordered() const noexcept {
+ return value_ !=
+ compare_internal::value_type(compare_internal::ncmp::unordered);
+ }
+
+ public:
+ // Conversion
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return !v.is_ordered() || v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return !v.is_ordered() || 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 >= v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+class weak_ordering
+ : public compare_internal::weak_ordering_base<weak_ordering> {
+ explicit constexpr weak_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr weak_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::weak_ordering_base<weak_ordering>;
+
+ public:
+ // Conversions
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator partial_ordering() const noexcept { // NOLINT
+ return value_ == 0 ? partial_ordering::equivalent
+ : (value_ < 0 ? partial_ordering::less
+ : partial_ordering::greater);
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 >= v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+class strong_ordering
+ : public compare_internal::strong_ordering_base<strong_ordering> {
+ explicit constexpr strong_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr strong_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::strong_ordering_base<strong_ordering>;
+
+ public:
+ // Conversions
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator strong_equality() const noexcept { // NOLINT
+ return value_ == 0 ? strong_equality::equal : strong_equality::nonequal;
+ }
+ constexpr operator partial_ordering() const noexcept { // NOLINT
+ return value_ == 0 ? partial_ordering::equivalent
+ : (value_ < 0 ? partial_ordering::less
+ : partial_ordering::greater);
+ }
+ constexpr operator weak_ordering() const noexcept { // NOLINT
+ return value_ == 0
+ ? weak_ordering::equivalent
+ : (value_ < 0 ? weak_ordering::less : weak_ordering::greater);
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 >= v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+namespace compare_internal {
+// We also provide these comparator adapter functions for internal absl use.
+
+// Helper functions to do a boolean comparison of two keys given a boolean
+// or three-way comparator.
+constexpr bool compare_result_as_less_than(const bool r) { return r; }
+constexpr bool compare_result_as_less_than(const int r) { return r < 0; }
+constexpr bool compare_result_as_less_than(const absl::weak_ordering r) {
+ return r < 0;
+}
+
+template <typename Compare, typename K, typename LK>
+constexpr bool do_less_than_comparison(const Compare &compare, const K &x,
+ const LK &y) {
+ return compare_result_as_less_than(compare(x, y));
+}
+
+// Helper functions to do a three-way comparison of two keys given a boolean or
+// three-way comparator.
+// SFINAE prevents implicit conversions to int (such as from bool).
+template <typename Int,
+ absl::enable_if_t<std::is_same<int, Int>::value, int> = 0>
+constexpr absl::weak_ordering compare_result_as_ordering(const Int c) {
+ return c < 0 ? absl::weak_ordering::less
+ : c == 0 ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+}
+constexpr absl::weak_ordering compare_result_as_ordering(
+ const absl::weak_ordering c) {
+ return c;
+}
+
+template <
+ typename Compare, typename K, typename LK,
+ absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare(
+ const K &, const LK &)>>::value,
+ int> = 0>
+constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
+ const K &x, const LK &y) {
+ return compare_result_as_ordering(compare(x, y));
+}
+template <
+ typename Compare, typename K, typename LK,
+ absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare(
+ const K &, const LK &)>>::value,
+ int> = 0>
+constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
+ const K &x, const LK &y) {
+ return compare(x, y) ? absl::weak_ordering::less
+ : compare(y, x) ? absl::weak_ordering::greater
+ : absl::weak_ordering::equivalent;
+}
+
+} // namespace compare_internal
+} // namespace absl
+
+#endif // ABSL_TYPES_COMPARE_H_
diff --git a/absl/types/compare_test.cc b/absl/types/compare_test.cc
new file mode 100644
index 00000000..dd0388c1
--- /dev/null
+++ b/absl/types/compare_test.cc
@@ -0,0 +1,315 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/types/compare.h"
+
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+
+namespace absl {
+namespace {
+
+// This is necessary to avoid a bunch of lint warnings suggesting that we use
+// EXPECT_EQ/etc., which doesn't work in this case because they convert the `0`
+// to an int, which can't be converted to the unspecified zero type.
+bool Identity(bool b) { return b; }
+
+TEST(Compare, WeakEquality) {
+ EXPECT_TRUE(Identity(weak_equality::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == weak_equality::equivalent));
+ EXPECT_TRUE(Identity(weak_equality::nonequivalent != 0));
+ EXPECT_TRUE(Identity(0 != weak_equality::nonequivalent));
+}
+
+TEST(Compare, StrongEquality) {
+ EXPECT_TRUE(Identity(strong_equality::equal == 0));
+ EXPECT_TRUE(Identity(0 == strong_equality::equal));
+ EXPECT_TRUE(Identity(strong_equality::nonequal != 0));
+ EXPECT_TRUE(Identity(0 != strong_equality::nonequal));
+ EXPECT_TRUE(Identity(strong_equality::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == strong_equality::equivalent));
+ EXPECT_TRUE(Identity(strong_equality::nonequivalent != 0));
+ EXPECT_TRUE(Identity(0 != strong_equality::nonequivalent));
+}
+
+TEST(Compare, PartialOrdering) {
+ EXPECT_TRUE(Identity(partial_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > partial_ordering::less));
+ EXPECT_TRUE(Identity(partial_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= partial_ordering::less));
+ EXPECT_TRUE(Identity(partial_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == partial_ordering::equivalent));
+ EXPECT_TRUE(Identity(partial_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < partial_ordering::greater));
+ EXPECT_TRUE(Identity(partial_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= partial_ordering::greater));
+ EXPECT_TRUE(Identity(partial_ordering::unordered != 0));
+ EXPECT_TRUE(Identity(0 != partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered < 0));
+ EXPECT_FALSE(Identity(0 < partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered <= 0));
+ EXPECT_FALSE(Identity(0 <= partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered > 0));
+ EXPECT_FALSE(Identity(0 > partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered >= 0));
+ EXPECT_FALSE(Identity(0 >= partial_ordering::unordered));
+}
+
+TEST(Compare, WeakOrdering) {
+ EXPECT_TRUE(Identity(weak_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > weak_ordering::less));
+ EXPECT_TRUE(Identity(weak_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= weak_ordering::less));
+ EXPECT_TRUE(Identity(weak_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == weak_ordering::equivalent));
+ EXPECT_TRUE(Identity(weak_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < weak_ordering::greater));
+ EXPECT_TRUE(Identity(weak_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= weak_ordering::greater));
+}
+
+TEST(Compare, StrongOrdering) {
+ EXPECT_TRUE(Identity(strong_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > strong_ordering::less));
+ EXPECT_TRUE(Identity(strong_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= strong_ordering::less));
+ EXPECT_TRUE(Identity(strong_ordering::equal == 0));
+ EXPECT_TRUE(Identity(0 == strong_ordering::equal));
+ EXPECT_TRUE(Identity(strong_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == strong_ordering::equivalent));
+ EXPECT_TRUE(Identity(strong_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < strong_ordering::greater));
+ EXPECT_TRUE(Identity(strong_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= strong_ordering::greater));
+}
+
+TEST(Compare, Conversions) {
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::nonequal) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::equivalent) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<weak_equality>(strong_equality::nonequivalent) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::less) != 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<weak_equality>(partial_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::unordered) != 0));
+
+ EXPECT_TRUE(implicit_cast<weak_equality>(weak_ordering::less) != 0);
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(weak_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(weak_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) <= 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<partial_ordering>(weak_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) >= 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<strong_equality>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) <= 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<partial_ordering>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) >= 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) <= 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) >= 0));
+}
+
+struct WeakOrderingLess {
+ template <typename T>
+ absl::weak_ordering operator()(const T &a, const T &b) const {
+ return a < b ? absl::weak_ordering::less
+ : a == b ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+ }
+};
+
+TEST(CompareResultAsLessThan, SanityTest) {
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(false));
+ EXPECT_TRUE(absl::compare_internal::compare_result_as_less_than(true));
+
+ EXPECT_TRUE(absl::compare_internal::compare_result_as_less_than(-1));
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(0));
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(1));
+
+ EXPECT_TRUE(
+ absl::compare_internal::compare_result_as_less_than(weak_ordering::less));
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(
+ weak_ordering::equivalent));
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(
+ weak_ordering::greater));
+}
+
+TEST(DoLessThanComparison, SanityTest) {
+ std::less<int> less;
+ WeakOrderingLess weak;
+
+ EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(less, -1, 0));
+ EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(weak, -1, 0));
+
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 10));
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 10));
+
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 5));
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 5));
+}
+
+TEST(CompareResultAsOrdering, SanityTest) {
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::compare_result_as_ordering(-1) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(-1) == 0));
+ EXPECT_FALSE(
+ Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) < 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) == 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(0) < 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::compare_result_as_ordering(0) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(0) > 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) < 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) == 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(1) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(1) == 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::compare_result_as_ordering(1) > 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) < 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) == 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) > 0));
+}
+
+TEST(DoThreeWayComparison, SanityTest) {
+ std::less<int> less;
+ WeakOrderingLess weak;
+
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) > 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) < 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) > 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) < 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) == 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) > 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) == 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) > 0));
+}
+
+} // namespace
+} // namespace absl
diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh
index fe9d6aaf..f32cbef7 100755
--- a/ci/linux_clang-latest_libcxx_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_bazel.sh
@@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then
COMPILATION_MODE="fastbuild opt"
fi
-readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190329"
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508"
# USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work.
diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh
index 611b7f24..7bbecd6f 100755
--- a/ci/linux_clang-latest_libstdcxx_bazel.sh
+++ b/ci/linux_clang-latest_libstdcxx_bazel.sh
@@ -32,7 +32,7 @@ if [ -z ${COMPILATION_MODE:-} ]; then
COMPILATION_MODE="fastbuild opt"
fi
-readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190329"
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190508"
# USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work.