diff options
Diffstat (limited to 'absl/types')
-rw-r--r-- | absl/types/BUILD.bazel | 21 | ||||
-rw-r--r-- | absl/types/CMakeLists.txt | 10 | ||||
-rw-r--r-- | absl/types/any.h | 8 | ||||
-rw-r--r-- | absl/types/any_exception_safety_test.cc | 8 | ||||
-rw-r--r-- | absl/types/bad_any_cast.cc | 8 | ||||
-rw-r--r-- | absl/types/bad_any_cast.h | 20 | ||||
-rw-r--r-- | absl/types/bad_optional_access.cc | 8 | ||||
-rw-r--r-- | absl/types/bad_optional_access.h | 20 | ||||
-rw-r--r-- | absl/types/bad_variant_access.cc | 8 | ||||
-rw-r--r-- | absl/types/bad_variant_access.h | 20 | ||||
-rw-r--r-- | absl/types/internal/variant.h | 88 | ||||
-rw-r--r-- | absl/types/optional.cc | 4 | ||||
-rw-r--r-- | absl/types/optional.h | 25 | ||||
-rw-r--r-- | absl/types/optional_exception_safety_test.cc | 30 | ||||
-rw-r--r-- | absl/types/optional_test.cc | 33 | ||||
-rw-r--r-- | absl/types/span.h | 55 | ||||
-rw-r--r-- | absl/types/span_test.cc | 3 | ||||
-rw-r--r-- | absl/types/variant.h | 76 | ||||
-rw-r--r-- | absl/types/variant_benchmark.cc | 4 | ||||
-rw-r--r-- | absl/types/variant_exception_safety_test.cc | 108 | ||||
-rw-r--r-- | absl/types/variant_test.cc | 25 |
21 files changed, 348 insertions, 234 deletions
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index c50ec425..d56fea6e 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -19,6 +19,7 @@ load( "ABSL_DEFAULT_COPTS", "ABSL_TEST_COPTS", "ABSL_EXCEPTIONS_FLAG", + "ABSL_EXCEPTIONS_FLAG_LINKOPTS", ) package(default_visibility = ["//visibility:public"]) @@ -42,7 +43,10 @@ cc_library( name = "bad_any_cast", hdrs = ["bad_any_cast.h"], copts = ABSL_DEFAULT_COPTS, - deps = [":bad_any_cast_impl"], + deps = [ + ":bad_any_cast_impl", + "//absl/base:config", + ], ) cc_library( @@ -52,6 +56,7 @@ cc_library( "bad_any_cast.h", ], copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, visibility = ["//visibility:private"], deps = [ "//absl/base", @@ -66,6 +71,7 @@ cc_test( "any_test.cc", ], copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ ":any", "//absl/base", @@ -97,6 +103,7 @@ cc_test( name = "any_exception_safety_test", srcs = ["any_exception_safety_test.cc"], copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ ":any", "//absl/base:exception_safety_testing", @@ -121,6 +128,7 @@ cc_test( size = "small", srcs = ["span_test.cc"], copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ ":span", "//absl/base:config", @@ -128,6 +136,7 @@ cc_test( "//absl/base:exception_testing", "//absl/container:fixed_array", "//absl/container:inlined_vector", + "//absl/hash:hash_testing", "//absl/strings", "@com_google_googletest//:gtest_main", ], @@ -145,6 +154,7 @@ cc_test( "//absl/base:exception_testing", "//absl/container:fixed_array", "//absl/container:inlined_vector", + "//absl/hash:hash_testing", "//absl/strings", "@com_google_googletest//:gtest_main", ], @@ -158,6 +168,7 @@ cc_library( deps = [ ":bad_optional_access", "//absl/base:config", + "//absl/base:core_headers", "//absl/memory", "//absl/meta:type_traits", "//absl/utility", @@ -169,6 +180,7 @@ cc_library( srcs = ["bad_optional_access.cc"], hdrs = ["bad_optional_access.h"], copts = ABSL_DEFAULT_COPTS + ABSL_EXCEPTIONS_FLAG, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ "//absl/base", "//absl/base:config", @@ -180,6 +192,7 @@ cc_library( srcs = ["bad_variant_access.cc"], hdrs = ["bad_variant_access.h"], copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ "//absl/base", "//absl/base:config", @@ -193,6 +206,7 @@ cc_test( "optional_test.cc", ], copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ ":optional", "//absl/base", @@ -209,6 +223,7 @@ cc_test( "optional_exception_safety_test.cc", ], copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ ":optional", "//absl/base:exception_safety_testing", @@ -236,6 +251,7 @@ cc_test( size = "small", srcs = ["variant_test.cc"], copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ ":variant", "//absl/base:config", @@ -253,6 +269,7 @@ cc_test( "variant_benchmark.cc", ], copts = ABSL_TEST_COPTS, + tags = ["benchmark"], deps = [ ":variant", "//absl/utility", @@ -267,8 +284,10 @@ cc_test( "variant_exception_safety_test.cc", ], copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG, + linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ ":variant", + "//absl/base:config", "//absl/base:exception_safety_testing", "//absl/memory", "@com_google_googletest//:gtest_main", diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt index 2f2e3a77..e8620766 100644 --- a/absl/types/CMakeLists.txt +++ b/absl/types/CMakeLists.txt @@ -123,7 +123,7 @@ absl_library( # test any_test set(ANY_TEST_SRC "any_test.cc") -set(ANY_TEST_PUBLIC_LIBRARIES absl::base absl::throw_delegate absl::any absl::bad_any_cast test_instance_tracker_lib) +set(ANY_TEST_PUBLIC_LIBRARIES absl::base absl_internal_throw_delegate absl::any absl::bad_any_cast absl::test_instance_tracker) absl_test( TARGET @@ -152,7 +152,7 @@ set(ANY_EXCEPTION_SAFETY_TEST_SRC "any_exception_safety_test.cc") set(ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES absl::any absl::base - absl_base_internal_exception_safety_testing + absl_internal_exception_safety_testing ) absl_test( @@ -169,7 +169,7 @@ absl_test( # test span_test set(SPAN_TEST_SRC "span_test.cc") -set(SPAN_TEST_PUBLIC_LIBRARIES absl::base absl::strings absl::throw_delegate absl::span test_instance_tracker_lib) +set(SPAN_TEST_PUBLIC_LIBRARIES absl::base absl::strings absl_internal_throw_delegate absl::span absl::test_instance_tracker) absl_test( TARGET @@ -197,7 +197,7 @@ absl_test( # test optional_test set(OPTIONAL_TEST_SRC "optional_test.cc") -set(OPTIONAL_TEST_PUBLIC_LIBRARIES absl::base absl::throw_delegate absl::optional absl_bad_optional_access) +set(OPTIONAL_TEST_PUBLIC_LIBRARIES absl::base absl_internal_throw_delegate absl::optional absl_bad_optional_access) absl_test( TARGET @@ -213,7 +213,7 @@ absl_test( set(OPTIONAL_EXCEPTION_SAFETY_TEST_SRC "optional_exception_safety_test.cc") set(OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES absl::optional - absl_base_internal_exception_safety_testing + absl_internal_exception_safety_testing ) absl_test( diff --git a/absl/types/any.h b/absl/types/any.h index 9d297dc8..dc3bfcfe 100644 --- a/absl/types/any.h +++ b/absl/types/any.h @@ -61,12 +61,12 @@ #include <any> namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { using std::any; using std::any_cast; using std::bad_any_cast; using std::make_any; -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl #else // ABSL_HAVE_STD_ANY @@ -93,7 +93,7 @@ using std::make_any; #endif // !defined(__GNUC__) || defined(__GXX_RTTI) namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { namespace any_internal { @@ -533,7 +533,7 @@ T* any_cast(any* operand) noexcept { : nullptr; } -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl #undef ABSL_ANY_DETAIL_HAS_RTTI diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc index 36955f6c..f9dd8c48 100644 --- a/absl/types/any_exception_safety_test.cc +++ b/absl/types/any_exception_safety_test.cc @@ -62,7 +62,7 @@ testing::AssertionResult AnyInvariants(absl::any* a) { static_cast<void>(unused); return AssertionFailure() << "A reset `any` should not be able to be any_cast"; - } catch (absl::bad_any_cast) { + } catch (const absl::bad_any_cast&) { } catch (...) { return AssertionFailure() << "Unexpected exception thrown from absl::any_cast"; @@ -107,7 +107,7 @@ TEST(AnyExceptionSafety, Assignment) { }; auto any_strong_tester = testing::MakeExceptionSafetyTester() .WithInitialValue(original) - .WithInvariants(AnyInvariants, any_is_strong); + .WithContracts(AnyInvariants, any_is_strong); Thrower val(2); absl::any any_val(val); @@ -129,7 +129,7 @@ TEST(AnyExceptionSafety, Assignment) { auto strong_empty_any_tester = testing::MakeExceptionSafetyTester() .WithInitialValue(absl::any{}) - .WithInvariants(AnyInvariants, empty_any_is_strong); + .WithContracts(AnyInvariants, empty_any_is_strong); EXPECT_TRUE(strong_empty_any_tester.Test(assign_any)); EXPECT_TRUE(strong_empty_any_tester.Test(assign_val)); @@ -142,7 +142,7 @@ TEST(AnyExceptionSafety, Emplace) { absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor}; auto one_tester = testing::MakeExceptionSafetyTester() .WithInitialValue(initial_val) - .WithInvariants(AnyInvariants, AnyIsEmpty); + .WithContracts(AnyInvariants, AnyIsEmpty); auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); }; auto emp_throwervec = [](absl::any* ap) { diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc index 537767cd..6244d09e 100644 --- a/absl/types/bad_any_cast.cc +++ b/absl/types/bad_any_cast.cc @@ -14,13 +14,15 @@ #include "absl/types/bad_any_cast.h" +#ifndef ABSL_HAVE_STD_ANY + #include <cstdlib> #include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { bad_any_cast::~bad_any_cast() = default; @@ -38,5 +40,7 @@ void ThrowBadAnyCast() { } } // namespace any_internal -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl + +#endif // ABSL_HAVE_STD_ANY diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h index 3f89e75d..7df9afbb 100644 --- a/absl/types/bad_any_cast.h +++ b/absl/types/bad_any_cast.h @@ -23,8 +23,22 @@ #include <typeinfo> +#include "absl/base/config.h" + +#ifdef ABSL_HAVE_STD_ANY + +#include <any> + +namespace absl { +inline namespace lts_2018_12_18 { +using std::bad_any_cast; +} // inline namespace lts_2018_12_18 +} // namespace absl + +#else // ABSL_HAVE_STD_ANY + namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { // ----------------------------------------------------------------------------- // bad_any_cast @@ -53,7 +67,9 @@ namespace any_internal { [[noreturn]] void ThrowBadAnyCast(); } // namespace any_internal -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl +#endif // ABSL_HAVE_STD_ANY + #endif // ABSL_TYPES_BAD_ANY_CAST_H_ diff --git a/absl/types/bad_optional_access.cc b/absl/types/bad_optional_access.cc index c5508678..2dc74d3b 100644 --- a/absl/types/bad_optional_access.cc +++ b/absl/types/bad_optional_access.cc @@ -14,13 +14,15 @@ #include "absl/types/bad_optional_access.h" +#ifndef ABSL_HAVE_STD_OPTIONAL + #include <cstdlib> #include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { bad_optional_access::~bad_optional_access() = default; @@ -40,5 +42,7 @@ void throw_bad_optional_access() { } } // namespace optional_internal -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl + +#endif // ABSL_HAVE_STD_OPTIONAL diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h index d468211a..1f56ff64 100644 --- a/absl/types/bad_optional_access.h +++ b/absl/types/bad_optional_access.h @@ -23,8 +23,22 @@ #include <stdexcept> +#include "absl/base/config.h" + +#ifdef ABSL_HAVE_STD_OPTIONAL + +#include <optional> + +namespace absl { +inline namespace lts_2018_12_18 { +using std::bad_optional_access; +} // inline namespace lts_2018_12_18 +} // namespace absl + +#else // ABSL_HAVE_STD_OPTIONAL + namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { // ----------------------------------------------------------------------------- // bad_optional_access @@ -56,7 +70,9 @@ namespace optional_internal { [[noreturn]] void throw_bad_optional_access(); } // namespace optional_internal -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl +#endif // ABSL_HAVE_STD_OPTIONAL + #endif // ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_ diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc index a796cfaa..a646ff53 100644 --- a/absl/types/bad_variant_access.cc +++ b/absl/types/bad_variant_access.cc @@ -14,6 +14,8 @@ #include "absl/types/bad_variant_access.h" +#ifndef ABSL_HAVE_STD_VARIANT + #include <cstdlib> #include <stdexcept> @@ -21,7 +23,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { ////////////////////////// // [variant.bad.access] // @@ -56,5 +58,7 @@ void Rethrow() { } } // namespace variant_internal -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl + +#endif // ABSL_HAVE_STD_VARIANT diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h index 2e007315..e0490842 100644 --- a/absl/types/bad_variant_access.h +++ b/absl/types/bad_variant_access.h @@ -23,8 +23,22 @@ #include <stdexcept> +#include "absl/base/config.h" + +#ifdef ABSL_HAVE_STD_VARIANT + +#include <variant> + +namespace absl { +inline namespace lts_2018_12_18 { +using std::bad_variant_access; +} // inline namespace lts_2018_12_18 +} // namespace absl + +#else // ABSL_HAVE_STD_VARIANT + namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { // ----------------------------------------------------------------------------- // bad_variant_access @@ -60,7 +74,9 @@ namespace variant_internal { [[noreturn]] void Rethrow(); } // namespace variant_internal -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl +#endif // ABSL_HAVE_STD_VARIANT + #endif // ABSL_TYPES_BAD_VARIANT_ACCESS_H_ diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h index 3b884647..875f88e0 100644 --- a/absl/types/internal/variant.h +++ b/absl/types/internal/variant.h @@ -1,4 +1,4 @@ -// 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. @@ -15,6 +15,7 @@ // Implementation details of absl/types/variant.h, pulled into a // separate file to avoid cluttering the top of the API header with // implementation details. +// #ifndef ABSL_TYPES_variant_internal_H_ #define ABSL_TYPES_variant_internal_H_ @@ -37,8 +38,10 @@ #include "absl/types/bad_variant_access.h" #include "absl/utility/utility.h" +#if !defined(ABSL_HAVE_STD_VARIANT) + namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { template <class... Types> class variant; @@ -580,12 +583,9 @@ struct VariantCoreAccess { self.index_ = other.index(); } + // Access a variant alternative, assuming the index is correct. template <std::size_t I, class Variant> static VariantAccessResult<I, Variant> Access(Variant&& self) { - if (ABSL_PREDICT_FALSE(self.index_ != I)) { - TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>(); - } - // This cast instead of invocation of AccessUnion with an rvalue is a // workaround for msvc. Without this there is a runtime failure when dealing // with rvalues. @@ -594,6 +594,16 @@ struct VariantCoreAccess { variant_internal::AccessUnion(self.state_, SizeT<I>())); } + // Access a variant alternative, throwing if the index is incorrect. + template <std::size_t I, class Variant> + static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) { + if (ABSL_PREDICT_FALSE(self.index_ != I)) { + TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>(); + } + + return Access<I>(absl::forward<Variant>(self)); + } + // The implementation of the move-assignment operation for a variant. template <class VType> struct MoveAssignVisitor { @@ -902,6 +912,11 @@ struct PerformVisitation { template <std::size_t... TupIs, std::size_t... Is> constexpr ReturnType Run(std::false_type /*has_valueless*/, index_sequence<TupIs...>, SizeT<Is>...) const { + static_assert( + std::is_same<ReturnType, + absl::result_of_t<Op(VariantAccessResult< + Is, QualifiedVariants>...)>>::value, + "All visitation overloads must have the same return type."); return absl::base_internal::Invoke( absl::forward<Op>(op), VariantCoreAccess::Access<Is>( @@ -1056,32 +1071,6 @@ struct OverloadSet<> { static void Overload(...); }; -//////////////////////////////// -// Library Fundamentals V2 TS // -//////////////////////////////// - -// TODO(calabrese): Consider moving this to absl/meta/type_traits.h - -// The following is a rough implementation of parts of the detection idiom. -// It is used for the comparison operator checks. - -template <class Enabler, class To, template <class...> class Op, class... Args> -struct is_detected_convertible_impl { - using type = std::false_type; -}; - -template <class To, template <class...> class Op, class... Args> -struct is_detected_convertible_impl< - absl::enable_if_t<std::is_convertible<Op<Args...>, To>::value>, To, Op, - Args...> { - using type = std::true_type; -}; - -// NOTE: This differs from library fundamentals by being lazy. -template <class To, template <class...> class Op, class... Args> -struct is_detected_convertible - : is_detected_convertible_impl<void, To, Op, Args...>::type {}; - template <class T> using LessThanResult = decltype(std::declval<T>() < std::declval<T>()); @@ -1101,6 +1090,8 @@ using EqualResult = decltype(std::declval<T>() == std::declval<T>()); template <class T> using NotEqualResult = decltype(std::declval<T>() != std::declval<T>()); +using type_traits_internal::is_detected_convertible; + template <class... T> using RequireAllHaveEqualT = absl::enable_if_t< absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value, @@ -1245,23 +1236,29 @@ using VariantCopyBase = absl::conditional_t< // Base that is dependent on whether or not the move-assign can be trivial. template <class... T> using VariantMoveAssignBase = absl::conditional_t< - absl::disjunction<absl::conjunction<std::is_move_assignable<Union<T...>>, - std::is_move_constructible<Union<T...>>, - std::is_destructible<Union<T...>>>, - absl::negation<absl::conjunction< - std::is_move_constructible<T>..., - std::is_move_assignable<T>...>>>::value, + absl::disjunction< + absl::conjunction<absl::is_move_assignable<Union<T...>>, + std::is_move_constructible<Union<T...>>, + std::is_destructible<Union<T...>>>, + absl::negation<absl::conjunction<std::is_move_constructible<T>..., + // Note: We're not qualifying this with + // absl:: because it doesn't compile + // under MSVC. + is_move_assignable<T>...>>>::value, VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>; // Base that is dependent on whether or not the copy-assign can be trivial. template <class... T> using VariantCopyAssignBase = absl::conditional_t< - absl::disjunction<absl::conjunction<std::is_copy_assignable<Union<T...>>, - std::is_copy_constructible<Union<T...>>, - std::is_destructible<Union<T...>>>, - absl::negation<absl::conjunction< - std::is_copy_constructible<T>..., - std::is_copy_assignable<T>...>>>::value, + absl::disjunction< + absl::conjunction<absl::is_copy_assignable<Union<T...>>, + std::is_copy_constructible<Union<T...>>, + std::is_destructible<Union<T...>>>, + absl::negation<absl::conjunction<std::is_copy_constructible<T>..., + // Note: We're not qualifying this with + // absl:: because it doesn't compile + // under MSVC. + is_copy_assignable<T>...>>>::value, VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>; template <class... T> @@ -1628,7 +1625,8 @@ struct VariantHashBase<Variant, }; } // namespace variant_internal -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl +#endif // !defined(ABSL_HAVE_STD_VARIANT) #endif // ABSL_TYPES_variant_internal_H_ diff --git a/absl/types/optional.cc b/absl/types/optional.cc index 85424ee3..5c77f154 100644 --- a/absl/types/optional.cc +++ b/absl/types/optional.cc @@ -16,11 +16,11 @@ #ifndef ABSL_HAVE_STD_OPTIONAL namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { nullopt_t::init_t nullopt_t::init; extern const nullopt_t nullopt{nullopt_t::init}; -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl #endif // ABSL_HAVE_STD_OPTIONAL diff --git a/absl/types/optional.h b/absl/types/optional.h index 12f0664a..1ca8dec6 100644 --- a/absl/types/optional.h +++ b/absl/types/optional.h @@ -43,13 +43,13 @@ #include <optional> namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { using std::bad_optional_access; using std::optional; using std::make_optional; using std::nullopt_t; using std::nullopt; -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl #else // ABSL_HAVE_STD_OPTIONAL @@ -61,6 +61,7 @@ using std::nullopt; #include <type_traits> #include <utility> +#include "absl/base/attributes.h" #include "absl/memory/memory.h" #include "absl/meta/type_traits.h" #include "absl/types/bad_optional_access.h" @@ -94,7 +95,7 @@ using std::nullopt; #endif namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { // ----------------------------------------------------------------------------- // absl::optional @@ -165,7 +166,7 @@ struct empty_struct {}; // This class stores the data in optional<T>. // It is specialized based on whether T is trivially destructible. // This is the specialization for non trivially destructible type. -template <typename T, bool = std::is_trivially_destructible<T>::value> +template <typename T, bool unused = std::is_trivially_destructible<T>::value> class optional_data_dtor_base { struct dummy_type { static_assert(sizeof(T) % sizeof(empty_struct) == 0, ""); @@ -263,10 +264,10 @@ class optional_data_base : public optional_data_dtor_base<T> { // have trivial move but nontrivial copy. // Also, we should be checking is_trivially_copyable here, which is not // supported now, so we use is_trivially_* traits instead. -template <typename T, bool = absl::is_trivially_copy_constructible<T>::value&& - absl::is_trivially_copy_assignable< - typename std::remove_cv<T>::type>::value&& - std::is_trivially_destructible<T>::value> +template <typename T, + bool unused = absl::is_trivially_copy_constructible<T>::value&& + absl::is_trivially_copy_assignable<typename std::remove_cv< + T>::type>::value&& std::is_trivially_destructible<T>::value> class optional_data; // Trivially copyable types @@ -414,10 +415,10 @@ constexpr copy_traits get_ctor_copy_traits() { template <typename T> constexpr copy_traits get_assign_copy_traits() { - return std::is_copy_assignable<T>::value && + return absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value ? copy_traits::copyable - : std::is_move_assignable<T>::value && + : absl::is_move_assignable<T>::value && std::is_move_constructible<T>::value ? copy_traits::movable : copy_traits::non_movable; @@ -703,7 +704,7 @@ class optional : private optional_internal::optional_data<T>, // optional::reset() // // Destroys the inner `T` value of an `absl::optional` if one is present. - void reset() noexcept { this->destruct(); } + ABSL_ATTRIBUTE_REINITIALIZES void reset() noexcept { this->destruct(); } // optional::emplace() // @@ -1125,7 +1126,7 @@ constexpr auto operator>=(const U& v, const optional<T>& x) return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true; } -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl namespace std { diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc index e136d0a0..313891f7 100644 --- a/absl/types/optional_exception_safety_test.cc +++ b/absl/types/optional_exception_safety_test.cc @@ -18,7 +18,7 @@ #include "absl/base/internal/exception_safety_testing.h" namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { namespace { @@ -39,12 +39,12 @@ constexpr int kUpdatedInteger = 10; template <typename OptionalT> bool ValueThrowsBadOptionalAccess(const OptionalT& optional) try { return (static_cast<void>(optional.value()), false); -} catch (absl::bad_optional_access) { +} catch (const absl::bad_optional_access&) { return true; } template <typename OptionalT> -AssertionResult CheckInvariants(OptionalT* optional_ptr) { +AssertionResult OptionalInvariants(OptionalT* optional_ptr) { // Check the current state post-throw for validity auto& optional = *optional_ptr; @@ -124,8 +124,8 @@ TEST(OptionalExceptionSafety, NothrowConstructors) { TEST(OptionalExceptionSafety, Emplace) { // Test the basic guarantee plus test the result of optional::has_value() // is false in all cases - auto disengaged_test = MakeExceptionSafetyTester().WithInvariants( - CheckInvariants<Optional>, CheckDisengaged<Optional>); + auto disengaged_test = MakeExceptionSafetyTester().WithContracts( + OptionalInvariants<Optional>, CheckDisengaged<Optional>); auto disengaged_test_empty = disengaged_test.WithInitialValue(Optional()); auto disengaged_test_nonempty = disengaged_test.WithInitialValue(Optional(kInitialInteger)); @@ -148,11 +148,11 @@ TEST(OptionalExceptionSafety, EverythingThrowsSwap) { // Test the basic guarantee plus test the result of optional::has_value() // remains the same auto test = - MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>); + MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithInvariants(CheckDisengaged<Optional>); + .WithContracts(CheckDisengaged<Optional>); auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithInvariants(CheckEngaged<Optional>); + .WithContracts(CheckEngaged<Optional>); auto swap_empty = [](Optional* optional_ptr) { auto empty = Optional(); @@ -193,11 +193,11 @@ TEST(OptionalExceptionSafety, CopyAssign) { // Test the basic guarantee plus test the result of optional::has_value() // remains the same auto test = - MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>); + MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithInvariants(CheckDisengaged<Optional>); + .WithContracts(CheckDisengaged<Optional>); auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithInvariants(CheckEngaged<Optional>); + .WithContracts(CheckEngaged<Optional>); auto copyassign_nonempty = [](Optional* optional_ptr) { auto nonempty = @@ -219,11 +219,11 @@ TEST(OptionalExceptionSafety, MoveAssign) { // Test the basic guarantee plus test the result of optional::has_value() // remains the same auto test = - MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>); + MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithInvariants(CheckDisengaged<Optional>); + .WithContracts(CheckDisengaged<Optional>); auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithInvariants(CheckEngaged<Optional>); + .WithContracts(CheckEngaged<Optional>); auto moveassign_empty = [](Optional* optional_ptr) { auto empty = Optional(); @@ -280,5 +280,5 @@ TEST(OptionalExceptionSafety, NothrowMoveAssign) { } // namespace -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc index 179bfd66..fc4f00a4 100644 --- a/absl/types/optional_test.cc +++ b/absl/types/optional_test.cc @@ -607,11 +607,12 @@ TEST(optionalTest, CopyAssignment) { opt2_to_empty = empty; EXPECT_FALSE(opt2_to_empty); - EXPECT_FALSE(std::is_copy_assignable<absl::optional<const int>>::value); - EXPECT_TRUE(std::is_copy_assignable<absl::optional<Copyable>>::value); - EXPECT_FALSE(std::is_copy_assignable<absl::optional<MoveableThrow>>::value); - EXPECT_FALSE(std::is_copy_assignable<absl::optional<MoveableNoThrow>>::value); - EXPECT_FALSE(std::is_copy_assignable<absl::optional<NonMovable>>::value); + EXPECT_FALSE(absl::is_copy_assignable<absl::optional<const int>>::value); + EXPECT_TRUE(absl::is_copy_assignable<absl::optional<Copyable>>::value); + EXPECT_FALSE(absl::is_copy_assignable<absl::optional<MoveableThrow>>::value); + EXPECT_FALSE( + absl::is_copy_assignable<absl::optional<MoveableNoThrow>>::value); + EXPECT_FALSE(absl::is_copy_assignable<absl::optional<NonMovable>>::value); EXPECT_TRUE(absl::is_trivially_copy_assignable<int>::value); EXPECT_TRUE(absl::is_trivially_copy_assignable<volatile int>::value); @@ -625,9 +626,9 @@ TEST(optionalTest, CopyAssignment) { }; EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial>::value); - EXPECT_FALSE(std::is_copy_assignable<const Trivial>::value); - EXPECT_FALSE(std::is_copy_assignable<volatile Trivial>::value); - EXPECT_TRUE(std::is_copy_assignable<NonTrivial>::value); + EXPECT_FALSE(absl::is_copy_assignable<const Trivial>::value); + EXPECT_FALSE(absl::is_copy_assignable<volatile Trivial>::value); + EXPECT_TRUE(absl::is_copy_assignable<NonTrivial>::value); EXPECT_FALSE(absl::is_trivially_copy_assignable<NonTrivial>::value); // std::optional doesn't support volatile nontrivial types. @@ -695,11 +696,11 @@ TEST(optionalTest, MoveAssignment) { EXPECT_EQ(1, listener.volatile_move_assign); } #endif // ABSL_HAVE_STD_OPTIONAL - EXPECT_FALSE(std::is_move_assignable<absl::optional<const int>>::value); - EXPECT_TRUE(std::is_move_assignable<absl::optional<Copyable>>::value); - EXPECT_TRUE(std::is_move_assignable<absl::optional<MoveableThrow>>::value); - EXPECT_TRUE(std::is_move_assignable<absl::optional<MoveableNoThrow>>::value); - EXPECT_FALSE(std::is_move_assignable<absl::optional<NonMovable>>::value); + EXPECT_FALSE(absl::is_move_assignable<absl::optional<const int>>::value); + EXPECT_TRUE(absl::is_move_assignable<absl::optional<Copyable>>::value); + EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableThrow>>::value); + EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableNoThrow>>::value); + EXPECT_FALSE(absl::is_move_assignable<absl::optional<NonMovable>>::value); EXPECT_FALSE( std::is_nothrow_move_assignable<absl::optional<MoveableThrow>>::value); @@ -1041,9 +1042,9 @@ TEST(optionalTest, Value) { // test exception throw on value() absl::optional<int> empty; #ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(empty.value(), absl::bad_optional_access); + EXPECT_THROW((void)empty.value(), absl::bad_optional_access); #else - EXPECT_DEATH(empty.value(), "Bad optional access"); + EXPECT_DEATH((void)empty.value(), "Bad optional access"); #endif // test constexpr value() @@ -1619,7 +1620,7 @@ TEST(optionalTest, AssignmentConstraints) { EXPECT_TRUE( (std::is_assignable<absl::optional<AnyLike>&, const AnyLike&>::value)); EXPECT_TRUE(std::is_move_assignable<absl::optional<AnyLike>>::value); - EXPECT_TRUE(std::is_copy_assignable<absl::optional<AnyLike>>::value); + EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value); } } // namespace diff --git a/absl/types/span.h b/absl/types/span.h index 1b5edf25..99b6765b 100644 --- a/absl/types/span.h +++ b/absl/types/span.h @@ -72,7 +72,7 @@ #include "absl/meta/type_traits.h" namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { template <typename T> class Span; @@ -88,7 +88,7 @@ constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references) return c.data(); } -// Before C++17, std::string::data returns a const char* in all cases. +// Before C++17, string::data returns a const char* in all cases. inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references) int) noexcept { return &s[0]; @@ -380,64 +380,70 @@ class Span { // // Returns a reference to the i'th element of this span. constexpr reference at(size_type i) const { - return ABSL_PREDICT_TRUE(i < size()) - ? ptr_[i] + return ABSL_PREDICT_TRUE(i < size()) // + ? *(data() + i) : (base_internal::ThrowStdOutOfRange( "Span::at failed bounds check"), - ptr_[i]); + *(data() + i)); } // Span::front() // // Returns a reference to the first element of this span. - reference front() const noexcept { return ABSL_ASSERT(size() > 0), ptr_[0]; } + constexpr reference front() const noexcept { + return ABSL_ASSERT(size() > 0), *data(); + } // Span::back() // // Returns a reference to the last element of this span. - reference back() const noexcept { - return ABSL_ASSERT(size() > 0), ptr_[size() - 1]; + constexpr reference back() const noexcept { + return ABSL_ASSERT(size() > 0), *(data() + size() - 1); } // Span::begin() // // Returns an iterator to the first element of this span. - constexpr iterator begin() const noexcept { return ptr_; } + constexpr iterator begin() const noexcept { return data(); } // Span::cbegin() // // Returns a const iterator to the first element of this span. - constexpr const_iterator cbegin() const noexcept { return ptr_; } + constexpr const_iterator cbegin() const noexcept { return begin(); } // Span::end() // // Returns an iterator to the last element of this span. - iterator end() const noexcept { return ptr_ + len_; } + constexpr iterator end() const noexcept { return data() + size(); } // Span::cend() // // Returns a const iterator to the last element of this span. - const_iterator cend() const noexcept { return end(); } + constexpr const_iterator cend() const noexcept { return end(); } // Span::rbegin() // // Returns a reverse iterator starting at the last element of this span. - reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } + constexpr reverse_iterator rbegin() const noexcept { + return reverse_iterator(end()); + } // Span::crbegin() // // Returns a reverse const iterator starting at the last element of this span. - const_reverse_iterator crbegin() const noexcept { return rbegin(); } + constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } // Span::rend() // // Returns a reverse iterator starting at the first element of this span. - reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } + constexpr reverse_iterator rend() const noexcept { + return reverse_iterator(begin()); + } // Span::crend() // // Returns a reverse iterator starting at the first element of this span. - const_reverse_iterator crend() const noexcept { return rend(); } + constexpr const_reverse_iterator crend() const noexcept { return rend(); } // Span mutations @@ -445,7 +451,7 @@ class Span { // // Removes the first `n` elements from the span. void remove_prefix(size_type n) noexcept { - assert(len_ >= n); + assert(size() >= n); ptr_ += n; len_ -= n; } @@ -454,7 +460,7 @@ class Span { // // Removes the last `n` elements from the span. void remove_suffix(size_type n) noexcept { - assert(len_ >= n); + assert(size() >= n); len_ -= n; } @@ -475,11 +481,18 @@ class Span { // absl::MakeSpan(vec).subspan(4); // {} // absl::MakeSpan(vec).subspan(5); // throws std::out_of_range constexpr Span subspan(size_type pos = 0, size_type len = npos) const { - return (pos <= len_) - ? Span(ptr_ + pos, span_internal::Min(len_ - pos, len)) + return (pos <= size()) + ? Span(data() + pos, span_internal::Min(size() - pos, len)) : (base_internal::ThrowStdOutOfRange("pos > size()"), Span()); } + // Support for absl::Hash. + template <typename H> + friend H AbslHashValue(H h, Span v) { + return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()), + v.size()); + } + private: pointer ptr_; size_type len_; @@ -746,6 +759,6 @@ template <int&... ExplicitArgumentBarrier, typename T, size_t N> constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept { return Span<const T>(array, N); } -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl #endif // ABSL_TYPES_SPAN_H_ diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc index 5a4f0014..bd739ff2 100644 --- a/absl/types/span_test.cc +++ b/absl/types/span_test.cc @@ -29,6 +29,7 @@ #include "absl/base/internal/exception_testing.h" #include "absl/container/fixed_array.h" #include "absl/container/inlined_vector.h" +#include "absl/hash/hash_testing.h" #include "absl/strings/str_cat.h" namespace { @@ -288,7 +289,7 @@ TEST(IntSpan, Subspan) { #ifdef ABSL_HAVE_EXCEPTIONS EXPECT_THROW(absl::MakeSpan(ramp).subspan(11, 5), std::out_of_range); #else - EXPECT_DEATH(absl::MakeSpan(ramp).subspan(11, 5), ""); + EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).subspan(11, 5), ""); #endif } diff --git a/absl/types/variant.h b/absl/types/variant.h index b0898d98..4ae4e00d 100644 --- a/absl/types/variant.h +++ b/absl/types/variant.h @@ -50,7 +50,7 @@ #include <variant> namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { using std::bad_variant_access; using std::get; using std::get_if; @@ -63,7 +63,7 @@ using std::variant_npos; using std::variant_size; using std::variant_size_v; using std::visit; -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl #else // ABSL_HAVE_STD_VARIANT @@ -79,13 +79,13 @@ using std::visit; #include "absl/types/internal/variant.h" namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { // ----------------------------------------------------------------------------- // absl::variant // ----------------------------------------------------------------------------- // -// An 'absl::variant` type is a form of type-safe union. An `absl::variant` -- +// An `absl::variant` type is a form of type-safe union. An `absl::variant` -- // except in exceptional cases -- always holds a value of one of its alternative // types. // @@ -139,7 +139,7 @@ void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) { // variant_size // -// Returns the number of alterative types available for a given `absl::variant` +// Returns the number of alternative types available for a given `absl::variant` // type as a compile-time constant expression. As this is a class template, it // is not generally useful for accessing the number of alternative types of // any given `absl::variant` instance. @@ -251,7 +251,7 @@ using variant_alternative_t = typename variant_alternative<I, T>::type; // // Example: // -// absl::variant<int, std::string> bar = 42; +// absl::variant<int, std::string> foo = 42; // if (absl::holds_alternative<int>(foo)) { // std::cout << "The variant holds an integer"; // } @@ -293,7 +293,7 @@ constexpr bool holds_alternative(const variant<Types...>& v) noexcept { // Overload for getting a variant's lvalue by type. template <class T, class... Types> constexpr T& get(variant<Types...>& v) { // NOLINT - return variant_internal::VariantCoreAccess::Access< + return variant_internal::VariantCoreAccess::CheckedAccess< variant_internal::IndexOf<T, Types...>::value>(v); } @@ -301,14 +301,14 @@ constexpr T& get(variant<Types...>& v) { // NOLINT // Note: `absl::move()` is required to allow use of constexpr in C++11. template <class T, class... Types> constexpr T&& get(variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::Access< + return variant_internal::VariantCoreAccess::CheckedAccess< variant_internal::IndexOf<T, Types...>::value>(absl::move(v)); } // Overload for getting a variant's const lvalue by type. template <class T, class... Types> constexpr const T& get(const variant<Types...>& v) { - return variant_internal::VariantCoreAccess::Access< + return variant_internal::VariantCoreAccess::CheckedAccess< variant_internal::IndexOf<T, Types...>::value>(v); } @@ -316,7 +316,7 @@ constexpr const T& get(const variant<Types...>& v) { // Note: `absl::move()` is required to allow use of constexpr in C++11. template <class T, class... Types> constexpr const T&& get(const variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::Access< + return variant_internal::VariantCoreAccess::CheckedAccess< variant_internal::IndexOf<T, Types...>::value>(absl::move(v)); } @@ -324,7 +324,7 @@ constexpr const T&& get(const variant<Types...>&& v) { template <std::size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get( variant<Types...>& v) { // NOLINT - return variant_internal::VariantCoreAccess::Access<I>(v); + return variant_internal::VariantCoreAccess::CheckedAccess<I>(v); } // Overload for getting a variant's rvalue by index. @@ -332,14 +332,14 @@ constexpr variant_alternative_t<I, variant<Types...>>& get( template <std::size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get( variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::Access<I>(absl::move(v)); + return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v)); } // Overload for getting a variant's const lvalue by index. template <std::size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get( const variant<Types...>& v) { - return variant_internal::VariantCoreAccess::Access<I>(v); + return variant_internal::VariantCoreAccess::CheckedAccess<I>(v); } // Overload for getting a variant's const rvalue by index. @@ -347,7 +347,7 @@ constexpr const variant_alternative_t<I, variant<Types...>>& get( template <std::size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get( const variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::Access<I>(absl::move(v)); + return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v)); } // get_if() @@ -365,8 +365,10 @@ constexpr const variant_alternative_t<I, variant<Types...>>&& get( template <std::size_t I, class... Types> constexpr absl::add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>* v) noexcept { - return (v != nullptr && v->index() == I) ? std::addressof(absl::get<I>(*v)) - : nullptr; + return (v != nullptr && v->index() == I) + ? std::addressof( + variant_internal::VariantCoreAccess::Access<I>(*v)) + : nullptr; } // Overload for getting a pointer to the const value stored in the given @@ -374,8 +376,10 @@ get_if(variant<Types...>* v) noexcept { template <std::size_t I, class... Types> constexpr absl::add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>* v) noexcept { - return (v != nullptr && v->index() == I) ? std::addressof(absl::get<I>(*v)) - : nullptr; + return (v != nullptr && v->index() == I) + ? std::addressof( + variant_internal::VariantCoreAccess::Access<I>(*v)) + : nullptr; } // Overload for getting a pointer to the value stored in the given variant by @@ -398,9 +402,9 @@ constexpr absl::add_pointer_t<const T> get_if( // Calls a provided functor on a given set of variants. `absl::visit()` is // commonly used to conditionally inspect the state of a given variant (or set // of variants). -// Requires: The expression in the Effects: element shall be a valid expression -// of the same type and value category, for all combinations of alternative -// types of all variants. Otherwise, the program is ill-formed. +// +// The functor must return the same type when called with any of the variants' +// alternatives. // // Example: // @@ -413,9 +417,10 @@ constexpr absl::add_pointer_t<const T> get_if( // }; // // // Declare our variant, and call `absl::visit()` on it. -// std::variant<int, std::string> foo = std::string("foo"); +// // Note that `GetVariant()` returns void in either case. +// absl::variant<int, std::string> foo = std::string("foo"); // GetVariant visitor; -// std::visit(visitor, foo); // Prints `The variant's value is: foo' +// absl::visit(visitor, foo); // Prints `The variant's value is: foo' template <typename Visitor, typename... Variants> variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis, Variants&&... vars) { @@ -448,14 +453,19 @@ constexpr bool operator!=(monostate, monostate) noexcept { return false; } //------------------------------------------------------------------------------ template <typename T0, typename... Tn> class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> { - // Intentionally not qualifing `negation` with `absl::` to work around a bug + static_assert(absl::conjunction<std::is_object<T0>, + std::is_object<Tn>...>::value, + "Attempted to instantiate a variant containing a non-object " + "type."); + // Intentionally not qualifying `negation` with `absl::` to work around a bug // in MSVC 2015 with inline namespace and variadic template. - static_assert(absl::conjunction<std::is_object<T0>, std::is_object<Tn>..., - negation<std::is_array<T0> >, - negation<std::is_array<Tn> >..., - std::is_nothrow_destructible<T0>, + static_assert(absl::conjunction<negation<std::is_array<T0> >, + negation<std::is_array<Tn> >...>::value, + "Attempted to instantiate a variant containing an array type."); + static_assert(absl::conjunction<std::is_nothrow_destructible<T0>, std::is_nothrow_destructible<Tn>...>::value, - "Attempted to instantiate a variant with an unsupported type."); + "Attempted to instantiate a variant containing a non-nothrow " + "destructible type."); friend struct variant_internal::VariantCoreAccess; @@ -555,7 +565,7 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> { // Assignment Operators - // Copy assignement operator + // Copy assignment operator variant& operator=(const variant& other) = default; // Move assignment operator @@ -783,7 +793,7 @@ operator>=(const variant<Types...>& a, const variant<Types...>& b) { a.index()); } -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl namespace std { @@ -804,7 +814,7 @@ struct hash<absl::variant<T...>> #endif // ABSL_HAVE_STD_VARIANT namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { namespace variant_internal { // Helper visitor for converting a variant<Ts...>` into another type (mostly @@ -840,7 +850,7 @@ To ConvertVariantTo(Variant&& variant) { std::forward<Variant>(variant)); } -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl #endif // ABSL_TYPES_VARIANT_H_ diff --git a/absl/types/variant_benchmark.cc b/absl/types/variant_benchmark.cc index 93acc2b6..854f1448 100644 --- a/absl/types/variant_benchmark.cc +++ b/absl/types/variant_benchmark.cc @@ -28,7 +28,7 @@ #include "absl/utility/utility.h" namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { namespace { template <std::size_t I> @@ -218,5 +218,5 @@ BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2) ->DenseRange(0, integral_pow(4, 2) - 1); } // namespace -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc index d7bc90d2..ff166051 100644 --- a/absl/types/variant_exception_safety_test.cc +++ b/absl/types/variant_exception_safety_test.cc @@ -11,6 +11,7 @@ // 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/variant.h" #include <iostream> @@ -20,11 +21,14 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/base/config.h" #include "absl/base/internal/exception_safety_testing.h" #include "absl/memory/memory.h" +// See comment in absl/base/config.h +#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { namespace { using ::testing::MakeExceptionSafetyTester; @@ -54,13 +58,13 @@ void ToValuelessByException(ThrowingVariant& v) { // NOLINT try { v.emplace<Thrower>(); v.emplace<Thrower>(ExceptionOnConversion<Thrower>()); - } catch (ConversionException& /*e*/) { + } catch (const ConversionException&) { // This space intentionally left blank. } } // Check that variant is still in a usable state after an exception is thrown. -testing::AssertionResult CheckInvariants(ThrowingVariant* v) { +testing::AssertionResult VariantInvariants(ThrowingVariant* v) { using testing::AssertionFailure; using testing::AssertionSuccess; @@ -101,7 +105,7 @@ testing::AssertionResult CheckInvariants(ThrowingVariant* v) { auto unused = absl::get<Thrower>(*v); static_cast<void>(unused); return AssertionFailure() << "Variant should not contain Thrower"; - } catch (absl::bad_variant_access) { + } catch (const absl::bad_variant_access&) { } catch (...) { return AssertionFailure() << "Unexpected exception throw from absl::get"; } @@ -214,8 +218,8 @@ TEST(VariantExceptionSafetyTest, CopyAssign) { MakeExceptionSafetyTester() .WithInitialValue(WithThrower()) .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(tester.WithInvariants(CheckInvariants).Test()); - EXPECT_FALSE(tester.WithInvariants(strong_guarantee).Test()); + EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test()); + EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); } { const ThrowingVariant rhs(ExpectedThrowerVec()); @@ -223,8 +227,8 @@ TEST(VariantExceptionSafetyTest, CopyAssign) { MakeExceptionSafetyTester() .WithInitialValue(WithThrowerVec()) .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(tester.WithInvariants(CheckInvariants).Test()); - EXPECT_FALSE(tester.WithInvariants(strong_guarantee).Test()); + EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test()); + EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); } // libstdc++ std::variant has bugs on copy assignment regarding exception // safety. @@ -252,12 +256,12 @@ TEST(VariantExceptionSafetyTest, CopyAssign) { .WithInitialValue(WithCopyNoThrow()) .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); EXPECT_TRUE(tester - .WithInvariants(CheckInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) + .WithContracts(VariantInvariants, + [](ThrowingVariant* lhs) { + return lhs->valueless_by_exception(); + }) .Test()); - EXPECT_FALSE(tester.WithInvariants(strong_guarantee).Test()); + EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); } #endif // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__)) { @@ -269,7 +273,7 @@ TEST(VariantExceptionSafetyTest, CopyAssign) { const ThrowingVariant rhs(MoveNothrow{}); EXPECT_TRUE(MakeExceptionSafetyTester() .WithInitialValue(WithThrower()) - .WithInvariants(CheckInvariants, strong_guarantee) + .WithContracts(VariantInvariants, strong_guarantee) .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; })); } } @@ -305,11 +309,11 @@ TEST(VariantExceptionSafetyTest, MoveAssign) { *lhs = std::move(copy); }); EXPECT_TRUE(tester - .WithInvariants( - CheckInvariants, + .WithContracts( + VariantInvariants, [&](ThrowingVariant* lhs) { return lhs->index() == j; }) .Test()); - EXPECT_FALSE(tester.WithInvariants(strong_guarantee).Test()); + EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); } { // - otherwise (index() != j), equivalent to @@ -319,10 +323,10 @@ TEST(VariantExceptionSafetyTest, MoveAssign) { ThrowingVariant rhs(CopyNothrow{}); EXPECT_TRUE(MakeExceptionSafetyTester() .WithInitialValue(WithThrower()) - .WithInvariants(CheckInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) + .WithContracts(VariantInvariants, + [](ThrowingVariant* lhs) { + return lhs->valueless_by_exception(); + }) .Test([&](ThrowingVariant* lhs) { auto copy = rhs; *lhs = std::move(copy); @@ -348,12 +352,12 @@ TEST(VariantExceptionSafetyTest, ValueAssign) { .WithInitialValue(WithThrower()) .WithOperation([rhs](ThrowingVariant* lhs) { *lhs = rhs; }); EXPECT_TRUE(copy_tester - .WithInvariants(CheckInvariants, - [](ThrowingVariant* lhs) { - return !lhs->valueless_by_exception(); - }) + .WithContracts(VariantInvariants, + [](ThrowingVariant* lhs) { + return !lhs->valueless_by_exception(); + }) .Test()); - EXPECT_FALSE(copy_tester.WithInvariants(strong_guarantee).Test()); + EXPECT_FALSE(copy_tester.WithContracts(strong_guarantee).Test()); // move assign auto move_tester = MakeExceptionSafetyTester() .WithInitialValue(WithThrower()) @@ -362,13 +366,13 @@ TEST(VariantExceptionSafetyTest, ValueAssign) { *lhs = std::move(copy); }); EXPECT_TRUE(move_tester - .WithInvariants(CheckInvariants, - [](ThrowingVariant* lhs) { - return !lhs->valueless_by_exception(); - }) + .WithContracts(VariantInvariants, + [](ThrowingVariant* lhs) { + return !lhs->valueless_by_exception(); + }) .Test()); - EXPECT_FALSE(move_tester.WithInvariants(strong_guarantee).Test()); + EXPECT_FALSE(move_tester.WithContracts(strong_guarantee).Test()); } // Otherwise (*this holds something else), if is_nothrow_constructible_v<Tj, // T> || !is_nothrow_move_constructible_v<Tj> is true, equivalent to @@ -401,12 +405,12 @@ TEST(VariantExceptionSafetyTest, ValueAssign) { .WithInitialValue(WithCopyNoThrow()) .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); EXPECT_TRUE(copy_tester - .WithInvariants(CheckInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) + .WithContracts(VariantInvariants, + [](ThrowingVariant* lhs) { + return lhs->valueless_by_exception(); + }) .Test()); - EXPECT_FALSE(copy_tester.WithInvariants(strong_guarantee).Test()); + EXPECT_FALSE(copy_tester.WithContracts(strong_guarantee).Test()); // move auto move_tester = MakeExceptionSafetyTester() .WithInitialValue(WithCopyNoThrow()) @@ -414,12 +418,12 @@ TEST(VariantExceptionSafetyTest, ValueAssign) { *lhs = ExpectedThrower(testing::nothrow_ctor); }); EXPECT_TRUE(move_tester - .WithInvariants(CheckInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) + .WithContracts(VariantInvariants, + [](ThrowingVariant* lhs) { + return lhs->valueless_by_exception(); + }) .Test()); - EXPECT_FALSE(move_tester.WithInvariants(strong_guarantee).Test()); + EXPECT_FALSE(move_tester.WithContracts(strong_guarantee).Test()); } // Otherwise (if is_nothrow_constructible_v<Tj, T> == false && // is_nothrow_move_constructible<Tj> == true), @@ -433,7 +437,7 @@ TEST(VariantExceptionSafetyTest, ValueAssign) { MoveNothrow rhs; EXPECT_TRUE(MakeExceptionSafetyTester() .WithInitialValue(WithThrower()) - .WithInvariants(CheckInvariants, strong_guarantee) + .WithContracts(VariantInvariants, strong_guarantee) .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; })); } #endif // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__)) @@ -451,12 +455,12 @@ TEST(VariantExceptionSafetyTest, Emplace) { v->emplace<Thrower>(args); }); EXPECT_TRUE(tester - .WithInvariants(CheckInvariants, - [](ThrowingVariant* v) { - return v->valueless_by_exception(); - }) + .WithContracts(VariantInvariants, + [](ThrowingVariant* v) { + return v->valueless_by_exception(); + }) .Test()); - EXPECT_FALSE(tester.WithInvariants(strong_guarantee).Test()); + EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); } } @@ -473,7 +477,7 @@ TEST(VariantExceptionSafetyTest, Swap) { ThrowingVariant rhs = ExpectedThrower(); EXPECT_TRUE(MakeExceptionSafetyTester() .WithInitialValue(WithThrower()) - .WithInvariants(CheckInvariants) + .WithContracts(VariantInvariants) .Test([&](ThrowingVariant* lhs) { auto copy = rhs; lhs->swap(copy); @@ -487,7 +491,7 @@ TEST(VariantExceptionSafetyTest, Swap) { ThrowingVariant rhs = ExpectedThrower(); EXPECT_TRUE(MakeExceptionSafetyTester() .WithInitialValue(WithCopyNoThrow()) - .WithInvariants(CheckInvariants) + .WithContracts(VariantInvariants) .Test([&](ThrowingVariant* lhs) { auto copy = rhs; lhs->swap(copy); @@ -497,7 +501,7 @@ TEST(VariantExceptionSafetyTest, Swap) { ThrowingVariant rhs = ExpectedThrower(); EXPECT_TRUE(MakeExceptionSafetyTester() .WithInitialValue(WithCopyNoThrow()) - .WithInvariants(CheckInvariants) + .WithContracts(VariantInvariants) .Test([&](ThrowingVariant* lhs) { auto copy = rhs; copy.swap(*lhs); @@ -506,5 +510,7 @@ TEST(VariantExceptionSafetyTest, Swap) { } } // namespace -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl + +#endif // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index 295023ae..59223ea7 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -52,7 +52,7 @@ #endif // ABSL_HAVE_EXCEPTIONS #define ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(...) \ - ABSL_VARIANT_TEST_EXPECT_FAIL((__VA_ARGS__), absl::bad_variant_access, \ + ABSL_VARIANT_TEST_EXPECT_FAIL((void)(__VA_ARGS__), absl::bad_variant_access, \ "Bad variant access") struct Hashable {}; @@ -67,7 +67,7 @@ struct hash<Hashable> { struct NonHashable {}; namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { namespace { using ::testing::DoubleEq; @@ -404,7 +404,7 @@ struct is_trivially_move_constructible template <class T> struct is_trivially_move_assignable - : std::is_move_assignable<SingleUnion<T>>::type {}; + : absl::is_move_assignable<SingleUnion<T>>::type {}; TEST(VariantTest, NothrowMoveConstructible) { // Verify that variant is nothrow move constructible iff its template @@ -560,9 +560,14 @@ TEST(VariantTest, TestDtor) { } #ifdef ABSL_HAVE_EXCEPTIONS - +// See comment in absl/base/config.h +#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) +TEST(VariantTest, DISABLED_TestDtorValuelessByException) +#else // Test destruction when in the valueless_by_exception state. -TEST(VariantTest, TestDtorValuelessByException) { +TEST(VariantTest, TestDtorValuelessByException) +#endif +{ int counter = 0; IncrementInDtor counter_adjuster(&counter); @@ -2440,14 +2445,14 @@ TEST(VariantTest, TestMoveConversionViaConvertVariantTo) { TEST(VariantTest, TestCopyAndMoveTypeTraits) { EXPECT_TRUE(std::is_copy_constructible<variant<std::string>>::value); - EXPECT_TRUE(std::is_copy_assignable<variant<std::string>>::value); + EXPECT_TRUE(absl::is_copy_assignable<variant<std::string>>::value); EXPECT_TRUE(std::is_move_constructible<variant<std::string>>::value); - EXPECT_TRUE(std::is_move_assignable<variant<std::string>>::value); + EXPECT_TRUE(absl::is_move_assignable<variant<std::string>>::value); EXPECT_TRUE(std::is_move_constructible<variant<std::unique_ptr<int>>>::value); - EXPECT_TRUE(std::is_move_assignable<variant<std::unique_ptr<int>>>::value); + EXPECT_TRUE(absl::is_move_assignable<variant<std::unique_ptr<int>>>::value); EXPECT_FALSE( std::is_copy_constructible<variant<std::unique_ptr<int>>>::value); - EXPECT_FALSE(std::is_copy_assignable<variant<std::unique_ptr<int>>>::value); + EXPECT_FALSE(absl::is_copy_assignable<variant<std::unique_ptr<int>>>::value); EXPECT_FALSE( absl::is_trivially_copy_constructible<variant<std::string>>::value); @@ -2610,5 +2615,5 @@ TEST(VariantTest, MoveCtorBug) { } } // namespace -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl |