Remove the implementation of `absl::any`, which was only needed prior to C++17. `absl::any` is now an alias for `std::any`. It is recommended that clients simply use `std::any`. PiperOrigin-RevId: 729541787 Change-Id: I4a677704bca31d4c602b73ac2dc12cac1fe18793
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index 48900c2..ae62229 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake
@@ -429,8 +429,6 @@ "time/internal/cctz/src/tzfile.h" "time/internal/cctz/src/zone_info_source.cc" "types/any.h" - "types/bad_any_cast.cc" - "types/bad_any_cast.h" "types/bad_optional_access.cc" "types/bad_optional_access.h" "types/bad_variant_access.cc" @@ -492,8 +490,6 @@ "any" "any_invocable" "atomic_hook" - "bad_any_cast" - "bad_any_cast_impl" "bad_optional_access" "bad_variant_access" "base"
diff --git a/absl/base/config.h b/absl/base/config.h index 5256d5b..f5cd03a 100644 --- a/absl/base/config.h +++ b/absl/base/config.h
@@ -519,18 +519,9 @@ #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0 #endif -// ABSL_HAVE_STD_ANY -// -// Checks whether C++17 std::any is available. -#ifdef ABSL_HAVE_STD_ANY -#error "ABSL_HAVE_STD_ANY cannot be directly set." -#elif defined(__cpp_lib_any) && __cpp_lib_any >= 201606L +// ABSL_HAVE_STD_ANY/ABSL_USES_STD_ANY #define ABSL_HAVE_STD_ANY 1 -#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ - ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \ - !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE -#define ABSL_HAVE_STD_ANY 1 -#endif +#define ABSL_USES_STD_ANY 1 // ABSL_HAVE_STD_OPTIONAL // @@ -586,21 +577,6 @@ #define ABSL_HAVE_STD_ORDERING 1 #endif -// ABSL_USES_STD_ANY -// -// Indicates whether absl::any is an alias for std::any. -#if !defined(ABSL_OPTION_USE_STD_ANY) -#error options.h is misconfigured. -#elif ABSL_OPTION_USE_STD_ANY == 0 || \ - (ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY)) -#undef ABSL_USES_STD_ANY -#elif ABSL_OPTION_USE_STD_ANY == 1 || \ - (ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY)) -#define ABSL_USES_STD_ANY 1 -#else -#error options.h is misconfigured. -#endif - // ABSL_USES_STD_OPTIONAL // // Indicates whether absl::optional is an alias for std::optional.
diff --git a/absl/base/options.h b/absl/base/options.h index 4b70446..582c4fd 100644 --- a/absl/base/options.h +++ b/absl/base/options.h
@@ -64,38 +64,14 @@ // proper Abseil implementation at compile-time, which will not be sufficient // to guarantee ABI stability to package managers. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #ifndef ABSL_BASE_OPTIONS_H_ #define ABSL_BASE_OPTIONS_H_ // ----------------------------------------------------------------------------- // Type Compatibility Options // ----------------------------------------------------------------------------- -// -// ABSL_OPTION_USE_STD_ANY -// -// This option controls whether absl::any is implemented as an alias to -// std::any, or as an independent implementation. -// -// A value of 0 means to use Abseil's implementation. This requires only C++11 -// support, and is expected to work on every toolchain we support. -// -// A value of 1 means to use an alias to std::any. This requires that all code -// using Abseil is built in C++17 mode or later. -// -// A value of 2 means to detect the C++ version being used to compile Abseil, -// and use an alias only if a working std::any is available. This option is -// useful when you are building your entire program, including all of its -// dependencies, from source. It should not be used otherwise -- for example, -// if you are distributing Abseil in a binary package manager -- since in -// mode 2, absl::any will name a different type, with a different mangled name -// and binary layout, depending on the compiler flags passed by the end user. -// For more info, see https://abseil.io/about/design/dropin-types. -// -// User code should not inspect this macro. To check in the preprocessor if -// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY. - -#define ABSL_OPTION_USE_STD_ANY 2 - // ABSL_OPTION_USE_STD_OPTIONAL //
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index 532afa6..564d69a 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel
@@ -37,72 +37,15 @@ copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ - ":bad_any_cast", "//absl/base:config", "//absl/base:core_headers", - "//absl/base:fast_type_id", - "//absl/meta:type_traits", "//absl/utility", ], ) cc_library( name = "bad_any_cast", - hdrs = ["bad_any_cast.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bad_any_cast_impl", - "//absl/base:config", - ], -) - -cc_library( - name = "bad_any_cast_impl", - srcs = [ - "bad_any_cast.cc", - "bad_any_cast.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = ["//visibility:private"], - deps = [ - "//absl/base:config", - "//absl/base:raw_logging_internal", - ], -) - -cc_test( - name = "any_test", - size = "small", - srcs = [ - "any_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":any", - "//absl/base:config", - "//absl/base:exception_testing", - "//absl/container:test_instance_tracker", - "//absl/log", - "@googletest//:gtest", - "@googletest//:gtest_main", - ], -) - -cc_test( - name = "any_exception_safety_test", - srcs = ["any_exception_safety_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":any", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "@googletest//:gtest", - "@googletest//:gtest_main", - ], + deprecation = "bad_any_cast dependency is empty can be removed", ) cc_library(
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt index 400b49a..3c1f19e 100644 --- a/absl/types/CMakeLists.txt +++ b/absl/types/CMakeLists.txt
@@ -21,90 +21,14 @@ COPTS ${ABSL_DEFAULT_COPTS} DEPS - absl::bad_any_cast absl::config absl::core_headers - absl::fast_type_id - absl::type_traits absl::utility PUBLIC ) absl_cc_library( NAME - bad_any_cast - HDRS - "bad_any_cast.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bad_any_cast_impl - absl::config - PUBLIC -) - -# Internal-only target, do not depend on directly. -absl_cc_library( - NAME - bad_any_cast_impl - SRCS - "bad_any_cast.h" - "bad_any_cast.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::raw_logging_internal -) - -absl_cc_test( - NAME - any_test - SRCS - "any_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::any - absl::config - absl::exception_testing - absl::log - absl::test_instance_tracker - GTest::gmock_main -) - -absl_cc_test( - NAME - any_test_noexceptions - SRCS - "any_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::any - absl::config - absl::exception_testing - absl::raw_logging_internal - absl::test_instance_tracker - GTest::gmock_main -) - -absl_cc_test( - NAME - any_exception_safety_test - SRCS - "any_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::any - absl::config - absl::exception_safety_testing - GTest::gmock_main -) - -absl_cc_library( - NAME span HDRS "span.h"
diff --git a/absl/types/any.h b/absl/types/any.h index 61f071f..c488631 100644 --- a/absl/types/any.h +++ b/absl/types/any.h
@@ -17,50 +17,21 @@ // any.h // ----------------------------------------------------------------------------- // -// This header file define the `absl::any` type for holding a type-safe value -// of any type. The 'absl::any` type is useful for providing a way to hold -// something that is, as yet, unspecified. Such unspecified types -// traditionally are passed between API boundaries until they are later cast to -// their "destination" types. To cast to such a destination type, use -// `absl::any_cast()`. Note that when casting an `absl::any`, you must cast it -// to an explicit type; implicit conversions will throw. -// -// Example: -// -// auto a = absl::any(65); -// absl::any_cast<int>(a); // 65 -// absl::any_cast<char>(a); // throws absl::bad_any_cast -// absl::any_cast<std::string>(a); // throws absl::bad_any_cast -// -// `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction -// and is designed to be a drop-in replacement for code compliant with C++17. -// -// Traditionally, the behavior of casting to a temporary unspecified type has -// been accomplished with the `void *` paradigm, where the pointer was to some -// other unspecified type. `absl::any` provides an "owning" version of `void *` -// that avoids issues of pointer management. -// -// Note: just as in the case of `void *`, use of `absl::any` (and its C++17 -// version `std::any`) is a code smell indicating that your API might not be -// constructed correctly. We have seen that most uses of `any` are unwarranted, -// and `absl::any`, like `std::any`, is difficult to use properly. Before using -// this abstraction, make sure that you should not instead be rewriting your -// code to be more specific. -// -// Abseil has also released an `absl::variant` type (a C++11 compatible version -// of the C++17 `std::variant`), which is generally preferred for use over -// `absl::any`. +// Historical note: Abseil once provided an implementation of `absl::any` as a +// polyfill for `std::any` prior to C++17. Now that C++17 is required, +// `absl::any` is an alias for `std::any`. + #ifndef ABSL_TYPES_ANY_H_ #define ABSL_TYPES_ANY_H_ -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/utility/utility.h" - -#ifdef ABSL_USES_STD_ANY - #include <any> // IWYU pragma: export +#include "absl/base/config.h" + +// Include-what-you-use cleanup required for these headers. +#include "absl/base/attributes.h" +#include "absl/utility/utility.h" + namespace absl { ABSL_NAMESPACE_BEGIN using std::any; @@ -70,450 +41,4 @@ ABSL_NAMESPACE_END } // namespace absl -#else // ABSL_USES_STD_ANY - -#include <algorithm> -#include <cstddef> -#include <initializer_list> -#include <memory> -#include <stdexcept> -#include <type_traits> -#include <typeinfo> -#include <utility> - -#include "absl/base/internal/fast_type_id.h" -#include "absl/meta/type_traits.h" -#include "absl/types/bad_any_cast.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -class any; - -// swap() -// -// Swaps two `absl::any` values. Equivalent to `x.swap(y) where `x` and `y` are -// `absl::any` types. -void swap(any& x, any& y) noexcept; - -// make_any() -// -// Constructs an `absl::any` of type `T` with the given arguments. -template <typename T, typename... Args> -any make_any(Args&&... args); - -// Overload of `absl::make_any()` for constructing an `absl::any` type from an -// initializer list. -template <typename T, typename U, typename... Args> -any make_any(std::initializer_list<U> il, Args&&... args); - -// any_cast() -// -// Statically casts the value of a `const absl::any` type to the given type. -// This function will throw `absl::bad_any_cast` if the stored value type of the -// `absl::any` does not match the cast. -// -// `any_cast()` can also be used to get a reference to the internal storage iff -// a reference type is passed as its `ValueType`: -// -// Example: -// -// absl::any my_any = std::vector<int>(); -// absl::any_cast<std::vector<int>&>(my_any).push_back(42); -template <typename ValueType> -ValueType any_cast(const any& operand); - -// Overload of `any_cast()` to statically cast the value of a non-const -// `absl::any` type to the given type. This function will throw -// `absl::bad_any_cast` if the stored value type of the `absl::any` does not -// match the cast. -template <typename ValueType> -ValueType any_cast(any& operand); // NOLINT(runtime/references) - -// Overload of `any_cast()` to statically cast the rvalue of an `absl::any` -// type. This function will throw `absl::bad_any_cast` if the stored value type -// of the `absl::any` does not match the cast. -template <typename ValueType> -ValueType any_cast(any&& operand); - -// Overload of `any_cast()` to statically cast the value of a const pointer -// `absl::any` type to the given pointer type, or `nullptr` if the stored value -// type of the `absl::any` does not match the cast. -template <typename ValueType> -const ValueType* any_cast(const any* operand) noexcept; - -// Overload of `any_cast()` to statically cast the value of a pointer -// `absl::any` type to the given pointer type, or `nullptr` if the stored value -// type of the `absl::any` does not match the cast. -template <typename ValueType> -ValueType* any_cast(any* operand) noexcept; - -// ----------------------------------------------------------------------------- -// 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 -// store values of types that are unknown at compile time. The `absl::any` -// object, when containing a value, must contain a value type; storing a -// reference type is neither desired nor supported. -// -// An `absl::any` can only store a type that is copy-constructible; move-only -// types are not allowed within an `any` object. -// -// Example: -// -// auto a = absl::any(65); // Literal, copyable -// auto b = absl::any(std::vector<int>()); // Default-initialized, copyable -// std::unique_ptr<Foo> my_foo; -// auto c = absl::any(std::move(my_foo)); // Error, not copy-constructible -// -// Note that `absl::any` makes use of decayed types (`absl::decay_t` in this -// context) to remove const-volatile qualifiers (known as "cv qualifiers"), -// decay functions to function pointers, etc. We essentially "decay" a given -// type into its essential type. -// -// `absl::any` makes use of decayed types when determining the basic type `T` of -// the value to store in the any's contained object. In the documentation below, -// we explicitly denote this by using the phrase "a decayed type of `T`". -// -// Example: -// -// const int a = 4; -// absl::any foo(a); // Decay ensures we store an "int", not a "const int&". -// -// void my_function() {} -// absl::any bar(my_function); // Decay ensures we store a function pointer. -// -// `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction -// and is designed to be a drop-in replacement for code compliant with C++17. -class any { - private: - template <typename T> - struct IsInPlaceType; - - public: - // Constructors - - // Constructs an empty `absl::any` object (`any::has_value()` will return - // `false`). - constexpr any() noexcept; - - // Copy constructs an `absl::any` object with a "contained object" of the - // passed type of `other` (or an empty `absl::any` if `other.has_value()` is - // `false`. - any(const any& other) - : obj_(other.has_value() ? other.obj_->Clone() - : std::unique_ptr<ObjInterface>()) {} - - // Move constructs an `absl::any` object with a "contained object" of the - // passed type of `other` (or an empty `absl::any` if `other.has_value()` is - // `false`). - any(any&& other) noexcept = default; - - // Constructs an `absl::any` object with a "contained object" of the decayed - // type of `T`, which is initialized via `std::forward<T>(value)`. - // - // This constructor will not participate in overload resolution if the - // decayed type of `T` is not copy-constructible. - template < - typename T, typename VT = absl::decay_t<T>, - absl::enable_if_t<!absl::disjunction< - std::is_same<any, VT>, IsInPlaceType<VT>, - absl::negation<std::is_copy_constructible<VT> > >::value>* = nullptr> - any(T&& value) : obj_(new Obj<VT>(in_place, std::forward<T>(value))) {} - - // Constructs an `absl::any` object with a "contained object" of the decayed - // type of `T`, which is initialized via `std::forward<T>(value)`. - template <typename T, typename... Args, typename VT = absl::decay_t<T>, - absl::enable_if_t<absl::conjunction< - std::is_copy_constructible<VT>, - std::is_constructible<VT, Args...>>::value>* = nullptr> - explicit any(in_place_type_t<T> /*tag*/, Args&&... args) - : obj_(new Obj<VT>(in_place, std::forward<Args>(args)...)) {} - - // Constructs an `absl::any` object with a "contained object" of the passed - // type `VT` as a decayed type of `T`. `VT` is initialized as if - // direct-non-list-initializing an object of type `VT` with the arguments - // `initializer_list, std::forward<Args>(args)...`. - template < - typename T, typename U, typename... Args, typename VT = absl::decay_t<T>, - absl::enable_if_t< - absl::conjunction<std::is_copy_constructible<VT>, - std::is_constructible<VT, std::initializer_list<U>&, - Args...>>::value>* = nullptr> - explicit any(in_place_type_t<T> /*tag*/, std::initializer_list<U> ilist, - Args&&... args) - : obj_(new Obj<VT>(in_place, ilist, std::forward<Args>(args)...)) {} - - // Assignment operators - - // Copy assigns an `absl::any` object with a "contained object" of the - // passed type. - any& operator=(const any& rhs) { - any(rhs).swap(*this); - return *this; - } - - // Move assigns an `absl::any` object with a "contained object" of the - // passed type. `rhs` is left in a valid but otherwise unspecified state. - any& operator=(any&& rhs) noexcept { - any(std::move(rhs)).swap(*this); - return *this; - } - - // Assigns an `absl::any` object with a "contained object" of the passed type. - template <typename T, typename VT = absl::decay_t<T>, - absl::enable_if_t<absl::conjunction< - absl::negation<std::is_same<VT, any>>, - std::is_copy_constructible<VT>>::value>* = nullptr> - any& operator=(T&& rhs) { - any tmp(in_place_type_t<VT>(), std::forward<T>(rhs)); - tmp.swap(*this); - return *this; - } - - // Modifiers - - // any::emplace() - // - // Emplaces a value within an `absl::any` object by calling `any::reset()`, - // initializing the contained value as if direct-non-list-initializing an - // object of type `VT` with the arguments `std::forward<Args>(args)...`, and - // returning a reference to the new contained value. - // - // Note: If an exception is thrown during the call to `VT`'s constructor, - // `*this` does not contain a value, and any previously contained value has - // been destroyed. - template < - typename T, typename... Args, typename VT = absl::decay_t<T>, - absl::enable_if_t<std::is_copy_constructible<VT>::value && - std::is_constructible<VT, Args...>::value>* = nullptr> - VT& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND { - reset(); // NOTE: reset() is required here even in the world of exceptions. - Obj<VT>* const object_ptr = - new Obj<VT>(in_place, std::forward<Args>(args)...); - obj_ = std::unique_ptr<ObjInterface>(object_ptr); - return object_ptr->value; - } - - // Overload of `any::emplace()` to emplace a value within an `absl::any` - // object by calling `any::reset()`, initializing the contained value as if - // direct-non-list-initializing an object of type `VT` with the arguments - // `initializer_list, std::forward<Args>(args)...`, and returning a reference - // to the new contained value. - // - // Note: If an exception is thrown during the call to `VT`'s constructor, - // `*this` does not contain a value, and any previously contained value has - // been destroyed. The function shall not participate in overload resolution - // unless `is_copy_constructible_v<VT>` is `true` and - // `is_constructible_v<VT, initializer_list<U>&, Args...>` is `true`. - template < - typename T, typename U, typename... Args, typename VT = absl::decay_t<T>, - absl::enable_if_t<std::is_copy_constructible<VT>::value && - std::is_constructible<VT, std::initializer_list<U>&, - Args...>::value>* = nullptr> - VT& emplace(std::initializer_list<U> ilist, - Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND { - reset(); // NOTE: reset() is required here even in the world of exceptions. - Obj<VT>* const object_ptr = - new Obj<VT>(in_place, ilist, std::forward<Args>(args)...); - obj_ = std::unique_ptr<ObjInterface>(object_ptr); - return object_ptr->value; - } - - // any::reset() - // - // Resets the state of the `absl::any` object, destroying the contained object - // if present. - void reset() noexcept { obj_ = nullptr; } - - // any::swap() - // - // Swaps the passed value and the value of this `absl::any` object. - void swap(any& other) noexcept { obj_.swap(other.obj_); } - - // Observers - - // any::has_value() - // - // Returns `true` if the `any` object has a contained value, otherwise - // returns `false`. - bool has_value() const noexcept { return obj_ != nullptr; } - -#ifdef ABSL_INTERNAL_HAS_RTTI - // Returns: typeid(T) if *this has a contained object of type T, otherwise - // typeid(void). - const std::type_info& type() const noexcept { - if (has_value()) { - return obj_->Type(); - } - - return typeid(void); - } -#endif // ABSL_INTERNAL_HAS_RTTI - - private: - // Tagged type-erased abstraction for holding a cloneable object. - class ObjInterface { - public: - virtual ~ObjInterface() = default; - virtual std::unique_ptr<ObjInterface> Clone() const = 0; - virtual const void* ObjTypeId() const noexcept = 0; -#ifdef ABSL_INTERNAL_HAS_RTTI - virtual const std::type_info& Type() const noexcept = 0; -#endif // ABSL_INTERNAL_HAS_RTTI - }; - - // Hold a value of some queryable type, with an ability to Clone it. - template <typename T> - class Obj : public ObjInterface { - public: - template <typename... Args> - explicit Obj(in_place_t /*tag*/, Args&&... args) - : value(std::forward<Args>(args)...) {} - - std::unique_ptr<ObjInterface> Clone() const final { - return std::unique_ptr<ObjInterface>(new Obj(in_place, value)); - } - - const void* ObjTypeId() const noexcept final { return IdForType<T>(); } - -#ifdef ABSL_INTERNAL_HAS_RTTI - const std::type_info& Type() const noexcept final { return typeid(T); } -#endif // ABSL_INTERNAL_HAS_RTTI - - T value; - }; - - std::unique_ptr<ObjInterface> CloneObj() const { - if (!obj_) return nullptr; - return obj_->Clone(); - } - - template <typename T> - constexpr static const void* IdForType() { - // Note: This type dance is to make the behavior consistent with typeid. - using NormalizedType = - typename std::remove_cv<typename std::remove_reference<T>::type>::type; - - return base_internal::FastTypeId<NormalizedType>(); - } - - const void* GetObjTypeId() const { - return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>(); - } - - // `absl::any` nonmember functions // - - // Description at the declaration site (top of file). - template <typename ValueType> - friend ValueType any_cast(const any& operand); - - // Description at the declaration site (top of file). - template <typename ValueType> - friend ValueType any_cast(any& operand); // NOLINT(runtime/references) - - // Description at the declaration site (top of file). - template <typename T> - friend const T* any_cast(const any* operand) noexcept; - - // Description at the declaration site (top of file). - template <typename T> - friend T* any_cast(any* operand) noexcept; - - std::unique_ptr<ObjInterface> obj_; -}; - -// ----------------------------------------------------------------------------- -// Implementation Details -// ----------------------------------------------------------------------------- - -constexpr any::any() noexcept = default; - -template <typename T> -struct any::IsInPlaceType : std::false_type {}; - -template <typename T> -struct any::IsInPlaceType<in_place_type_t<T>> : std::true_type {}; - -inline void swap(any& x, any& y) noexcept { x.swap(y); } - -// Description at the declaration site (top of file). -template <typename T, typename... Args> -any make_any(Args&&... args) { - return any(in_place_type_t<T>(), std::forward<Args>(args)...); -} - -// Description at the declaration site (top of file). -template <typename T, typename U, typename... Args> -any make_any(std::initializer_list<U> il, Args&&... args) { - return any(in_place_type_t<T>(), il, std::forward<Args>(args)...); -} - -// Description at the declaration site (top of file). -template <typename ValueType> -ValueType any_cast(const any& operand) { - using U = typename std::remove_cv< - typename std::remove_reference<ValueType>::type>::type; - static_assert(std::is_constructible<ValueType, const U&>::value, - "Invalid ValueType"); - auto* const result = (any_cast<U>)(&operand); - if (result == nullptr) { - any_internal::ThrowBadAnyCast(); - } - return static_cast<ValueType>(*result); -} - -// Description at the declaration site (top of file). -template <typename ValueType> -ValueType any_cast(any& operand) { // NOLINT(runtime/references) - using U = typename std::remove_cv< - typename std::remove_reference<ValueType>::type>::type; - static_assert(std::is_constructible<ValueType, U&>::value, - "Invalid ValueType"); - auto* result = (any_cast<U>)(&operand); - if (result == nullptr) { - any_internal::ThrowBadAnyCast(); - } - return static_cast<ValueType>(*result); -} - -// Description at the declaration site (top of file). -template <typename ValueType> -ValueType any_cast(any&& operand) { - using U = typename std::remove_cv< - typename std::remove_reference<ValueType>::type>::type; - static_assert(std::is_constructible<ValueType, U>::value, - "Invalid ValueType"); - return static_cast<ValueType>(std::move((any_cast<U&>)(operand))); -} - -// Description at the declaration site (top of file). -template <typename T> -const T* any_cast(const any* operand) noexcept { - using U = - typename std::remove_cv<typename std::remove_reference<T>::type>::type; - return operand && operand->GetObjTypeId() == any::IdForType<U>() - ? std::addressof( - static_cast<const any::Obj<U>*>(operand->obj_.get())->value) - : nullptr; -} - -// Description at the declaration site (top of file). -template <typename T> -T* any_cast(any* operand) noexcept { - using U = - typename std::remove_cv<typename std::remove_reference<T>::type>::type; - return operand && operand->GetObjTypeId() == any::IdForType<U>() - ? std::addressof( - static_cast<any::Obj<U>*>(operand->obj_.get())->value) - : nullptr; -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_ANY - #endif // ABSL_TYPES_ANY_H_
diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc deleted file mode 100644 index 31c1140..0000000 --- a/absl/types/any_exception_safety_test.cc +++ /dev/null
@@ -1,173 +0,0 @@ -// 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 -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/types/any.h" - -#include "absl/base/config.h" - -// This test is a no-op when absl::any is an alias for std::any and when -// exceptions are not enabled. -#if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS) - -#include <typeinfo> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" - -using Thrower = testing::ThrowingValue<>; -using NoThrowMoveThrower = - testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; -using ThrowerList = std::initializer_list<Thrower>; -using ThrowerVec = std::vector<Thrower>; -using ThrowingAlloc = testing::ThrowingAllocator<Thrower>; -using ThrowingThrowerVec = std::vector<Thrower, ThrowingAlloc>; - -namespace { - -testing::AssertionResult AnyInvariants(absl::any* a) { - using testing::AssertionFailure; - using testing::AssertionSuccess; - - if (a->has_value()) { - if (a->type() == typeid(void)) { - return AssertionFailure() - << "A non-empty any should not have type `void`"; - } - } else { - if (a->type() != typeid(void)) { - return AssertionFailure() - << "An empty any should have type void, but has type " - << a->type().name(); - } - } - - // Make sure that reset() changes any to a valid state. - a->reset(); - if (a->has_value()) { - return AssertionFailure() << "A reset `any` should be valueless"; - } - if (a->type() != typeid(void)) { - return AssertionFailure() << "A reset `any` should have type() of `void`, " - "but instead has type " - << a->type().name(); - } - try { - auto unused = absl::any_cast<Thrower>(*a); - static_cast<void>(unused); - return AssertionFailure() - << "A reset `any` should not be able to be any_cast"; - } catch (const absl::bad_any_cast&) { - } catch (...) { - return AssertionFailure() - << "Unexpected exception thrown from absl::any_cast"; - } - return AssertionSuccess(); -} - -testing::AssertionResult AnyIsEmpty(absl::any* a) { - if (!a->has_value()) { - return testing::AssertionSuccess(); - } - return testing::AssertionFailure() - << "a should be empty, but instead has value " - << absl::any_cast<Thrower>(*a).Get(); -} - -TEST(AnyExceptionSafety, Ctors) { - Thrower val(1); - testing::TestThrowingCtor<absl::any>(val); - - Thrower copy(val); - testing::TestThrowingCtor<absl::any>(copy); - - testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<Thrower>(), 1); - - testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<ThrowerVec>(), - ThrowerList{val}); - - testing::TestThrowingCtor<absl::any, - absl::in_place_type_t<ThrowingThrowerVec>, - ThrowerList, ThrowingAlloc>( - absl::in_place_type_t<ThrowingThrowerVec>(), {val}, ThrowingAlloc()); -} - -TEST(AnyExceptionSafety, Assignment) { - auto original = - absl::any(absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor); - auto any_is_strong = [original](absl::any* ap) { - return testing::AssertionResult(ap->has_value() && - absl::any_cast<Thrower>(original) == - absl::any_cast<Thrower>(*ap)); - }; - auto any_strong_tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(original) - .WithContracts(AnyInvariants, any_is_strong); - - Thrower val(2); - absl::any any_val(val); - NoThrowMoveThrower mv_val(2); - - auto assign_any = [&any_val](absl::any* ap) { *ap = any_val; }; - auto assign_val = [&val](absl::any* ap) { *ap = val; }; - auto move = [&val](absl::any* ap) { *ap = std::move(val); }; - auto move_movable = [&mv_val](absl::any* ap) { *ap = std::move(mv_val); }; - - EXPECT_TRUE(any_strong_tester.Test(assign_any)); - EXPECT_TRUE(any_strong_tester.Test(assign_val)); - EXPECT_TRUE(any_strong_tester.Test(move)); - EXPECT_TRUE(any_strong_tester.Test(move_movable)); - - auto empty_any_is_strong = [](absl::any* ap) { - return testing::AssertionResult{!ap->has_value()}; - }; - auto strong_empty_any_tester = - testing::MakeExceptionSafetyTester() - .WithInitialValue(absl::any{}) - .WithContracts(AnyInvariants, empty_any_is_strong); - - EXPECT_TRUE(strong_empty_any_tester.Test(assign_any)); - EXPECT_TRUE(strong_empty_any_tester.Test(assign_val)); - EXPECT_TRUE(strong_empty_any_tester.Test(move)); -} - -TEST(AnyExceptionSafety, Emplace) { - auto initial_val = - absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor}; - auto one_tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(initial_val) - .WithContracts(AnyInvariants, AnyIsEmpty); - - auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); }; - auto emp_throwervec = [](absl::any* ap) { - std::initializer_list<Thrower> il{Thrower(2, testing::nothrow_ctor)}; - ap->emplace<ThrowerVec>(il); - }; - auto emp_movethrower = [](absl::any* ap) { - ap->emplace<NoThrowMoveThrower>(2); - }; - - EXPECT_TRUE(one_tester.Test(emp_thrower)); - EXPECT_TRUE(one_tester.Test(emp_throwervec)); - EXPECT_TRUE(one_tester.Test(emp_movethrower)); - - auto empty_tester = one_tester.WithInitialValue(absl::any{}); - - EXPECT_TRUE(empty_tester.Test(emp_thrower)); - EXPECT_TRUE(empty_tester.Test(emp_throwervec)); -} - -} // namespace - -#endif // #if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/absl/types/any_test.cc b/absl/types/any_test.cc deleted file mode 100644 index 666ea5b..0000000 --- a/absl/types/any_test.cc +++ /dev/null
@@ -1,778 +0,0 @@ -// 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 -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/types/any.h" - -// This test is a no-op when absl::any is an alias for std::any. -#if !defined(ABSL_USES_STD_ANY) - -#include <initializer_list> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/base/internal/exception_testing.h" -#include "absl/container/internal/test_instance_tracker.h" -#include "absl/log/log.h" - -namespace { -using absl::test_internal::CopyableOnlyInstance; -using absl::test_internal::InstanceTracker; - -template <typename T> -const T& AsConst(const T& t) { - return t; -} - -struct MoveOnly { - MoveOnly() = default; - explicit MoveOnly(int value) : value(value) {} - MoveOnly(MoveOnly&&) = default; - MoveOnly& operator=(MoveOnly&&) = default; - - int value = 0; -}; - -struct CopyOnly { - CopyOnly() = default; - explicit CopyOnly(int value) : value(value) {} - CopyOnly(CopyOnly&&) = delete; - CopyOnly& operator=(CopyOnly&&) = delete; - CopyOnly(const CopyOnly&) = default; - CopyOnly& operator=(const CopyOnly&) = default; - - int value = 0; -}; - -struct MoveOnlyWithListConstructor { - MoveOnlyWithListConstructor() = default; - explicit MoveOnlyWithListConstructor(std::initializer_list<int> /*ilist*/, - int value) - : value(value) {} - MoveOnlyWithListConstructor(MoveOnlyWithListConstructor&&) = default; - MoveOnlyWithListConstructor& operator=(MoveOnlyWithListConstructor&&) = - default; - - int value = 0; -}; - -struct IntMoveOnlyCopyOnly { - IntMoveOnlyCopyOnly(int value, MoveOnly /*move_only*/, CopyOnly /*copy_only*/) - : value(value) {} - - int value; -}; - -struct ListMoveOnlyCopyOnly { - ListMoveOnlyCopyOnly(std::initializer_list<int> ilist, MoveOnly /*move_only*/, - CopyOnly /*copy_only*/) - : values(ilist) {} - - std::vector<int> values; -}; - -using FunctionType = void(); -void FunctionToEmplace() {} - -using ArrayType = int[2]; -using DecayedArray = absl::decay_t<ArrayType>; - -TEST(AnyTest, Noexcept) { - static_assert(std::is_nothrow_default_constructible<absl::any>(), ""); - static_assert(std::is_nothrow_move_constructible<absl::any>(), ""); - static_assert(std::is_nothrow_move_assignable<absl::any>(), ""); - static_assert(noexcept(std::declval<absl::any&>().has_value()), ""); - static_assert(noexcept(std::declval<absl::any&>().type()), ""); - static_assert(noexcept(absl::any_cast<int>(std::declval<absl::any*>())), ""); - static_assert( - noexcept(std::declval<absl::any&>().swap(std::declval<absl::any&>())), - ""); - - using std::swap; - static_assert( - noexcept(swap(std::declval<absl::any&>(), std::declval<absl::any&>())), - ""); -} - -TEST(AnyTest, HasValue) { - absl::any o; - EXPECT_FALSE(o.has_value()); - o.emplace<int>(); - EXPECT_TRUE(o.has_value()); - o.reset(); - EXPECT_FALSE(o.has_value()); -} - -TEST(AnyTest, Type) { - absl::any o; - EXPECT_EQ(typeid(void), o.type()); - o.emplace<int>(5); - EXPECT_EQ(typeid(int), o.type()); - o.emplace<float>(5.f); - EXPECT_EQ(typeid(float), o.type()); - o.reset(); - EXPECT_EQ(typeid(void), o.type()); -} - -TEST(AnyTest, EmptyPointerCast) { - // pointer-to-unqualified overload - { - absl::any o; - EXPECT_EQ(nullptr, absl::any_cast<int>(&o)); - o.emplace<int>(); - EXPECT_NE(nullptr, absl::any_cast<int>(&o)); - o.reset(); - EXPECT_EQ(nullptr, absl::any_cast<int>(&o)); - } - - // pointer-to-const overload - { - absl::any o; - EXPECT_EQ(nullptr, absl::any_cast<int>(&AsConst(o))); - o.emplace<int>(); - EXPECT_NE(nullptr, absl::any_cast<int>(&AsConst(o))); - o.reset(); - EXPECT_EQ(nullptr, absl::any_cast<int>(&AsConst(o))); - } -} - -TEST(AnyTest, InPlaceConstruction) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type_t<IntMoveOnlyCopyOnly>(), 5, MoveOnly(), - copy_only); - IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); -} - -TEST(AnyTest, InPlaceConstructionVariableTemplate) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type<IntMoveOnlyCopyOnly>, 5, MoveOnly(), - copy_only); - auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); -} - -TEST(AnyTest, InPlaceConstructionWithCV) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type_t<const volatile IntMoveOnlyCopyOnly>(), 5, - MoveOnly(), copy_only); - IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); -} - -TEST(AnyTest, InPlaceConstructionWithCVVariableTemplate) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type<const volatile IntMoveOnlyCopyOnly>, 5, - MoveOnly(), copy_only); - auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); -} - -TEST(AnyTest, InPlaceConstructionWithFunction) { - absl::any o(absl::in_place_type_t<FunctionType>(), FunctionToEmplace); - FunctionType*& construction_result = absl::any_cast<FunctionType*&>(o); - EXPECT_EQ(&FunctionToEmplace, construction_result); -} - -TEST(AnyTest, InPlaceConstructionWithFunctionVariableTemplate) { - absl::any o(absl::in_place_type<FunctionType>, FunctionToEmplace); - auto& construction_result = absl::any_cast<FunctionType*&>(o); - EXPECT_EQ(&FunctionToEmplace, construction_result); -} - -TEST(AnyTest, InPlaceConstructionWithArray) { - ArrayType ar = {5, 42}; - absl::any o(absl::in_place_type_t<ArrayType>(), ar); - DecayedArray& construction_result = absl::any_cast<DecayedArray&>(o); - EXPECT_EQ(&ar[0], construction_result); -} - -TEST(AnyTest, InPlaceConstructionWithArrayVariableTemplate) { - ArrayType ar = {5, 42}; - absl::any o(absl::in_place_type<ArrayType>, ar); - auto& construction_result = absl::any_cast<DecayedArray&>(o); - EXPECT_EQ(&ar[0], construction_result); -} - -TEST(AnyTest, InPlaceConstructionIlist) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type_t<ListMoveOnlyCopyOnly>(), {1, 2, 3, 4}, - MoveOnly(), copy_only); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, InPlaceConstructionIlistVariableTemplate) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type<ListMoveOnlyCopyOnly>, {1, 2, 3, 4}, - MoveOnly(), copy_only); - auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, InPlaceConstructionIlistWithCV) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type_t<const volatile ListMoveOnlyCopyOnly>(), - {1, 2, 3, 4}, MoveOnly(), copy_only); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, InPlaceConstructionIlistWithCVVariableTemplate) { - const CopyOnly copy_only{}; - absl::any o(absl::in_place_type<const volatile ListMoveOnlyCopyOnly>, - {1, 2, 3, 4}, MoveOnly(), copy_only); - auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, InPlaceNoArgs) { - absl::any o(absl::in_place_type_t<int>{}); - EXPECT_EQ(0, absl::any_cast<int&>(o)); -} - -TEST(AnyTest, InPlaceNoArgsVariableTemplate) { - absl::any o(absl::in_place_type<int>); - EXPECT_EQ(0, absl::any_cast<int&>(o)); -} - -template <typename Enabler, typename T, typename... Args> -struct CanEmplaceAnyImpl : std::false_type {}; - -template <typename T, typename... Args> -struct CanEmplaceAnyImpl< - absl::void_t<decltype( - std::declval<absl::any&>().emplace<T>(std::declval<Args>()...))>, - T, Args...> : std::true_type {}; - -template <typename T, typename... Args> -using CanEmplaceAny = CanEmplaceAnyImpl<void, T, Args...>; - -TEST(AnyTest, Emplace) { - const CopyOnly copy_only{}; - absl::any o; - EXPECT_TRUE((std::is_same<decltype(o.emplace<IntMoveOnlyCopyOnly>( - 5, MoveOnly(), copy_only)), - IntMoveOnlyCopyOnly&>::value)); - IntMoveOnlyCopyOnly& emplace_result = - o.emplace<IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only); - EXPECT_EQ(5, emplace_result.value); - IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); - EXPECT_EQ(&emplace_result, &v); - - static_assert(!CanEmplaceAny<int, int, int>::value, ""); - static_assert(!CanEmplaceAny<MoveOnly, MoveOnly>::value, ""); -} - -TEST(AnyTest, EmplaceWithCV) { - const CopyOnly copy_only{}; - absl::any o; - EXPECT_TRUE( - (std::is_same<decltype(o.emplace<const volatile IntMoveOnlyCopyOnly>( - 5, MoveOnly(), copy_only)), - IntMoveOnlyCopyOnly&>::value)); - IntMoveOnlyCopyOnly& emplace_result = - o.emplace<const volatile IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only); - EXPECT_EQ(5, emplace_result.value); - IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o); - EXPECT_EQ(5, v.value); - EXPECT_EQ(&emplace_result, &v); -} - -TEST(AnyTest, EmplaceWithFunction) { - absl::any o; - EXPECT_TRUE( - (std::is_same<decltype(o.emplace<FunctionType>(FunctionToEmplace)), - FunctionType*&>::value)); - FunctionType*& emplace_result = o.emplace<FunctionType>(FunctionToEmplace); - EXPECT_EQ(&FunctionToEmplace, emplace_result); -} - -TEST(AnyTest, EmplaceWithArray) { - absl::any o; - ArrayType ar = {5, 42}; - EXPECT_TRUE( - (std::is_same<decltype(o.emplace<ArrayType>(ar)), DecayedArray&>::value)); - DecayedArray& emplace_result = o.emplace<ArrayType>(ar); - EXPECT_EQ(&ar[0], emplace_result); -} - -TEST(AnyTest, EmplaceIlist) { - const CopyOnly copy_only{}; - absl::any o; - EXPECT_TRUE((std::is_same<decltype(o.emplace<ListMoveOnlyCopyOnly>( - {1, 2, 3, 4}, MoveOnly(), copy_only)), - ListMoveOnlyCopyOnly&>::value)); - ListMoveOnlyCopyOnly& emplace_result = - o.emplace<ListMoveOnlyCopyOnly>({1, 2, 3, 4}, MoveOnly(), copy_only); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - EXPECT_EQ(&v, &emplace_result); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); - - static_assert(!CanEmplaceAny<int, std::initializer_list<int>>::value, ""); - static_assert(!CanEmplaceAny<MoveOnlyWithListConstructor, - std::initializer_list<int>, int>::value, - ""); -} - -TEST(AnyTest, EmplaceIlistWithCV) { - const CopyOnly copy_only{}; - absl::any o; - EXPECT_TRUE( - (std::is_same<decltype(o.emplace<const volatile ListMoveOnlyCopyOnly>( - {1, 2, 3, 4}, MoveOnly(), copy_only)), - ListMoveOnlyCopyOnly&>::value)); - ListMoveOnlyCopyOnly& emplace_result = - o.emplace<const volatile ListMoveOnlyCopyOnly>({1, 2, 3, 4}, MoveOnly(), - copy_only); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - EXPECT_EQ(&v, &emplace_result); - std::vector<int> expected_values = {1, 2, 3, 4}; - EXPECT_EQ(expected_values, v.values); -} - -TEST(AnyTest, EmplaceNoArgs) { - absl::any o; - o.emplace<int>(); - EXPECT_EQ(0, absl::any_cast<int>(o)); -} - -TEST(AnyTest, ConversionConstruction) { - { - absl::any o = 5; - EXPECT_EQ(5, absl::any_cast<int>(o)); - } - - { - const CopyOnly copy_only(5); - absl::any o = copy_only; - EXPECT_EQ(5, absl::any_cast<CopyOnly&>(o).value); - } - - static_assert(!std::is_convertible<MoveOnly, absl::any>::value, ""); -} - -TEST(AnyTest, ConversionAssignment) { - { - absl::any o; - o = 5; - EXPECT_EQ(5, absl::any_cast<int>(o)); - } - - { - const CopyOnly copy_only(5); - absl::any o; - o = copy_only; - EXPECT_EQ(5, absl::any_cast<CopyOnly&>(o).value); - } - - static_assert(!std::is_assignable<MoveOnly, absl::any>::value, ""); -} - -// Suppress MSVC warnings. -// 4521: multiple copy constructors specified -// We wrote multiple of them to test that the correct overloads are selected. -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4521) -#endif - -// Weird type for testing, only used to make sure we "properly" perfect-forward -// when being placed into an absl::any (use the l-value constructor if given an -// l-value rather than use the copy constructor). -struct WeirdConstructor42 { - explicit WeirdConstructor42(int value) : value(value) {} - - // Copy-constructor - WeirdConstructor42(const WeirdConstructor42& other) : value(other.value) {} - - // L-value "weird" constructor (used when given an l-value) - WeirdConstructor42( - WeirdConstructor42& /*other*/) // NOLINT(runtime/references) - : value(42) {} - - int value; -}; -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -TEST(AnyTest, WeirdConversionConstruction) { - { - const WeirdConstructor42 source(5); - absl::any o = source; // Actual copy - EXPECT_EQ(5, absl::any_cast<WeirdConstructor42&>(o).value); - } - - { - WeirdConstructor42 source(5); - absl::any o = source; // Weird "conversion" - EXPECT_EQ(42, absl::any_cast<WeirdConstructor42&>(o).value); - } -} - -TEST(AnyTest, WeirdConversionAssignment) { - { - const WeirdConstructor42 source(5); - absl::any o; - o = source; // Actual copy - EXPECT_EQ(5, absl::any_cast<WeirdConstructor42&>(o).value); - } - - { - WeirdConstructor42 source(5); - absl::any o; - o = source; // Weird "conversion" - EXPECT_EQ(42, absl::any_cast<WeirdConstructor42&>(o).value); - } -} - -struct Value {}; - -TEST(AnyTest, AnyCastValue) { - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<int>(o)); - EXPECT_EQ(5, absl::any_cast<int>(AsConst(o))); - static_assert( - std::is_same<decltype(absl::any_cast<Value>(o)), Value>::value, ""); - } - - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<const int>(o)); - EXPECT_EQ(5, absl::any_cast<const int>(AsConst(o))); - static_assert(std::is_same<decltype(absl::any_cast<const Value>(o)), - const Value>::value, - ""); - } -} - -TEST(AnyTest, AnyCastReference) { - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<int&>(o)); - EXPECT_EQ(5, absl::any_cast<const int&>(AsConst(o))); - static_assert( - std::is_same<decltype(absl::any_cast<Value&>(o)), Value&>::value, ""); - } - - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<const int>(o)); - EXPECT_EQ(5, absl::any_cast<const int>(AsConst(o))); - static_assert(std::is_same<decltype(absl::any_cast<const Value&>(o)), - const Value&>::value, - ""); - } - - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<int&&>(std::move(o))); - static_assert(std::is_same<decltype(absl::any_cast<Value&&>(std::move(o))), - Value&&>::value, - ""); - } - - { - absl::any o; - o.emplace<int>(5); - EXPECT_EQ(5, absl::any_cast<const int>(std::move(o))); - static_assert( - std::is_same<decltype(absl::any_cast<const Value&&>(std::move(o))), - const Value&&>::value, - ""); - } -} - -TEST(AnyTest, AnyCastPointer) { - { - absl::any o; - EXPECT_EQ(nullptr, absl::any_cast<char>(&o)); - o.emplace<int>(5); - EXPECT_EQ(nullptr, absl::any_cast<char>(&o)); - o.emplace<char>('a'); - EXPECT_EQ('a', *absl::any_cast<char>(&o)); - static_assert( - std::is_same<decltype(absl::any_cast<Value>(&o)), Value*>::value, ""); - } - - { - absl::any o; - EXPECT_EQ(nullptr, absl::any_cast<const char>(&o)); - o.emplace<int>(5); - EXPECT_EQ(nullptr, absl::any_cast<const char>(&o)); - o.emplace<char>('a'); - EXPECT_EQ('a', *absl::any_cast<const char>(&o)); - static_assert(std::is_same<decltype(absl::any_cast<const Value>(&o)), - const Value*>::value, - ""); - } -} - -TEST(AnyTest, MakeAny) { - const CopyOnly copy_only{}; - auto o = absl::make_any<IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only); - static_assert(std::is_same<decltype(o), absl::any>::value, ""); - EXPECT_EQ(5, absl::any_cast<IntMoveOnlyCopyOnly&>(o).value); -} - -TEST(AnyTest, MakeAnyIList) { - const CopyOnly copy_only{}; - auto o = - absl::make_any<ListMoveOnlyCopyOnly>({1, 2, 3}, MoveOnly(), copy_only); - static_assert(std::is_same<decltype(o), absl::any>::value, ""); - ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o); - std::vector<int> expected_values = {1, 2, 3}; - EXPECT_EQ(expected_values, v.values); -} - -// Test the use of copy constructor and operator= -TEST(AnyTest, Copy) { - InstanceTracker tracker_raii; - - { - absl::any o(absl::in_place_type<CopyableOnlyInstance>, 123); - CopyableOnlyInstance* f1 = absl::any_cast<CopyableOnlyInstance>(&o); - - absl::any o2(o); - const CopyableOnlyInstance* f2 = absl::any_cast<CopyableOnlyInstance>(&o2); - EXPECT_EQ(123, f2->value()); - EXPECT_NE(f1, f2); - - absl::any o3; - o3 = o2; - const CopyableOnlyInstance* f3 = absl::any_cast<CopyableOnlyInstance>(&o3); - EXPECT_EQ(123, f3->value()); - EXPECT_NE(f2, f3); - - const absl::any o4(4); - // copy construct from const lvalue ref. - absl::any o5 = o4; - EXPECT_EQ(4, absl::any_cast<int>(o4)); - EXPECT_EQ(4, absl::any_cast<int>(o5)); - - // Copy construct from const rvalue ref. - absl::any o6 = std::move(o4); // NOLINT - EXPECT_EQ(4, absl::any_cast<int>(o4)); - EXPECT_EQ(4, absl::any_cast<int>(o6)); - } -} - -TEST(AnyTest, Move) { - InstanceTracker tracker_raii; - - absl::any any1; - any1.emplace<CopyableOnlyInstance>(5); - - // This is a copy, so copy count increases to 1. - absl::any any2 = any1; - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any1).value()); - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any2).value()); - EXPECT_EQ(1, tracker_raii.copies()); - - // This isn't a copy, so copy count doesn't increase. - absl::any any3 = std::move(any2); - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any3).value()); - EXPECT_EQ(1, tracker_raii.copies()); - - absl::any any4; - any4 = std::move(any3); - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any4).value()); - EXPECT_EQ(1, tracker_raii.copies()); - - absl::any tmp4(4); - absl::any o4(std::move(tmp4)); // move construct - EXPECT_EQ(4, absl::any_cast<int>(o4)); - o4 = *&o4; // self assign - EXPECT_EQ(4, absl::any_cast<int>(o4)); - EXPECT_TRUE(o4.has_value()); - - absl::any o5; - absl::any tmp5(5); - o5 = std::move(tmp5); // move assign - EXPECT_EQ(5, absl::any_cast<int>(o5)); -} - -// Reset the ObjectOwner with an object of a different type -TEST(AnyTest, Reset) { - absl::any o; - o.emplace<int>(); - - o.reset(); - EXPECT_FALSE(o.has_value()); - - o.emplace<char>(); - EXPECT_TRUE(o.has_value()); -} - -TEST(AnyTest, ConversionConstructionCausesOneCopy) { - InstanceTracker tracker_raii; - CopyableOnlyInstance counter(5); - absl::any o(counter); - EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(o).value()); - EXPECT_EQ(1, tracker_raii.copies()); -} - -////////////////////////////////// -// Tests for Exception Behavior // -////////////////////////////////// - -#if defined(ABSL_USES_STD_ANY) - -// If using a std `any` implementation, we can't check for a specific message. -#define ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(...) \ - ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), absl::bad_any_cast, \ - "") - -#else - -// If using the absl `any` implementation, we can rely on a specific message. -#define ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(...) \ - ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), absl::bad_any_cast, \ - "Bad any cast") - -#endif // defined(ABSL_USES_STD_ANY) - -TEST(AnyTest, ThrowBadAlloc) { - { - absl::any a; - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int&>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int&&>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&&>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(absl::any{})); - - // const absl::any operand - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&>(AsConst(a))); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(AsConst(a))); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(AsConst(a))); - } - - { - absl::any a(absl::in_place_type<int>); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float&>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&&>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST( - absl::any_cast<const float&&>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(a)); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(absl::any{})); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(absl::any{})); - - // const absl::any operand - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float&>(AsConst(a))); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(AsConst(a))); - ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(AsConst(a))); - } -} - -class BadCopy {}; - -struct BadCopyable { - BadCopyable() = default; - BadCopyable(BadCopyable&&) = default; - BadCopyable(const BadCopyable&) { -#ifdef ABSL_HAVE_EXCEPTIONS - throw BadCopy(); -#else - LOG(FATAL) << "Bad copy"; -#endif - } -}; - -#define ABSL_ANY_TEST_EXPECT_BAD_COPY(...) \ - ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), BadCopy, "Bad copy") - -// Test the guarantees regarding exceptions in copy/assign. -TEST(AnyTest, FailedCopy) { - { - const BadCopyable bad{}; - ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{bad}); - } - - { - absl::any src(absl::in_place_type<BadCopyable>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{src}); - } - - { - BadCopyable bad; - absl::any target; - ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad); - } - - { - BadCopyable bad; - absl::any target(absl::in_place_type<BadCopyable>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad); - EXPECT_TRUE(target.has_value()); - } - - { - absl::any src(absl::in_place_type<BadCopyable>); - absl::any target; - ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src); - EXPECT_FALSE(target.has_value()); - } - - { - absl::any src(absl::in_place_type<BadCopyable>); - absl::any target(absl::in_place_type<BadCopyable>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src); - EXPECT_TRUE(target.has_value()); - } -} - -// Test the guarantees regarding exceptions in emplace. -TEST(AnyTest, FailedEmplace) { - BadCopyable bad; - absl::any target; - ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad)); -} - -// GCC and Clang have a bug here. -// Ine some cases, the exception seems to be thrown at the wrong time, and -// target may contain a value. -#ifdef __GNUC__ -TEST(AnyTest, DISABLED_FailedEmplaceInPlace) { -#else -TEST(AnyTest, FailedEmplaceInPlace) { -#endif - BadCopyable bad; - absl::any target(absl::in_place_type<int>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad)); - EXPECT_FALSE(target.has_value()); -} - -} // namespace - -#endif // #if !defined(ABSL_USES_STD_ANY)
diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc deleted file mode 100644 index 22558b4..0000000 --- a/absl/types/bad_any_cast.cc +++ /dev/null
@@ -1,64 +0,0 @@ -// 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 -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/types/bad_any_cast.h" - -#ifndef ABSL_USES_STD_ANY - -#include <cstdlib> - -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -bad_any_cast::~bad_any_cast() = default; - -const char* bad_any_cast::what() const noexcept { return "Bad any cast"; } - -namespace any_internal { - -void ThrowBadAnyCast() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw bad_any_cast(); -#else - ABSL_RAW_LOG(FATAL, "Bad any cast"); - std::abort(); -#endif -} - -} // namespace any_internal -ABSL_NAMESPACE_END -} // namespace absl - -#else - -// https://github.com/abseil/abseil-cpp/issues/1465 -// CMake builds on Apple platforms error when libraries are empty. -// Our CMake configuration can avoid this error on header-only libraries, -// but since this library is conditionally empty, including a single -// variable is an easy workaround. -#ifdef __APPLE__ -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { -extern const char kAvoidEmptyBadAnyCastLibraryWarning; -const char kAvoidEmptyBadAnyCastLibraryWarning = 0; -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl -#endif // __APPLE__ - -#endif // ABSL_USES_STD_ANY
diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h deleted file mode 100644 index 114cef8..0000000 --- a/absl/types/bad_any_cast.h +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// 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_ - -#include <typeinfo> - -#include "absl/base/config.h" - -#ifdef ABSL_USES_STD_ANY - -#include <any> - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_any_cast; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_ANY - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// 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; -}; - -namespace any_internal { - -[[noreturn]] void ThrowBadAnyCast(); - -} // namespace any_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_ANY - -#endif // ABSL_TYPES_BAD_ANY_CAST_H_
diff --git a/absl/utility/utility.h b/absl/utility/utility.h index 9e37ee2..47074bd 100644 --- a/absl/utility/utility.h +++ b/absl/utility/utility.h
@@ -53,6 +53,8 @@ using std::forward; using std::index_sequence; using std::index_sequence_for; +using std::in_place_type; +using std::in_place_type_t; using std::integer_sequence; using std::make_index_sequence; using std::make_integer_sequence; @@ -96,23 +98,6 @@ #endif // ABSL_USES_STD_OPTIONAL -#if defined(ABSL_USES_STD_ANY) || defined(ABSL_USES_STD_VARIANT) -using std::in_place_type; -using std::in_place_type_t; -#else - -// in_place_type_t -// -// Tag type used for in-place construction when the type to construct needs to -// be specified, such as with `absl::any`, designed to be a drop-in replacement -// for C++17's `std::in_place_type_t`. -template <typename T> -using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag<T>); - -template <typename T> -void in_place_type(utility_internal::InPlaceTypeTag<T>) {} -#endif // ABSL_USES_STD_ANY || ABSL_USES_STD_VARIANT - #ifdef ABSL_USES_STD_VARIANT using std::in_place_index; using std::in_place_index_t;