summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2019-03-08 14:06:50 -0800
committerGravatar Derek Mauro <dmauro@google.com>2019-03-08 17:11:18 -0500
commit88a152ae747c3c42dc9167d46c590929b048d436 (patch)
treee0858f1abd59c78a59b7d8449b7fb7c76904c88c
parentc1cecb25a94c075725e9d2640f6b978a8f61957b (diff)
Export of internal Abseil changes.
-- 5dc8d7504b7c11710b19365a6582c288c8992366 by Derek Mauro <dmauro@google.com>: Fix constexpr Span::last under MSVC and add Span constexpr tests. PiperOrigin-RevId: 237515952 -- 5ea8c146e653bbc49ff7e698699478242df7de35 by Derek Mauro <dmauro@google.com>: Implement Span::first and Span::last from C++20. https://github.com/abseil/abseil-cpp/pull/274 PiperOrigin-RevId: 237494399 -- 08db3417f1d8fe4556255d57a2f0df51b09bdd9a by Derek Mauro <dmauro@google.com>: HTTPS in more URLs. PiperOrigin-RevId: 237486823 -- 83ec63a7f8e47b62af619546f9f7b3bf72e74e86 by Derek Mauro <dmauro@google.com>: Changed HTTP URLs to HTTPS where possible. https://github.com/abseil/abseil-cpp/pull/270 PiperOrigin-RevId: 237445310 -- 220bf279c14cb31efa239500d1a70e0ac0c32e3c by Abseil Team <absl-team@google.com>: Support parsing decltype(nullptr) as a type. PiperOrigin-RevId: 237336739 -- ced234bbe78f5d495c3f6f6a9c2e0a95f7c080a5 by Gennadiy Rozental <rogeeff@google.com>: Introduce internal interface for setting environment variable value in scope PiperOrigin-RevId: 237275806 -- 1f1acb4e294af24d9f7598e85163d5e1d9958ae9 by Samuel Benzaquen <sbenza@google.com>: Avoid using aliases in the SFINAE expressions to make it more compatible with MSVC. Turn on the tests in MSVC. PiperOrigin-RevId: 237261456 -- 06cf7de6250a0572ef90fa1176f742ca0451ce71 by Derek Mauro <dmauro@google.com>: Fix unused variable warning. PiperOrigin-RevId: 237108006 GitOrigin-RevId: 5dc8d7504b7c11710b19365a6582c288c8992366 Change-Id: Ife5182c80942945c4e8700844c8febb482d6ad82
-rw-r--r--UPGRADES.md2
-rw-r--r--absl/base/BUILD.bazel22
-rw-r--r--absl/base/CMakeLists.txt23
-rw-r--r--absl/base/attributes.h4
-rw-r--r--absl/base/internal/scoped_set_env.cc79
-rw-r--r--absl/base/internal/scoped_set_env.h41
-rw-r--r--absl/base/internal/scoped_set_env_test.cc99
-rw-r--r--absl/compiler_config_setting.bzl40
-rw-r--r--absl/container/internal/unordered_map_members_test.h2
-rw-r--r--absl/container/internal/unordered_set_members_test.h2
-rw-r--r--absl/debugging/internal/demangle.cc6
-rw-r--r--absl/hash/hash_test.cc22
-rw-r--r--absl/hash/internal/hash.h161
-rw-r--r--absl/strings/string_view_test.cc1
-rw-r--r--absl/time/duration.cc2
-rw-r--r--absl/time/time.h4
-rw-r--r--absl/types/span.h2
17 files changed, 371 insertions, 141 deletions
diff --git a/UPGRADES.md b/UPGRADES.md
index edbc4dc4..35599d08 100644
--- a/UPGRADES.md
+++ b/UPGRADES.md
@@ -6,7 +6,7 @@ to do the work of effecting such API-breaking changes, when absolutely
necessary.
These tools will be listed on the [C++ Upgrade Tools][upgrade-tools] guide on
-http://abseil.io.
+https://abseil.io.
For more information, the [C++ Automated Upgrade Guide][api-upgrades-guide]
outlines this process.
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 12a8a130..19c50458 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -483,3 +483,25 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
+
+cc_library(
+ name = "scoped_set_env",
+ testonly = 1,
+ srcs = ["internal/scoped_set_env.cc"],
+ hdrs = ["internal/scoped_set_env.h"],
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [":base"],
+)
+
+cc_test(
+ name = "scoped_set_env_test",
+ size = "small",
+ srcs = ["internal/scoped_set_env_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ deps = [
+ ":scoped_set_env",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 936c0d2d..f2bacb23 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -415,3 +415,26 @@ absl_cc_test(
absl::bits
gtest_main
)
+
+absl_cc_library(
+ NAME
+ scoped_set_env
+ SRCS
+ "internal/scoped_set_env.cc"
+ HDRS
+ "internal/scoped_set_env.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::base
+)
+
+absl_cc_test(
+ NAME
+ scoped_set_env_test
+ SRCS
+ "internal/scoped_set_env_test.cc"
+ DEPS
+ absl::scoped_set_env
+ gtest_main
+)
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index dc3a95a4..48195d61 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -80,7 +80,7 @@
//
// A function-like feature checking macro that accepts C++11 style attributes.
// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
-// (http://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
+// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
// find `__has_cpp_attribute`, will evaluate to 0.
#if defined(__cplusplus) && defined(__has_cpp_attribute)
// NOTE: requiring __cplusplus above should not be necessary, but
@@ -102,7 +102,7 @@
//
// Tells the compiler to perform `printf` format string checking if the
// compiler supports it; see the 'format' attribute in
-// <http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
+// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
//
// Note: As the GCC manual states, "[s]ince non-static C++ methods
// have an implicit 'this' argument, the arguments of such methods
diff --git a/absl/base/internal/scoped_set_env.cc b/absl/base/internal/scoped_set_env.cc
new file mode 100644
index 00000000..9b164124
--- /dev/null
+++ b/absl/base/internal/scoped_set_env.cc
@@ -0,0 +1,79 @@
+// Copyright 2019 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/base/internal/scoped_set_env.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <cstdlib>
+
+#include "absl/base/internal/raw_logging.h"
+
+namespace absl {
+namespace base_internal {
+
+namespace {
+
+#ifdef _WIN32
+const int kMaxEnvVarValueSize = 1024;
+#endif
+
+void SetEnvVar(const char* name, const char* value) {
+#ifdef _WIN32
+ SetEnvironmentVariable(name, value);
+#else
+ if (value == nullptr) {
+ ::unsetenv(name);
+ } else {
+ ::setenv(name, value, 1);
+ }
+#endif
+}
+
+} // namespace
+
+ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)
+ : var_name_(var_name), was_unset_(false) {
+#ifdef _WIN32
+ char buf[kMaxEnvVarValueSize];
+ auto get_res = GetEnvironmentVariable(var_name_.c_str(), buf, sizeof(buf));
+ ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size");
+
+ if (get_res == 0) {
+ was_unset_ = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+ } else {
+ old_value_.assign(buf, get_res);
+ }
+
+ SetEnvironmentVariable(var_name_.c_str(), new_value);
+#else
+ const char* val = ::getenv(var_name_.c_str());
+ if (val == nullptr) {
+ was_unset_ = true;
+ } else {
+ old_value_ = val;
+ }
+#endif
+
+ SetEnvVar(var_name_.c_str(), new_value);
+}
+
+ScopedSetEnv::~ScopedSetEnv() {
+ SetEnvVar(var_name_.c_str(), was_unset_ ? nullptr : old_value_.c_str());
+}
+
+} // namespace base_internal
+} // namespace absl
diff --git a/absl/base/internal/scoped_set_env.h b/absl/base/internal/scoped_set_env.h
new file mode 100644
index 00000000..855b22fd
--- /dev/null
+++ b/absl/base/internal/scoped_set_env.h
@@ -0,0 +1,41 @@
+//
+// Copyright 2019 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.
+//
+
+#ifndef ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
+#define ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
+
+#include <string>
+
+namespace absl {
+namespace base_internal {
+
+class ScopedSetEnv {
+ public:
+ ScopedSetEnv(const char* var_name, const char* new_value);
+ ~ScopedSetEnv();
+
+ private:
+ std::string var_name_;
+ std::string old_value_;
+
+ // True if the environment variable was initially not set.
+ bool was_unset_;
+};
+
+} // namespace base_internal
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
diff --git a/absl/base/internal/scoped_set_env_test.cc b/absl/base/internal/scoped_set_env_test.cc
new file mode 100644
index 00000000..4bd68c48
--- /dev/null
+++ b/absl/base/internal/scoped_set_env_test.cc
@@ -0,0 +1,99 @@
+// Copyright 2019 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.
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/scoped_set_env.h"
+
+namespace {
+
+using absl::base_internal::ScopedSetEnv;
+
+std::string GetEnvVar(const char* name) {
+#ifdef _WIN32
+ char buf[1024];
+ auto get_res = GetEnvironmentVariable(name, buf, sizeof(buf));
+ if (get_res == sizeof(buf)) {
+ return "TOO_BIG";
+ }
+
+ if (get_res == 0) {
+ return "UNSET";
+ }
+
+ return std::string(buf, get_res);
+#else
+ const char* val = ::getenv(name);
+ if (val == nullptr) {
+ return "UNSET";
+ }
+
+ return val;
+#endif
+}
+
+TEST(ScopedSetEnvTest, SetNonExistingVarToString) {
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+
+ {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+ }
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+}
+
+TEST(ScopedSetEnvTest, SetNonExistingVarToNull) {
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+
+ {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr);
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+ }
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+}
+
+TEST(ScopedSetEnvTest, SetExistingVarToString) {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+
+ {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "new_value");
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "new_value");
+ }
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+}
+
+TEST(ScopedSetEnvTest, SetExistingVarToNull) {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+
+ {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr);
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+ }
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+}
+
+} // namespace
diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl
index f1a87018..e03f94ec 100644
--- a/absl/compiler_config_setting.bzl
+++ b/absl/compiler_config_setting.bzl
@@ -17,23 +17,23 @@
"""Creates config_setting that allows selecting based on 'compiler' value."""
def create_llvm_config(name, visibility):
- # The "do_not_use_tools_cpp_compiler_present" attribute exists to
- # distinguish between older versions of Bazel that do not support
- # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
- # In the future, the only way to select on the compiler will be through
- # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
- # be removed.
- if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
- native.config_setting(
- name = name,
- flag_values = {
- "@bazel_tools//tools/cpp:compiler": "llvm",
- },
- visibility = visibility,
- )
- else:
- native.config_setting(
- name = name,
- values = {"compiler": "llvm"},
- visibility = visibility,
- )
+ # The "do_not_use_tools_cpp_compiler_present" attribute exists to
+ # distinguish between older versions of Bazel that do not support
+ # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
+ # In the future, the only way to select on the compiler will be through
+ # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
+ # be removed.
+ if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
+ native.config_setting(
+ name = name,
+ flag_values = {
+ "@bazel_tools//tools/cpp:compiler": "llvm",
+ },
+ visibility = visibility,
+ )
+ else:
+ native.config_setting(
+ name = name,
+ values = {"compiler": "llvm"},
+ visibility = visibility,
+ )
diff --git a/absl/container/internal/unordered_map_members_test.h b/absl/container/internal/unordered_map_members_test.h
index 5c9a799c..1bf31ab4 100644
--- a/absl/container/internal/unordered_map_members_test.h
+++ b/absl/container/internal/unordered_map_members_test.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/absl/container/internal/unordered_set_members_test.h b/absl/container/internal/unordered_set_members_test.h
index eaf00445..b96c945a 100644
--- a/absl/container/internal/unordered_set_members_test.h
+++ b/absl/container/internal/unordered_set_members_test.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 0d959a98..52a553fd 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -1168,6 +1168,12 @@ static bool ParseType(State *state) {
}
state->parse_state = copy;
+ // nullptr_t, i.e. decltype(nullptr).
+ if (ParseTwoCharToken(state, "Dn")) {
+ return true;
+ }
+ state->parse_state = copy;
+
if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
ParseType(state)) {
return true;
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index d9ebd30f..a2430e7a 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -165,9 +165,6 @@ TEST(HashValueTest, PointerAlignment) {
}
}
-// TODO(EricWF): MSVC 15 has a bug that causes it to incorrectly evaluate the
-// SFINAE in internal/hash.h, causing this test to fail.
-#if !defined(_MSC_VER)
TEST(HashValueTest, PairAndTuple) {
EXPECT_TRUE((is_hashable<std::pair<int, int>>::value));
EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value));
@@ -196,7 +193,6 @@ TEST(HashValueTest, PairAndTuple) {
std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9),
std::forward_as_tuple(0, 0, -42))));
}
-#endif // !defined(_MSC_VER)
TEST(HashValueTest, CombineContiguousWorks) {
std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)};
@@ -304,16 +300,12 @@ TEST(HashValueTest, Strings) {
SpyHash(absl::string_view("ABC")));
}
-// TODO(EricWF): MSVC 15 has a bug that causes it to incorrectly evaluate the
-// SFINAE in internal/hash.h, causing this test to fail.
-#if !defined(_MSC_VER)
TEST(HashValueTest, StdArray) {
EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}})));
}
-#endif // !defined(_MSC_VER)
TEST(HashValueTest, StdBitset) {
EXPECT_TRUE((is_hashable<std::bitset<257>>::value));
@@ -414,9 +406,6 @@ TEST(HashValueTest, Variant) {
#endif
}
-// TODO(EricWF): MSVC 15 has a bug that causes it to incorrectly evaluate the
-// SFINAE in internal/hash.h, causing this test to fail.
-#if !defined(_MSC_VER)
TEST(HashValueTest, Maps) {
EXPECT_TRUE((is_hashable<std::map<int, std::string>>::value));
@@ -433,7 +422,6 @@ TEST(HashValueTest, Maps) {
MM{{0, "foo"}, {42, "bar"}}, MM{{1, "foo"}, {42, "bar"}},
MM{{1, "foo"}, {1, "foo"}, {43, "bar"}}, MM{{1, "foo"}, {43, "baz"}})));
}
-#endif // !defined(_MSC_VER)
template <typename T, typename = void>
struct IsHashCallble : std::false_type {};
@@ -511,8 +499,16 @@ struct CombineVariadic {
Int(4));
}
};
+enum class InvokeTag {
+ kUniquelyRepresented,
+ kHashValue,
+#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+ kLegacyHash,
+#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+ kStdHash,
+ kNone
+};
-using InvokeTag = absl::hash_internal::InvokeHashTag;
template <InvokeTag T>
using InvokeTagConstant = std::integral_constant<InvokeTag, T>;
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 2a45bc84..9ab98901 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -535,20 +535,6 @@ hash_range_or_bytes(H hash_state, const T* data, size_t size) {
return hash_state;
}
-// InvokeHashTag
-//
-// InvokeHash(H, const T&) invokes the appropriate hash implementation for a
-// hasher of type `H` and a value of type `T`. If `T` is not hashable, there
-// will be no matching overload of InvokeHash().
-// Note: Some platforms (eg MSVC) do not support the detect idiom on
-// std::hash. In those platforms the last fallback will be std::hash and
-// InvokeHash() will always have a valid overload even if std::hash<T> is not
-// valid.
-//
-// We try the following options in order:
-// * If is_uniquely_represented, hash bytes directly.
-// * ADL AbslHashValue(H, const T&) call.
-// * std::hash<T>
#if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) && \
ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1
@@ -556,23 +542,15 @@ hash_range_or_bytes(H hash_state, const T* data, size_t size) {
#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0
#endif
-enum class InvokeHashTag {
- kUniquelyRepresented,
- kHashValue,
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- kLegacyHash,
-#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- kStdHash,
- kNone
-};
-
// HashSelect
//
// Type trait to select the appropriate hash implementation to use.
-// HashSelect<T>::value is an instance of InvokeHashTag that indicates the best
-// available hashing mechanism.
-// See `Note` above about MSVC.
-template <typename T>
+// HashSelect::type<T> will give the proper hash implementation, to be invoked
+// as:
+// HashSelect::type<T>::Invoke(state, value)
+// Also, HashSelect::type<T>::value is a boolean equal to `true` if there is a
+// valid `Invoke` function. Types that are not hashable will have a ::value of
+// `false`.
struct HashSelect {
private:
struct State : HashStateBase<State> {
@@ -581,89 +559,75 @@ struct HashSelect {
using State::HashStateBase::combine_contiguous;
};
- // `Probe<V, Tag>::value` evaluates to `V<T>::value` if it is a valid
- // expression, and `false` otherwise.
- // `Probe<V, Tag>::tag` always evaluates to `Tag`.
- template <template <typename> class V, InvokeHashTag Tag>
- struct Probe {
- private:
- template <typename U, typename std::enable_if<V<U>::value, int>::type = 0>
- static std::true_type Test(int);
- template <typename U>
- static std::false_type Test(char);
-
- public:
- static constexpr InvokeHashTag kTag = Tag;
- static constexpr bool value = decltype(
- Test<absl::remove_const_t<absl::remove_reference_t<T>>>(0))::value;
+ struct UniquelyRepresentedProbe {
+ template <typename H, typename T>
+ static auto Invoke(H state, const T& value)
+ -> absl::enable_if_t<is_uniquely_represented<T>::value, H> {
+ return hash_internal::hash_bytes(std::move(state), value);
+ }
};
- template <typename U>
- using ProbeUniquelyRepresented = is_uniquely_represented<U>;
-
- template <typename U>
- using ProbeHashValue =
- std::is_same<State, decltype(AbslHashValue(std::declval<State>(),
- std::declval<const U&>()))>;
+ struct HashValueProbe {
+ template <typename H, typename T>
+ static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+ std::is_same<H,
+ decltype(AbslHashValue(std::move(state), value))>::value,
+ H> {
+ return AbslHashValue(std::move(state), value);
+ }
+ };
+ struct LegacyHashProbe {
#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- template <typename U>
- using ProbeLegacyHash =
- std::is_convertible<decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<
- U>()(std::declval<const U&>())),
- size_t>;
+ template <typename H, typename T>
+ static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+ std::is_convertible<
+ decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(value)),
+ size_t>::value,
+ H> {
+ return hash_internal::hash_bytes(
+ std::move(state),
+ ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
+ }
#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+ };
- template <typename U>
- using ProbeStdHash = absl::type_traits_internal::IsHashable<U>;
+ struct StdHashProbe {
+ template <typename H, typename T>
+ static auto Invoke(H state, const T& value)
+ -> absl::enable_if_t<type_traits_internal::IsHashable<T>::value, H> {
+ return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
+ }
+ };
- template <typename U>
- using ProbeNone = std::true_type;
+ template <typename Hash, typename T>
+ struct Probe : Hash {
+ private:
+ template <typename H, typename = decltype(H::Invoke(
+ std::declval<State>(), std::declval<const T&>()))>
+ static std::true_type Test(int);
+ template <typename U>
+ static std::false_type Test(char);
+
+ public:
+ static constexpr bool value = decltype(Test<Hash>(0))::value;
+ };
public:
// Probe each implementation in order.
// disjunction provides short circuting wrt instantiation.
- static constexpr InvokeHashTag value = absl::disjunction<
- Probe<ProbeUniquelyRepresented, InvokeHashTag::kUniquelyRepresented>,
- Probe<ProbeHashValue, InvokeHashTag::kHashValue>,
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- Probe<ProbeLegacyHash, InvokeHashTag::kLegacyHash>,
-#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- Probe<ProbeStdHash, InvokeHashTag::kStdHash>,
- Probe<ProbeNone, InvokeHashTag::kNone>>::kTag;
+ template <typename T>
+ using Apply = absl::disjunction< //
+ Probe<UniquelyRepresentedProbe, T>, //
+ Probe<HashValueProbe, T>, //
+ Probe<LegacyHashProbe, T>, //
+ Probe<StdHashProbe, T>, //
+ std::false_type>;
};
template <typename T>
-struct is_hashable : std::integral_constant<bool, HashSelect<T>::value !=
- InvokeHashTag::kNone> {};
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kUniquelyRepresented,
- H>
-InvokeHash(H state, const T& value) {
- return hash_internal::hash_bytes(std::move(state), value);
-}
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kHashValue, H>
-InvokeHash(H state, const T& value) {
- return AbslHashValue(std::move(state), value);
-}
-
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kLegacyHash, H>
-InvokeHash(H state, const T& value) {
- return hash_internal::hash_bytes(
- std::move(state), ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
-}
-#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kStdHash, H>
-InvokeHash(H state, const T& value) {
- return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
-}
+struct is_hashable
+ : std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
// CityHashState
class CityHashState : public HashStateBase<CityHashState> {
@@ -873,7 +837,8 @@ struct Hash
template <typename H>
template <typename T, typename... Ts>
H HashStateBase<H>::combine(H state, const T& value, const Ts&... values) {
- return H::combine(hash_internal::InvokeHash(std::move(state), value),
+ return H::combine(hash_internal::HashSelect::template Apply<T>::Invoke(
+ std::move(state), value),
values...);
}
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc
index d439900d..823d8ed4 100644
--- a/absl/strings/string_view_test.cc
+++ b/absl/strings/string_view_test.cc
@@ -756,7 +756,6 @@ TEST(StringViewTest, Remove) {
std::string s1("123");
s1 += '\0';
s1 += "456";
- absl::string_view b(s1);
absl::string_view e;
std::string s2;
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index be4ef2ea..8ce4acbb 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -856,7 +856,7 @@ bool ConsumeDurationUnit(const char** start, Duration* unit) {
} // namespace
// From Go's doc at https://golang.org/pkg/time/#ParseDuration
-// [ParseDuration] parses a duration string. A duration string is
+// [ParseDuration] parses a duration string. A duration string is
// a possibly signed sequence of decimal numbers, each with optional
// fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
// Valid time units are "ns", "us" "ms", "s", "m", "h".
diff --git a/absl/time/time.h b/absl/time/time.h
index fef305c5..59e1dc64 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -836,8 +836,8 @@ std::string UnparseFlag(Time t);
//
// See also:
// - https://github.com/google/cctz
-// - http://www.iana.org/time-zones
-// - http://en.wikipedia.org/wiki/Zoneinfo
+// - https://www.iana.org/time-zones
+// - https://en.wikipedia.org/wiki/Zoneinfo
class TimeZone {
public:
explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {}
diff --git a/absl/types/span.h b/absl/types/span.h
index ea1808d3..d7f48d9f 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -515,7 +515,7 @@ class Span {
// absl::MakeSpan(vec).last(5); // throws std::out_of_range
constexpr Span last(size_type len) const {
return (len <= size())
- ? Span(data() + size() - len, len)
+ ? Span(size() - len + data(), len)
: (base_internal::ThrowStdOutOfRange("len > size()"), Span());
}