Export of internal Abseil changes.

--
9fa04b5fb4b6aeb47226b9095b3bc36a53669c39 by Abseil Team <absl-team@google.com>:

Release types/compare.h, which contains stand ins for three-way comparison result types from C++20. Use absl::weak_ordering for a three-way comparator in test-instance-tracker.h.

PiperOrigin-RevId: 247290078

--
70a762f4eb35ea1d5a5fcb3274a8086824a0b82c by Derek Mauro <dmauro@google.com>:

Upgrade linux_clang-latest builds to LLVM r356814 and Bazel 0.25.0

PiperOrigin-RevId: 247250176

--
f305cd5c36561e4dbb69eb87568553ae5badcb15 by CJ Johnson <johnsoncj@google.com>:

Remove argument deduction based on template template argument in InlinedVector/Storage

PiperOrigin-RevId: 247232334

--
2cab8e426838baceb7d08edb313416480d26aa5b by Eric Fiselier <ericwf@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 247140132
GitOrigin-RevId: 9fa04b5fb4b6aeb47226b9095b3bc36a53669c39
Change-Id: I373a7d9bc90befa2a9f06555cb8703610c0313b9
This commit is contained in:
Abseil Team 2019-05-08 14:20:43 -07:00 committed by Eric Fiselier
parent aa468ad755
commit 27c2f6e2f3
18 changed files with 982 additions and 14 deletions

View file

@ -213,6 +213,7 @@ cc_library(
visibility = [
"//absl:__subpackages__",
],
deps = ["//absl/types:compare"],
)
cc_test(

View file

@ -204,6 +204,8 @@ absl_cc_library(
"internal/test_instance_tracker.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
absl::compare
TESTONLY
)

View file

@ -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>

View file

@ -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;

View file

@ -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_;

View file

@ -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());

View file

@ -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"

View file

@ -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",

View file

@ -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.

View file

@ -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",

View file

@ -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 {

View file

@ -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";

View file

@ -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",
],
)

View file

@ -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()

506
absl/types/compare.h Normal file
View file

@ -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_

315
absl/types/compare_test.cc Normal file
View file

@ -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

View file

@ -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.

View file

@ -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.