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 @@ ...@@ -382,6 +382,19 @@
#endif #endif
#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 // ABSL_HAVE_STD_STRING_VIEW
// //
// Checks whether C++17 std::string_view is available. // Checks whether C++17 std::string_view is available.
...@@ -396,17 +409,18 @@ ...@@ -396,17 +409,18 @@
#endif #endif
// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than // 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 // the support for <optional>, <any>, <string_view>, <variant>. So we use
// whether we have VS 2017 RTM (when <optional>, <any>, <string_view> is // _MSC_VER to check whether we have VS 2017 RTM (when <optional>, <any>,
// implemented) or higher. // <string_view>, <variant> is implemented) or higher. Also, `__cplusplus` is
// Also, `__cplusplus` is not correctly set by MSVC, so we use `_MSVC_LANG` to // not correctly set by MSVC, so we use `_MSVC_LANG` to check the language
// check the language version. // version.
// TODO(zhangxy): fix tests before enabling aliasing for `std::any`, // TODO(zhangxy): fix tests before enabling aliasing for `std::any`,
// `std::string_view`. // `std::string_view`.
#if defined(_MSC_VER) && _MSC_VER >= 1910 && \ #if defined(_MSC_VER) && _MSC_VER >= 1910 && \
((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402) ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
// #define ABSL_HAVE_STD_ANY 1 // #define ABSL_HAVE_STD_ANY 1
#define ABSL_HAVE_STD_OPTIONAL 1 #define ABSL_HAVE_STD_OPTIONAL 1
#define ABSL_HAVE_STD_VARIANT 1
// #define ABSL_HAVE_STD_STRING_VIEW 1 // #define ABSL_HAVE_STD_STRING_VIEW 1
#endif #endif
......
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
namespace absl { namespace absl {
namespace { namespace {
using ::absl::exceptions_internal::SetCountdown;
using ::absl::exceptions_internal::TestException; using ::absl::exceptions_internal::TestException;
using ::absl::exceptions_internal::UnsetCountdown;
// EXPECT_NO_THROW can't inspect the thrown inspection in general. // EXPECT_NO_THROW can't inspect the thrown inspection in general.
template <typename F> template <typename F>
...@@ -54,7 +56,7 @@ TEST_F(ThrowingValueTest, Throws) { ...@@ -54,7 +56,7 @@ TEST_F(ThrowingValueTest, Throws) {
// It's not guaranteed that every operator only throws *once*. The default // 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 // ctor only throws once, though, so use it to make sure we only throw when
// the countdown hits 0 // the countdown hits 0
exceptions_internal::countdown = 2; SetCountdown(2);
ExpectNoThrow([]() { ThrowingValue<> bomb; }); ExpectNoThrow([]() { ThrowingValue<> bomb; });
ExpectNoThrow([]() { ThrowingValue<> bomb; }); ExpectNoThrow([]() { ThrowingValue<> bomb; });
EXPECT_THROW(ThrowingValue<> bomb, TestException); EXPECT_THROW(ThrowingValue<> bomb, TestException);
......
...@@ -94,6 +94,12 @@ class TestBadAllocException : public std::bad_alloc, public TestException { ...@@ -94,6 +94,12 @@ class TestBadAllocException : public std::bad_alloc, public TestException {
extern int countdown; 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); void MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false);
testing::AssertionResult FailureMessage(const TestException& e, testing::AssertionResult FailureMessage(const TestException& e,
...@@ -134,7 +140,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl( ...@@ -134,7 +140,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl(
const Invariant& invariant) { const Invariant& invariant) {
auto t_ptr = factory(); auto t_ptr = factory();
absl::optional<testing::AssertionResult> current_res; absl::optional<testing::AssertionResult> current_res;
exceptions_internal::countdown = count; SetCountdown(count);
try { try {
operation(t_ptr.get()); operation(t_ptr.get());
} catch (const exceptions_internal::TestException& e) { } catch (const exceptions_internal::TestException& e) {
...@@ -143,7 +149,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl( ...@@ -143,7 +149,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl(
*current_res << e.what() << " failed invariant check"; *current_res << e.what() << " failed invariant check";
} }
} }
exceptions_internal::countdown = -1; UnsetCountdown();
return current_res; return current_res;
} }
...@@ -196,11 +202,6 @@ inline absl::optional<testing::AssertionResult> TestAllInvariantsAtCountdown( ...@@ -196,11 +202,6 @@ inline absl::optional<testing::AssertionResult> TestAllInvariantsAtCountdown(
extern exceptions_internal::NoThrowTag no_throw_ctor; extern exceptions_internal::NoThrowTag no_throw_ctor;
extern exceptions_internal::StrongGuaranteeTagType strong_guarantee; 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 // A test class which is convertible to bool. The conversion can be
// instrumented to throw at a controlled time. // instrumented to throw at a controlled time.
class ThrowingBool { class ThrowingBool {
...@@ -731,10 +732,10 @@ struct ConstructorTracker { ...@@ -731,10 +732,10 @@ struct ConstructorTracker {
template <typename T, typename... Args> template <typename T, typename... Args>
T TestThrowingCtor(Args&&... args) { T TestThrowingCtor(Args&&... args) {
struct Cleanup { struct Cleanup {
~Cleanup() { UnsetCountdown(); } ~Cleanup() { exceptions_internal::UnsetCountdown(); }
} c; } c;
for (int count = 0;; ++count) { for (int count = 0;; ++count) {
exceptions_internal::countdown = count; exceptions_internal::SetCountdown(count);
try { try {
return T(std::forward<Args>(args)...); return T(std::forward<Args>(args)...);
} catch (const exceptions_internal::TestException&) { } catch (const exceptions_internal::TestException&) {
......
...@@ -47,10 +47,17 @@ ...@@ -47,10 +47,17 @@
// mutex. GUARDED_BY() allows the user to specify a particular mutex that // mutex. GUARDED_BY() allows the user to specify a particular mutex that
// should be held when accessing the annotated variable. // 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: // Example:
// //
// Mutex mu; // class Foo {
// int p1 GUARDED_BY(mu); // Mutex mu_;
// int p1_ GUARDED_BY(mu_);
// ...
// };
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
// PT_GUARDED_BY() // PT_GUARDED_BY()
...@@ -59,17 +66,20 @@ ...@@ -59,17 +66,20 @@
// by a mutex when dereferencing the pointer. // by a mutex when dereferencing the pointer.
// //
// Example: // Example:
// Mutex mu; // class Foo {
// int *p1 PT_GUARDED_BY(mu); // Mutex mu_;
// int *p1_ PT_GUARDED_BY(mu_);
// ...
// };
// //
// Note that a pointer variable to a shared memory location could itself be a // Note that a pointer variable to a shared memory location could itself be a
// shared variable. // shared variable.
// //
// Example: // Example:
// //
// // `q`, guarded by `mu1`, points to a shared memory location that is // // `q_`, guarded by `mu1_`, points to a shared memory location that is
// // guarded by `mu2`: // // guarded by `mu2_`:
// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2); // int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) #define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
// ACQUIRED_AFTER() / ACQUIRED_BEFORE() // ACQUIRED_AFTER() / ACQUIRED_BEFORE()
...@@ -80,10 +90,13 @@ ...@@ -80,10 +90,13 @@
// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER // (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
// and ACQUIRED_BEFORE.) // and ACQUIRED_BEFORE.)
// //
// As with GUARDED_BY, this is only applicable to mutexes that are shared
// fields or global variables.
//
// Example: // Example:
// //
// Mutex m1; // Mutex m1_;
// Mutex m2 ACQUIRED_AFTER(m1); // Mutex m2_ ACQUIRED_AFTER(m1_);
#define ACQUIRED_AFTER(...) \ #define ACQUIRED_AFTER(...) \
THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#define ABSL_META_TYPE_TRAITS_H_ #define ABSL_META_TYPE_TRAITS_H_
#include <stddef.h> #include <stddef.h>
#include <functional>
#include <type_traits> #include <type_traits>
#include "absl/base/config.h" #include "absl/base/config.h"
...@@ -349,5 +350,23 @@ using underlying_type_t = typename std::underlying_type<T>::type; ...@@ -349,5 +350,23 @@ using underlying_type_t = typename std::underlying_type<T>::type;
template <typename T> template <typename T>
using result_of_t = typename std::result_of<T>::type; 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 } // namespace absl
#endif // ABSL_META_TYPE_TRAITS_H_ #endif // ABSL_META_TYPE_TRAITS_H_
...@@ -165,7 +165,7 @@ DereferenceFormatter() { ...@@ -165,7 +165,7 @@ DereferenceFormatter() {
// //
// Example 1: // Example 1:
// // Joins a collection of strings. This pattern also works with a collection // // 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::vector<std::string> v = {"foo", "bar", "baz"};
// std::string s = absl::StrJoin(v, "-"); // std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("foo-bar-baz", s); // EXPECT_EQ("foo-bar-baz", s);
......
...@@ -880,7 +880,8 @@ extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z ...@@ -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 // provided format std::string. Uses strftime()-like formatting options, with
// the following extensions: // 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 # digits of fractional precision
// - %E*S - Seconds with full fractional precision (a literal '*') // - %E*S - Seconds with full fractional precision (a literal '*')
// - %E#f - Fractional seconds with # digits of precision // - %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 ...@@ -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 // year. A year outside of [-999:9999] when formatted with %E4Y will produce
// more than four characters, just like %Y. // more than four characters, just like %Y.
// //
// We recommend that format strings include %Ez so that the result uniquely // We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)
// identifies a time instant. // so that the result uniquely identifies a time instant.
// //
// Example: // Example:
// //
...@@ -929,7 +930,8 @@ inline std::ostream& operator<<(std::ostream& os, Time t) { ...@@ -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 // Parses an input std::string according to the provided format std::string and
// returns the corresponding `absl::Time`. Uses strftime()-like formatting // returns the corresponding `absl::Time`. Uses strftime()-like formatting
// options, with the same extensions as FormatTime(), but with the // 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 // %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes // should always be terminated with a non-numeric. %E4Y always consumes
...@@ -940,10 +942,11 @@ inline std::ostream& operator<<(std::ostream& os, Time t) { ...@@ -940,10 +942,11 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
// "1970-01-01 00:00:00.0 +0000" // "1970-01-01 00:00:00.0 +0000"
// //
// For example, parsing a std::string of "15:45" (%H:%M) will return an absl::Time // 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() // that represents "1970-01-01 15:45:00.0 +0000".
// 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 // Note that since ParseTime() returns time instants, it makes the most sense
// matching RFC3339_full above. // 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, // Note also that `absl::ParseTime()` only heeds the fields year, month, day,
// hour, minute, (fractional) second, and UTC offset. Other fields, like // 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, ...@@ -974,8 +977,8 @@ bool ParseTime(const std::string& format, const std::string& input, Time* time,
std::string* err); std::string* err);
// Like ParseTime() above, but if the format std::string does not contain a UTC // 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 // offset specification (%z/%Ez/%E*z) then the input is interpreted in the
// TimeZone. This means that the input, by itself, does not identify a // given TimeZone. This means that the input, by itself, does not identify a
// unique instant. Being time-zone dependent, it also admits the possibility // unique instant. Being time-zone dependent, it also admits the possibility
// of ambiguity or non-existence, in which case the "pre" time (as defined // of ambiguity or non-existence, in which case the "pre" time (as defined
// for ConvertDateTime()) is returned. For these reasons we recommend that // for ConvertDateTime()) is returned. For these reasons we recommend that
......
...@@ -165,6 +165,17 @@ cc_library( ...@@ -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( cc_test(
name = "optional_test", name = "optional_test",
size = "small", size = "small",
...@@ -181,3 +192,34 @@ cc_test( ...@@ -181,3 +192,34 @@ cc_test(
"@com_google_googletest//:gtest_main", "@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 ...@@ -20,6 +20,7 @@ list(APPEND TYPES_PUBLIC_HEADERS
"bad_optional_access.h" "bad_optional_access.h"
"optional.h" "optional.h"
"span.h" "span.h"
"variant.h"
) )
...@@ -95,7 +96,19 @@ absl_library( ...@@ -95,7 +96,19 @@ absl_library(
bad_optional_access 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 ## TESTS
......
...@@ -172,7 +172,9 @@ const ValueType* any_cast(const any* operand) noexcept; ...@@ -172,7 +172,9 @@ const ValueType* any_cast(const any* operand) noexcept;
template <typename ValueType> template <typename ValueType>
ValueType* any_cast(any* operand) noexcept; ValueType* any_cast(any* operand) noexcept;
// any // -----------------------------------------------------------------------------
// absl::any
// -----------------------------------------------------------------------------
// //
// An `absl::any` object provides the facility to either store an instance of a // 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 // 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"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
...@@ -11,6 +11,12 @@ ...@@ -11,6 +11,12 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // 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_ #ifndef ABSL_TYPES_BAD_ANY_CAST_H_
#define ABSL_TYPES_BAD_ANY_CAST_H_ #define ABSL_TYPES_BAD_ANY_CAST_H_
...@@ -19,21 +25,28 @@ ...@@ -19,21 +25,28 @@
namespace absl { namespace absl {
//////////////////////// // -----------------------------------------------------------------------------
// [any.bad_any_cast] // // bad_any_cast
//////////////////////// // -----------------------------------------------------------------------------
//
// Objects of type bad_any_cast are thrown by a failed 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 { class bad_any_cast : public std::bad_cast {
public: public:
~bad_any_cast() override; ~bad_any_cast() override;
const char* what() const noexcept override; const char* what() const noexcept override;
}; };
//////////////////////////////////////////////
// Implementation-details beyond this point //
//////////////////////////////////////////////
namespace any_internal { namespace any_internal {
[[noreturn]] void ThrowBadAnyCast(); [[noreturn]] void ThrowBadAnyCast();
......
// Copyright 2017 The Abseil Authors. // Copyright 2018 The Abseil Authors.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
...@@ -11,6 +11,12 @@ ...@@ -11,6 +11,12 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // 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_ #ifndef ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
#define ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_ #define ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
...@@ -19,6 +25,23 @@ ...@@ -19,6 +25,23 @@
namespace absl { 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 { class bad_optional_access : public std::exception {
public: public:
bad_optional_access() = default; 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. // Copyright 2017 The Abseil Authors.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
...@@ -94,7 +93,9 @@ using std::nullopt; ...@@ -94,7 +93,9 @@ using std::nullopt;
namespace absl { namespace absl {
// optional // -----------------------------------------------------------------------------
// absl::optional
// -----------------------------------------------------------------------------
// //
// A value of type `absl::optional<T>` holds either a value of `T` or an // 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 // "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, {}); ...@@ -161,7 +161,7 @@ ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
#endif // ABSL_HAVE_STD_OPTIONAL #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; using std::in_place_type_t;
#else #else
...@@ -172,7 +172,11 @@ using std::in_place_type_t; ...@@ -172,7 +172,11 @@ using std::in_place_type_t;
// for C++17's `std::in_place_type_t`. // for C++17's `std::in_place_type_t`.
template <typename T> template <typename T>
struct in_place_type_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 // in_place_index_t
// //
...@@ -181,6 +185,7 @@ struct in_place_type_t {}; ...@@ -181,6 +185,7 @@ struct in_place_type_t {};
// for C++17's `std::in_place_index_t`. // for C++17's `std::in_place_index_t`.
template <size_t I> template <size_t I>
struct in_place_index_t {}; struct in_place_index_t {};
#endif // ABSL_HAVE_STD_VARIANT
// Constexpr move and forward // 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