Commit faf0a1b9 by Abseil Team Committed by Jon Cohen

- 551e205ef49682a1cb7e6e0cda46957fbcf88edd Release absl::variant. by Xiaoyi…

  - 551e205ef49682a1cb7e6e0cda46957fbcf88edd Release absl::variant. by Xiaoyi Zhang <zhangxy@google.com>
  - 01c52f640594d073c6e54c47e7853b25522cf085 Update comments in absl::variant (and minor changes to ab... by Tom Manshreck <shreck@google.com>
  - 064465e1e6b158abd8c38fd1942b4fc464b57d6a Documentation change. by Abseil Team <absl-team@google.com>
  - 58df2c8a27e80c9ea21d87c1acee8019246377c9 Relocates SetCountdown and UnsetCountdown to the exceptio... by Abseil Team <absl-team@google.com>
  - fd9d248d0948d472f2543f7fd9c0ae4a1cd60d01 Clarify thread_annotation.h documentation around local va... by Abseil Team <absl-team@google.com>
  - 0d0abaf7f0945ac5f2c5f49e78afe1b326d5aca0 Typo fix in comments. by Abseil Team <absl-team@google.com>
  - 67286d587cbd07508a81e5b8147c245a5b5538b4 Internal change. by Xiaoyi Zhang <zhangxy@google.com>

GitOrigin-RevId: 551e205ef49682a1cb7e6e0cda46957fbcf88edd
Change-Id: I1a343b080187293cb5f892a309618b5712e7aa14
parent 5b535401
......@@ -382,6 +382,19 @@
#endif
#endif
// ABSL_HAVE_STD_VARIANT
//
// Checks whether C++17 std::optional is available.
#ifdef ABSL_HAVE_STD_VARIANT
#error "ABSL_HAVE_STD_VARIANT cannot be directly set."
#endif
#ifdef __has_include
#if __has_include(<variant>) && __cplusplus >= 201703L
#define ABSL_HAVE_STD_VARIANT 1
#endif
#endif
// ABSL_HAVE_STD_STRING_VIEW
//
// Checks whether C++17 std::string_view is available.
......@@ -396,17 +409,18 @@
#endif
// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than
// the support for <optional>, <any>, <string_view>. So we use _MSC_VER to check
// whether we have VS 2017 RTM (when <optional>, <any>, <string_view> is
// implemented) or higher.
// Also, `__cplusplus` is not correctly set by MSVC, so we use `_MSVC_LANG` to
// check the language version.
// the support for <optional>, <any>, <string_view>, <variant>. So we use
// _MSC_VER to check whether we have VS 2017 RTM (when <optional>, <any>,
// <string_view>, <variant> is implemented) or higher. Also, `__cplusplus` is
// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language
// version.
// TODO(zhangxy): fix tests before enabling aliasing for `std::any`,
// `std::string_view`.
#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
// #define ABSL_HAVE_STD_ANY 1
#define ABSL_HAVE_STD_OPTIONAL 1
#define ABSL_HAVE_STD_VARIANT 1
// #define ABSL_HAVE_STD_STRING_VIEW 1
#endif
......
......@@ -27,7 +27,9 @@
namespace absl {
namespace {
using ::absl::exceptions_internal::SetCountdown;
using ::absl::exceptions_internal::TestException;
using ::absl::exceptions_internal::UnsetCountdown;
// EXPECT_NO_THROW can't inspect the thrown inspection in general.
template <typename F>
......@@ -54,7 +56,7 @@ TEST_F(ThrowingValueTest, Throws) {
// It's not guaranteed that every operator only throws *once*. The default
// ctor only throws once, though, so use it to make sure we only throw when
// the countdown hits 0
exceptions_internal::countdown = 2;
SetCountdown(2);
ExpectNoThrow([]() { ThrowingValue<> bomb; });
ExpectNoThrow([]() { ThrowingValue<> bomb; });
EXPECT_THROW(ThrowingValue<> bomb, TestException);
......
......@@ -94,6 +94,12 @@ class TestBadAllocException : public std::bad_alloc, public TestException {
extern int countdown;
// Allows the countdown variable to be set manually (defaulting to the initial
// value of 0)
inline void SetCountdown(int i = 0) { countdown = i; }
// Sets the countdown to the terminal value -1
inline void UnsetCountdown() { SetCountdown(-1); }
void MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false);
testing::AssertionResult FailureMessage(const TestException& e,
......@@ -134,7 +140,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl(
const Invariant& invariant) {
auto t_ptr = factory();
absl::optional<testing::AssertionResult> current_res;
exceptions_internal::countdown = count;
SetCountdown(count);
try {
operation(t_ptr.get());
} catch (const exceptions_internal::TestException& e) {
......@@ -143,7 +149,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl(
*current_res << e.what() << " failed invariant check";
}
}
exceptions_internal::countdown = -1;
UnsetCountdown();
return current_res;
}
......@@ -196,11 +202,6 @@ inline absl::optional<testing::AssertionResult> TestAllInvariantsAtCountdown(
extern exceptions_internal::NoThrowTag no_throw_ctor;
extern exceptions_internal::StrongGuaranteeTagType strong_guarantee;
// These are useful for tests which just construct objects and make sure there
// are no leaks.
inline void SetCountdown() { exceptions_internal::countdown = 0; }
inline void UnsetCountdown() { exceptions_internal::countdown = -1; }
// A test class which is convertible to bool. The conversion can be
// instrumented to throw at a controlled time.
class ThrowingBool {
......@@ -731,10 +732,10 @@ struct ConstructorTracker {
template <typename T, typename... Args>
T TestThrowingCtor(Args&&... args) {
struct Cleanup {
~Cleanup() { UnsetCountdown(); }
~Cleanup() { exceptions_internal::UnsetCountdown(); }
} c;
for (int count = 0;; ++count) {
exceptions_internal::countdown = count;
exceptions_internal::SetCountdown(count);
try {
return T(std::forward<Args>(args)...);
} catch (const exceptions_internal::TestException&) {
......
......@@ -47,10 +47,17 @@
// mutex. GUARDED_BY() allows the user to specify a particular mutex that
// should be held when accessing the annotated variable.
//
// Although this annotation (and PT_GUARDED_BY, below) cannot be applied to
// local variables, a local variable and its associated mutex can often be
// combined into a small class or struct, thereby allowing the annotation.
//
// Example:
//
// Mutex mu;
// int p1 GUARDED_BY(mu);
// class Foo {
// Mutex mu_;
// int p1_ GUARDED_BY(mu_);
// ...
// };
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
// PT_GUARDED_BY()
......@@ -59,17 +66,20 @@
// by a mutex when dereferencing the pointer.
//
// Example:
// Mutex mu;
// int *p1 PT_GUARDED_BY(mu);
// class Foo {
// Mutex mu_;
// int *p1_ PT_GUARDED_BY(mu_);
// ...
// };
//
// Note that a pointer variable to a shared memory location could itself be a
// shared variable.
//
// Example:
//
// // `q`, guarded by `mu1`, points to a shared memory location that is
// // guarded by `mu2`:
// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
// // `q_`, guarded by `mu1_`, points to a shared memory location that is
// // guarded by `mu2_`:
// int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
// ACQUIRED_AFTER() / ACQUIRED_BEFORE()
......@@ -80,10 +90,13 @@
// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
// and ACQUIRED_BEFORE.)
//
// As with GUARDED_BY, this is only applicable to mutexes that are shared
// fields or global variables.
//
// Example:
//
// Mutex m1;
// Mutex m2 ACQUIRED_AFTER(m1);
// Mutex m1_;
// Mutex m2_ ACQUIRED_AFTER(m1_);
#define ACQUIRED_AFTER(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
......
......@@ -36,6 +36,7 @@
#define ABSL_META_TYPE_TRAITS_H_
#include <stddef.h>
#include <functional>
#include <type_traits>
#include "absl/base/config.h"
......@@ -349,5 +350,23 @@ using underlying_type_t = typename std::underlying_type<T>::type;
template <typename T>
using result_of_t = typename std::result_of<T>::type;
namespace type_traits_internal {
template <typename Key, typename = size_t>
struct IsHashable : std::false_type {};
template <typename Key>
struct IsHashable<Key,
decltype(std::declval<std::hash<Key>>()(std::declval<Key>()))>
: std::true_type {};
template <typename Key>
struct IsHashEnabled
: absl::conjunction<std::is_default_constructible<std::hash<Key>>,
std::is_copy_constructible<std::hash<Key>>,
std::is_destructible<std::hash<Key>>,
std::is_copy_assignable<std::hash<Key>>,
IsHashable<Key>> {};
} // namespace type_traits_internal
} // namespace absl
#endif // ABSL_META_TYPE_TRAITS_H_
......@@ -165,7 +165,7 @@ DereferenceFormatter() {
//
// Example 1:
// // Joins a collection of strings. This pattern also works with a collection
// // of `asbl::string_view` or even `const char*`.
// // of `absl::string_view` or even `const char*`.
// std::vector<std::string> v = {"foo", "bar", "baz"};
// std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("foo-bar-baz", s);
......
......@@ -880,7 +880,8 @@ extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// provided format std::string. Uses strftime()-like formatting options, with
// the following extensions:
//
// - %Ez - RFC3339-compatible numeric time zone (+hh:mm or -hh:mm)
// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
// - %E#S - Seconds with # digits of fractional precision
// - %E*S - Seconds with full fractional precision (a literal '*')
// - %E#f - Fractional seconds with # digits of precision
......@@ -894,8 +895,8 @@ extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// year. A year outside of [-999:9999] when formatted with %E4Y will produce
// more than four characters, just like %Y.
//
// We recommend that format strings include %Ez so that the result uniquely
// identifies a time instant.
// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)
// so that the result uniquely identifies a time instant.
//
// Example:
//
......@@ -929,7 +930,8 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
// Parses an input std::string according to the provided format std::string and
// returns the corresponding `absl::Time`. Uses strftime()-like formatting
// options, with the same extensions as FormatTime(), but with the
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
// and %E*z also accept the same inputs.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
......@@ -940,10 +942,11 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
// "1970-01-01 00:00:00.0 +0000"
//
// For example, parsing a std::string of "15:45" (%H:%M) will return an absl::Time
// that represents "1970-01-01 15:45:00.0 +0000". Note: Since ParseTime()
// returns time instants, it makes the most sense to parse fully-specified
// date/time strings that include a UTC offset (%z/%Ez), such as those
// matching RFC3339_full above.
// that represents "1970-01-01 15:45:00.0 +0000".
//
// Note that since ParseTime() returns time instants, it makes the most sense
// to parse fully-specified date/time strings that include a UTC offset (%z,
// %Ez, or %E*z).
//
// Note also that `absl::ParseTime()` only heeds the fields year, month, day,
// hour, minute, (fractional) second, and UTC offset. Other fields, like
......@@ -974,8 +977,8 @@ bool ParseTime(const std::string& format, const std::string& input, Time* time,
std::string* err);
// Like ParseTime() above, but if the format std::string does not contain a UTC
// offset specification (%z/%Ez) then the input is interpreted in the given
// TimeZone. This means that the input, by itself, does not identify a
// offset specification (%z/%Ez/%E*z) then the input is interpreted in the
// given TimeZone. This means that the input, by itself, does not identify a
// unique instant. Being time-zone dependent, it also admits the possibility
// of ambiguity or non-existence, in which case the "pre" time (as defined
// for ConvertDateTime()) is returned. For these reasons we recommend that
......
......@@ -165,6 +165,17 @@ cc_library(
],
)
cc_library(
name = "bad_variant_access",
srcs = ["bad_variant_access.cc"],
hdrs = ["bad_variant_access.h"],
copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS,
deps = [
"//absl/base",
"//absl/base:config",
],
)
cc_test(
name = "optional_test",
size = "small",
......@@ -181,3 +192,34 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_library(
name = "variant",
srcs = ["internal/variant.h"],
hdrs = ["variant.h"],
copts = ABSL_DEFAULT_COPTS,
deps = [
":bad_variant_access",
"//absl/base:base_internal",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/meta:type_traits",
"//absl/utility",
],
)
cc_test(
name = "variant_test",
size = "small",
srcs = ["variant_test.cc"],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
deps = [
":variant",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
"//absl/meta:type_traits",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],
)
......@@ -20,6 +20,7 @@ list(APPEND TYPES_PUBLIC_HEADERS
"bad_optional_access.h"
"optional.h"
"span.h"
"variant.h"
)
......@@ -95,7 +96,19 @@ absl_library(
bad_optional_access
)
# variant library
absl_library(
TARGET
absl_variant
SOURCES
"bad_variant_access.h" "bad_variant_access.cc" "variant.h" "internal/variant.h"
PUBLIC_LIBRARIES
absl::base absl::meta absl::utility
PRIVATE_COMPILE_FLAGS
${ABSL_EXCEPTIONS_FLAG}
EXPORT_NAME
variant
)
#
## TESTS
......
......@@ -172,7 +172,9 @@ const ValueType* any_cast(const any* operand) noexcept;
template <typename ValueType>
ValueType* any_cast(any* operand) noexcept;
// any
// -----------------------------------------------------------------------------
// absl::any
// -----------------------------------------------------------------------------
//
// An `absl::any` object provides the facility to either store an instance of a
// type, known as the "contained object", or no value. An `absl::any` is used to
......
// Copyright 2017 The Abseil Authors.
// 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.
......@@ -11,6 +11,12 @@
// 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.
//
// -----------------------------------------------------------------------------
// bad_any_cast.h
// -----------------------------------------------------------------------------
//
// This header file defines the `absl::bad_any_cast` type.
#ifndef ABSL_TYPES_BAD_ANY_CAST_H_
#define ABSL_TYPES_BAD_ANY_CAST_H_
......@@ -19,21 +25,28 @@
namespace absl {
////////////////////////
// [any.bad_any_cast] //
////////////////////////
// Objects of type bad_any_cast are thrown by a failed any_cast.
// -----------------------------------------------------------------------------
// bad_any_cast
// -----------------------------------------------------------------------------
//
// An `absl::bad_any_cast` type is an exception type that is thrown when
// failing to successfully cast the return value of an `absl::any` object.
//
// Example:
//
// auto a = absl::any(65);
// absl::any_cast<int>(a); // 65
// try {
// absl::any_cast<char>(a);
// } catch(const absl::bad_any_cast& e) {
// std::cout << "Bad any cast: " << e.what() << '\n';
// }
class bad_any_cast : public std::bad_cast {
public:
~bad_any_cast() override;
const char* what() const noexcept override;
};
//////////////////////////////////////////////
// Implementation-details beyond this point //
//////////////////////////////////////////////
namespace any_internal {
[[noreturn]] void ThrowBadAnyCast();
......
// Copyright 2017 The Abseil Authors.
// 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.
......@@ -11,6 +11,12 @@
// 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.
//
// -----------------------------------------------------------------------------
// bad_optional_access.h
// -----------------------------------------------------------------------------
//
// This header file defines the `absl::bad_optional_access` type.
#ifndef ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
#define ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
......@@ -19,6 +25,23 @@
namespace absl {
// -----------------------------------------------------------------------------
// bad_optional_access
// -----------------------------------------------------------------------------
//
// An `absl::bad_optional_access` type is an exception type that is thrown when
// attempting to access an `absl::optional` object that does not contain a
// value.
//
// Example:
//
// absl::optional<int> o;
//
// try {
// int n = o.value();
// } catch(const absl::bad_optional_access& e) {
// std::cout << "Bad optional access: " << e.what() << '\n';
// }
class bad_optional_access : public std::exception {
public:
bad_optional_access() = default;
......
// Copyright 2017 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
//
// http://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/bad_variant_access.h"
#include <cstdlib>
#include <stdexcept>
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
namespace absl {
//////////////////////////
// [variant.bad.access] //
//////////////////////////
bad_variant_access::~bad_variant_access() = default;
const char* bad_variant_access::what() const noexcept {
return "Bad variant access";
}
namespace variant_internal {
void ThrowBadVariantAccess() {
#ifdef ABSL_HAVE_EXCEPTIONS
throw bad_variant_access();
#else
ABSL_RAW_LOG(FATAL, "Bad variant access");
abort(); // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn.
#endif
}
void Rethrow() {
#ifdef ABSL_HAVE_EXCEPTIONS
throw;
#else
ABSL_RAW_LOG(FATAL,
"Internal error in absl::variant implementation. Attempted to "
"rethrow an exception when building with exceptions disabled.");
abort(); // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn.
#endif
}
} // namespace variant_internal
} // namespace absl
// 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
//
// http://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.
//
// -----------------------------------------------------------------------------
// bad_variant_access.h
// -----------------------------------------------------------------------------
//
// This header file defines the `absl::bad_variant_access` type.
#ifndef ABSL_TYPES_BAD_VARIANT_ACCESS_H_
#define ABSL_TYPES_BAD_VARIANT_ACCESS_H_
#include <stdexcept>
namespace absl {
// -----------------------------------------------------------------------------
// bad_variant_access
// -----------------------------------------------------------------------------
//
// An `absl::bad_variant_access` type is an exception type that is thrown in
// the following cases:
//
// * Calling `absl::get(absl::variant) with an index or type that does not
// match the currently selected alternative type
// * Calling `absl::visit on an `absl::variant` that is in the
// `variant::valueless_by_exception` state.
//
// Example:
//
// absl::variant<int, std::string> v;
// v = 1;
// try {
// absl::get<std::string>(v);
// } catch(const absl::bad_variant_access& e) {
// std::cout << "Bad variant access: " << e.what() << '\n';
// }
class bad_variant_access : public std::exception {
public:
bad_variant_access() noexcept = default;
~bad_variant_access() override;
const char* what() const noexcept override;
};
namespace variant_internal {
[[noreturn]] void ThrowBadVariantAccess();
[[noreturn]] void Rethrow();
} // namespace variant_internal
} // namespace absl
#endif // ABSL_TYPES_BAD_VARIANT_ACCESS_H_
//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
......@@ -94,7 +93,9 @@ using std::nullopt;
namespace absl {
// optional
// -----------------------------------------------------------------------------
// absl::optional
// -----------------------------------------------------------------------------
//
// A value of type `absl::optional<T>` holds either a value of `T` or an
// "empty" value. When it holds a value of `T`, it stores it as a direct
......
......@@ -161,7 +161,7 @@ ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
#endif // ABSL_HAVE_STD_OPTIONAL
#ifdef ABSL_HAVE_STD_ANY
#if defined(ABSL_HAVE_STD_ANY) || defined(ABSL_HAVE_STD_VARIANT)
using std::in_place_type_t;
#else
......@@ -172,7 +172,11 @@ using std::in_place_type_t;
// for C++17's `std::in_place_type_t`.
template <typename T>
struct in_place_type_t {};
#endif // ABSL_HAVE_STD_ANY
#endif // ABSL_HAVE_STD_ANY || ABSL_HAVE_STD_VARIANT
#ifdef ABSL_HAVE_STD_VARIANT
using std::in_place_index_t;
#else
// in_place_index_t
//
......@@ -181,6 +185,7 @@ struct in_place_type_t {};
// for C++17's `std::in_place_index_t`.
template <size_t I>
struct in_place_index_t {};
#endif // ABSL_HAVE_STD_VARIANT
// Constexpr move and forward
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment