diff options
Diffstat (limited to 'third_party/abseil_cpp/absl/types')
33 files changed, 0 insertions, 20349 deletions
diff --git a/third_party/abseil_cpp/absl/types/BUILD.bazel b/third_party/abseil_cpp/absl/types/BUILD.bazel deleted file mode 100644 index 83be9360ff99..000000000000 --- a/third_party/abseil_cpp/absl/types/BUILD.bazel +++ /dev/null @@ -1,336 +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. - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_DEFAULT_LINKOPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "any", - hdrs = ["any.h"], - 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/base:raw_logging_internal", - "//absl/container:test_instance_tracker", - "@com_google_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", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "span", - srcs = [ - "internal/span.h", - ], - hdrs = [ - "span.h", - ], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/algorithm", - "//absl/base:core_headers", - "//absl/base:throw_delegate", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "span_test", - size = "small", - srcs = ["span_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":span", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:exception_testing", - "//absl/container:fixed_array", - "//absl/container:inlined_vector", - "//absl/hash:hash_testing", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "optional", - srcs = ["internal/optional.h"], - hdrs = ["optional.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bad_optional_access", - "//absl/base:base_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/utility", - ], -) - -cc_library( - name = "bad_optional_access", - srcs = ["bad_optional_access.cc"], - hdrs = ["bad_optional_access.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:raw_logging_internal", - ], -) - -cc_library( - name = "bad_variant_access", - srcs = ["bad_variant_access.cc"], - hdrs = ["bad_variant_access.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/base:config", - "//absl/base:raw_logging_internal", - ], -) - -cc_test( - name = "optional_test", - size = "small", - srcs = [ - "optional_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":optional", - "//absl/base:config", - "//absl/base:raw_logging_internal", - "//absl/meta:type_traits", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "optional_exception_safety_test", - srcs = [ - "optional_exception_safety_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":optional", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "conformance_testing", - testonly = 1, - hdrs = [ - "internal/conformance_aliases.h", - "internal/conformance_archetype.h", - "internal/conformance_profile.h", - "internal/conformance_testing.h", - "internal/conformance_testing_helpers.h", - "internal/parentheses.h", - "internal/transform_args.h", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - "//absl/algorithm:container", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/utility", - "@com_google_googletest//:gtest", - ], -) - -cc_test( - name = "conformance_testing_test", - size = "small", - srcs = [ - "internal/conformance_testing_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":conformance_testing", - "//absl/meta:type_traits", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "variant", - srcs = ["internal/variant.h"], - hdrs = ["variant.h"], - copts = ABSL_DEFAULT_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":bad_variant_access", - "//absl/base:base_internal", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/meta:type_traits", - "//absl/utility", - ], -) - -cc_test( - name = "variant_test", - size = "small", - srcs = ["variant_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":variant", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/memory", - "//absl/meta:type_traits", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "variant_benchmark", - srcs = [ - "variant_benchmark.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - tags = ["benchmark"], - deps = [ - ":variant", - "//absl/utility", - "@com_github_google_benchmark//:benchmark_main", - ], -) - -cc_test( - name = "variant_exception_safety_test", - size = "small", - srcs = [ - "variant_exception_safety_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":variant", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "//absl/memory", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "compare", - hdrs = ["compare.h"], - copts = ABSL_DEFAULT_COPTS, - deps = [ - "//absl/base:core_headers", - "//absl/meta:type_traits", - ], -) - -cc_test( - name = "compare_test", - size = "small", - srcs = [ - "compare_test.cc", - ], - copts = ABSL_TEST_COPTS, - deps = [ - ":compare", - "//absl/base", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/types/CMakeLists.txt b/third_party/abseil_cpp/absl/types/CMakeLists.txt deleted file mode 100644 index 3f99ad8a4b4d..000000000000 --- a/third_party/abseil_cpp/absl/types/CMakeLists.txt +++ /dev/null @@ -1,373 +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. -# -absl_cc_library( - NAME - any - HDRS - "any.h" - 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 -) - -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::raw_logging_internal - absl::test_instance_tracker - 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 - 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 - gmock_main -) - -absl_cc_library( - NAME - span - HDRS - "span.h" - SRCS - "internal/span.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::algorithm - absl::core_headers - absl::throw_delegate - absl::type_traits - PUBLIC -) - -absl_cc_test( - NAME - span_test - SRCS - "span_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::span - absl::base - absl::config - absl::core_headers - absl::exception_testing - absl::fixed_array - absl::inlined_vector - absl::hash_testing - absl::strings - gmock_main -) - -absl_cc_test( - NAME - span_test_noexceptions - SRCS - "span_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::span - absl::base - absl::config - absl::core_headers - absl::exception_testing - absl::fixed_array - absl::inlined_vector - absl::hash_testing - absl::strings - gmock_main -) - -absl_cc_library( - NAME - optional - HDRS - "optional.h" - SRCS - "internal/optional.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bad_optional_access - absl::base_internal - absl::config - absl::core_headers - absl::memory - absl::type_traits - absl::utility - PUBLIC -) - -absl_cc_library( - NAME - bad_optional_access - HDRS - "bad_optional_access.h" - SRCS - "bad_optional_access.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::raw_logging_internal - PUBLIC -) - -absl_cc_library( - NAME - bad_variant_access - HDRS - "bad_variant_access.h" - SRCS - "bad_variant_access.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::config - absl::raw_logging_internal - PUBLIC -) - -absl_cc_test( - NAME - optional_test - SRCS - "optional_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::optional - absl::config - absl::raw_logging_internal - absl::strings - absl::type_traits - gmock_main -) - -absl_cc_test( - NAME - optional_exception_safety_test - SRCS - "optional_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::optional - absl::config - absl::exception_safety_testing - gmock_main -) - -absl_cc_library( - NAME - conformance_testing - HDRS - "internal/conformance_aliases.h" - "internal/conformance_archetype.h" - "internal/conformance_profile.h" - "internal/conformance_testing.h" - "internal/conformance_testing_helpers.h" - "internal/parentheses.h" - "internal/transform_args.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::algorithm - absl::debugging - absl::type_traits - absl::strings - absl::utility - gmock_main - TESTONLY -) - -absl_cc_test( - NAME - conformance_testing_test - SRCS - "internal/conformance_testing_test.cc" - COPTS - ${ABSL_TEST_COPTS} - ${ABSL_EXCEPTIONS_FLAG} - LINKOPTS - ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} - DEPS - absl::conformance_testing - absl::type_traits - gmock_main -) - -absl_cc_test( - NAME - conformance_testing_test_no_exceptions - SRCS - "internal/conformance_testing_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::conformance_testing - absl::type_traits - gmock_main -) - -absl_cc_library( - NAME - variant - HDRS - "variant.h" - SRCS - "internal/variant.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::bad_variant_access - absl::base_internal - absl::config - absl::core_headers - absl::type_traits - absl::utility - PUBLIC -) - -absl_cc_test( - NAME - variant_test - SRCS - "variant_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::variant - absl::config - absl::core_headers - absl::memory - absl::type_traits - absl::strings - gmock_main -) - -absl_cc_library( - NAME - compare - HDRS - "compare.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::core_headers - absl::type_traits - PUBLIC -) - -absl_cc_test( - NAME - compare_test - SRCS - "compare_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::base - absl::compare - gmock_main -) - -# TODO(cohenjon,zhangxy) Figure out why this test is failing on gcc 4.8 -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) -else() -absl_cc_test( - NAME - variant_exception_safety_test - SRCS - "variant_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::variant - absl::config - absl::exception_safety_testing - absl::memory - gmock_main -) -endif() diff --git a/third_party/abseil_cpp/absl/types/any.h b/third_party/abseil_cpp/absl/types/any.h deleted file mode 100644 index fc5a07469f80..000000000000 --- a/third_party/abseil_cpp/absl/types/any.h +++ /dev/null @@ -1,528 +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. -// -// ----------------------------------------------------------------------------- -// 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`. -#ifndef ABSL_TYPES_ANY_H_ -#define ABSL_TYPES_ANY_H_ - -#include "absl/base/config.h" -#include "absl/utility/utility.h" - -#ifdef ABSL_USES_STD_ANY - -#include <any> // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::any; -using std::any_cast; -using std::bad_any_cast; -using std::make_any; -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/base/macros.h" -#include "absl/meta/type_traits.h" -#include "absl/types/bad_any_cast.h" - -// NOTE: This macro is an implementation detail that is undefined at the bottom -// of the file. It is not intended for expansion directly from user code. -#ifdef ABSL_ANY_DETAIL_HAS_RTTI -#error ABSL_ANY_DETAIL_HAS_RTTI cannot be directly set -#elif !defined(__GNUC__) || defined(__GXX_RTTI) -#define ABSL_ANY_DETAIL_HAS_RTTI 1 -#endif // !defined(__GNUC__) || defined(__GXX_RTTI) - -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) { - 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) { - 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; } - -#if ABSL_ANY_DETAIL_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_ANY_DETAIL_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; -#if ABSL_ANY_DETAIL_HAS_RTTI - virtual const std::type_info& Type() const noexcept = 0; -#endif // ABSL_ANY_DETAIL_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>(); } - -#if ABSL_ANY_DETAIL_HAS_RTTI - const std::type_info& Type() const noexcept final { return typeid(T); } -#endif // ABSL_ANY_DETAIL_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 - -#undef ABSL_ANY_DETAIL_HAS_RTTI - -#endif // ABSL_USES_STD_ANY - -#endif // ABSL_TYPES_ANY_H_ diff --git a/third_party/abseil_cpp/absl/types/any_exception_safety_test.cc b/third_party/abseil_cpp/absl/types/any_exception_safety_test.cc deleted file mode 100644 index 31c1140135f0..000000000000 --- a/third_party/abseil_cpp/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/third_party/abseil_cpp/absl/types/any_test.cc b/third_party/abseil_cpp/absl/types/any_test.cc deleted file mode 100644 index 70e4ba22b12b..000000000000 --- a/third_party/abseil_cpp/absl/types/any_test.cc +++ /dev/null @@ -1,781 +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/base/internal/raw_logging.h" -#include "absl/container/internal/test_instance_tracker.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 - ABSL_RAW_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)); - } - - { - BadCopyable bad; - absl::any target(absl::in_place_type<int>); - ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad)); -#if defined(ABSL_USES_STD_ANY) && defined(__GLIBCXX__) - // libstdc++ std::any::emplace() implementation (as of 7.2) has a bug: if an - // exception is thrown, *this contains a value. -#define ABSL_GLIBCXX_ANY_EMPLACE_EXCEPTION_BUG 1 -#endif -#if defined(ABSL_HAVE_EXCEPTIONS) && \ - !defined(ABSL_GLIBCXX_ANY_EMPLACE_EXCEPTION_BUG) - EXPECT_FALSE(target.has_value()); -#endif - } -} - -} // namespace - -#endif // #if !defined(ABSL_USES_STD_ANY) diff --git a/third_party/abseil_cpp/absl/types/bad_any_cast.cc b/third_party/abseil_cpp/absl/types/bad_any_cast.cc deleted file mode 100644 index b0592cc9bcc5..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_any_cast.cc +++ /dev/null @@ -1,46 +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 - -#endif // ABSL_USES_STD_ANY diff --git a/third_party/abseil_cpp/absl/types/bad_any_cast.h b/third_party/abseil_cpp/absl/types/bad_any_cast.h deleted file mode 100644 index 114cef80cdde..000000000000 --- a/third_party/abseil_cpp/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/third_party/abseil_cpp/absl/types/bad_optional_access.cc b/third_party/abseil_cpp/absl/types/bad_optional_access.cc deleted file mode 100644 index 26aca70d9cff..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_optional_access.cc +++ /dev/null @@ -1,48 +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_optional_access.h" - -#ifndef ABSL_USES_STD_OPTIONAL - -#include <cstdlib> - -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -bad_optional_access::~bad_optional_access() = default; - -const char* bad_optional_access::what() const noexcept { - return "optional has no value"; -} - -namespace optional_internal { - -void throw_bad_optional_access() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw bad_optional_access(); -#else - ABSL_RAW_LOG(FATAL, "Bad optional access"); - abort(); -#endif -} - -} // namespace optional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_OPTIONAL diff --git a/third_party/abseil_cpp/absl/types/bad_optional_access.h b/third_party/abseil_cpp/absl/types/bad_optional_access.h deleted file mode 100644 index a500286adc42..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_optional_access.h +++ /dev/null @@ -1,78 +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_optional_access.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::bad_optional_access` type. - -#ifndef ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_ -#define ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_ - -#include <stdexcept> - -#include "absl/base/config.h" - -#ifdef ABSL_USES_STD_OPTIONAL - -#include <optional> - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_optional_access; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_OPTIONAL - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// bad_optional_access -// ----------------------------------------------------------------------------- -// -// An `absl::bad_optional_access` type is an exception type that is thrown when -// attempting to access an `absl::optional` object that does not contain a -// value. -// -// Example: -// -// absl::optional<int> o; -// -// try { -// int n = o.value(); -// } catch(const absl::bad_optional_access& e) { -// std::cout << "Bad optional access: " << e.what() << '\n'; -// } -class bad_optional_access : public std::exception { - public: - bad_optional_access() = default; - ~bad_optional_access() override; - const char* what() const noexcept override; -}; - -namespace optional_internal { - -// throw delegator -[[noreturn]] void throw_bad_optional_access(); - -} // namespace optional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_OPTIONAL - -#endif // ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_ diff --git a/third_party/abseil_cpp/absl/types/bad_variant_access.cc b/third_party/abseil_cpp/absl/types/bad_variant_access.cc deleted file mode 100644 index 3dc88cc09f23..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_variant_access.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_variant_access.h" - -#ifndef ABSL_USES_STD_VARIANT - -#include <cstdlib> -#include <stdexcept> - -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -////////////////////////// -// [variant.bad.access] // -////////////////////////// - -bad_variant_access::~bad_variant_access() = default; - -const char* bad_variant_access::what() const noexcept { - return "Bad variant access"; -} - -namespace variant_internal { - -void ThrowBadVariantAccess() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw bad_variant_access(); -#else - ABSL_RAW_LOG(FATAL, "Bad variant access"); - abort(); // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn. -#endif -} - -void Rethrow() { -#ifdef ABSL_HAVE_EXCEPTIONS - throw; -#else - ABSL_RAW_LOG(FATAL, - "Internal error in absl::variant implementation. Attempted to " - "rethrow an exception when building with exceptions disabled."); - abort(); // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn. -#endif -} - -} // namespace variant_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_VARIANT diff --git a/third_party/abseil_cpp/absl/types/bad_variant_access.h b/third_party/abseil_cpp/absl/types/bad_variant_access.h deleted file mode 100644 index 095969f91eee..000000000000 --- a/third_party/abseil_cpp/absl/types/bad_variant_access.h +++ /dev/null @@ -1,82 +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_variant_access.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::bad_variant_access` type. - -#ifndef ABSL_TYPES_BAD_VARIANT_ACCESS_H_ -#define ABSL_TYPES_BAD_VARIANT_ACCESS_H_ - -#include <stdexcept> - -#include "absl/base/config.h" - -#ifdef ABSL_USES_STD_VARIANT - -#include <variant> - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_variant_access; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_VARIANT - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// bad_variant_access -// ----------------------------------------------------------------------------- -// -// An `absl::bad_variant_access` type is an exception type that is thrown in -// the following cases: -// -// * Calling `absl::get(absl::variant) with an index or type that does not -// match the currently selected alternative type -// * Calling `absl::visit on an `absl::variant` that is in the -// `variant::valueless_by_exception` state. -// -// Example: -// -// absl::variant<int, std::string> v; -// v = 1; -// try { -// absl::get<std::string>(v); -// } catch(const absl::bad_variant_access& e) { -// std::cout << "Bad variant access: " << e.what() << '\n'; -// } -class bad_variant_access : public std::exception { - public: - bad_variant_access() noexcept = default; - ~bad_variant_access() override; - const char* what() const noexcept override; -}; - -namespace variant_internal { - -[[noreturn]] void ThrowBadVariantAccess(); -[[noreturn]] void Rethrow(); - -} // namespace variant_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_USES_STD_VARIANT - -#endif // ABSL_TYPES_BAD_VARIANT_ACCESS_H_ diff --git a/third_party/abseil_cpp/absl/types/compare.h b/third_party/abseil_cpp/absl/types/compare.h deleted file mode 100644 index 19b076e7f19c..000000000000 --- a/third_party/abseil_cpp/absl/types/compare.h +++ /dev/null @@ -1,600 +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. -// -// ----------------------------------------------------------------------------- -// compare.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::weak_equality`, `absl::strong_equality`, -// `absl::partial_ordering`, `absl::weak_ordering`, and `absl::strong_ordering` -// types for storing the results of three way comparisons. -// -// Example: -// absl::weak_ordering compare(const std::string& a, const std::string& b); -// -// These are C++11 compatible versions of the C++20 corresponding types -// (`std::weak_equality`, etc.) and are designed to be drop-in replacements -// for code compliant with C++20. - -#ifndef ABSL_TYPES_COMPARE_H_ -#define ABSL_TYPES_COMPARE_H_ - -#include <cstddef> -#include <cstdint> -#include <cstdlib> -#include <type_traits> - -#include "absl/base/attributes.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace compare_internal { - -using value_type = int8_t; - -template <typename T> -struct Fail { - static_assert(sizeof(T) < 0, "Only literal `0` is allowed."); -}; - -// We need the NullPtrT template to avoid triggering the modernize-use-nullptr -// ClangTidy warning in user code. -template <typename NullPtrT = std::nullptr_t> -struct OnlyLiteralZero { - constexpr OnlyLiteralZero(NullPtrT) noexcept {} // NOLINT - - // Fails compilation when `nullptr` or integral type arguments other than - // `int` are passed. This constructor doesn't accept `int` because literal `0` - // has type `int`. Literal `0` arguments will be implicitly converted to - // `std::nullptr_t` and accepted by the above constructor, while other `int` - // arguments will fail to be converted and cause compilation failure. - template < - typename T, - typename = typename std::enable_if< - std::is_same<T, std::nullptr_t>::value || - (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type, - typename = typename Fail<T>::type> - OnlyLiteralZero(T); // NOLINT -}; - -enum class eq : value_type { - equal = 0, - equivalent = equal, - nonequal = 1, - nonequivalent = nonequal, -}; - -enum class ord : value_type { less = -1, greater = 1 }; - -enum class ncmp : value_type { unordered = -127 }; - -// Define macros to allow for creation or emulation of C++17 inline variables -// based on whether the feature is supported. Note: we can't use -// ABSL_INTERNAL_INLINE_CONSTEXPR here because the variables here are of -// incomplete types so they need to be defined after the types are complete. -#ifdef __cpp_inline_variables - -// A no-op expansion that can be followed by a semicolon at class level. -#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "") - -#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \ - static const type name - -#define ABSL_COMPARE_INLINE_INIT(type, name, init) \ - inline constexpr type type::name(init) - -#else // __cpp_inline_variables - -#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \ - ABSL_CONST_INIT static const T name - -// A no-op expansion that can be followed by a semicolon at class level. -#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, "") - -#define ABSL_COMPARE_INLINE_INIT(type, name, init) \ - template <typename T> \ - const T compare_internal::type##_base<T>::name(init) - -#endif // __cpp_inline_variables - -// These template base classes allow for defining the values of the constants -// in the header file (for performance) without using inline variables (which -// aren't available in C++11). -template <typename T> -struct weak_equality_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); -}; - -template <typename T> -struct strong_equality_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); - ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequal); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); -}; - -template <typename T> -struct partial_ordering_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(less); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); - ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered); -}; - -template <typename T> -struct weak_ordering_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(less); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); -}; - -template <typename T> -struct strong_ordering_base { - ABSL_COMPARE_INLINE_BASECLASS_DECL(less); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); - ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); - ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); -}; - -} // namespace compare_internal - -class weak_equality - : public compare_internal::weak_equality_base<weak_equality> { - explicit constexpr weak_equality(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::weak_equality_base<weak_equality>; - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, nonequivalent); - - // Comparisons - friend constexpr bool operator==( - weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ == 0; - } - friend constexpr bool operator!=( - weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ != 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - weak_equality v) noexcept { - return 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - weak_equality v) noexcept { - return 0 != v.value_; - } - friend constexpr bool operator==(weak_equality v1, - weak_equality v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(weak_equality v1, - weak_equality v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(weak_equality, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(weak_equality, nonequivalent, - compare_internal::eq::nonequivalent); - -class strong_equality - : public compare_internal::strong_equality_base<strong_equality> { - explicit constexpr strong_equality(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::strong_equality_base<strong_equality>; - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equal); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequal); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequivalent); - - // Conversion - constexpr operator weak_equality() const noexcept { // NOLINT - return value_ == 0 ? weak_equality::equivalent - : weak_equality::nonequivalent; - } - // Comparisons - friend constexpr bool operator==( - strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ == 0; - } - friend constexpr bool operator!=( - strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ != 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - strong_equality v) noexcept { - return 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - strong_equality v) noexcept { - return 0 != v.value_; - } - friend constexpr bool operator==(strong_equality v1, - strong_equality v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(strong_equality v1, - strong_equality v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(strong_equality, equal, compare_internal::eq::equal); -ABSL_COMPARE_INLINE_INIT(strong_equality, nonequal, - compare_internal::eq::nonequal); -ABSL_COMPARE_INLINE_INIT(strong_equality, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(strong_equality, nonequivalent, - compare_internal::eq::nonequivalent); - -class partial_ordering - : public compare_internal::partial_ordering_base<partial_ordering> { - explicit constexpr partial_ordering(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - explicit constexpr partial_ordering(compare_internal::ord v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::partial_ordering_base<partial_ordering>; - - constexpr bool is_ordered() const noexcept { - return value_ != - compare_internal::value_type(compare_internal::ncmp::unordered); - } - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered); - - // Conversion - constexpr operator weak_equality() const noexcept { // NOLINT - return value_ == 0 ? weak_equality::equivalent - : weak_equality::nonequivalent; - } - // Comparisons - friend constexpr bool operator==( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ == 0; - } - friend constexpr bool operator!=( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return !v.is_ordered() || v.value_ != 0; - } - friend constexpr bool operator<( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ < 0; - } - friend constexpr bool operator<=( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ <= 0; - } - friend constexpr bool operator>( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ > 0; - } - friend constexpr bool operator>=( - partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.is_ordered() && v.value_ >= 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return !v.is_ordered() || 0 != v.value_; - } - friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 < v.value_; - } - friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 <= v.value_; - } - friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 > v.value_; - } - friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, - partial_ordering v) noexcept { - return v.is_ordered() && 0 >= v.value_; - } - friend constexpr bool operator==(partial_ordering v1, - partial_ordering v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(partial_ordering v1, - partial_ordering v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less); -ABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(partial_ordering, greater, - compare_internal::ord::greater); -ABSL_COMPARE_INLINE_INIT(partial_ordering, unordered, - compare_internal::ncmp::unordered); - -class weak_ordering - : public compare_internal::weak_ordering_base<weak_ordering> { - explicit constexpr weak_ordering(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - explicit constexpr weak_ordering(compare_internal::ord v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::weak_ordering_base<weak_ordering>; - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater); - - // Conversions - constexpr operator weak_equality() const noexcept { // NOLINT - return value_ == 0 ? weak_equality::equivalent - : weak_equality::nonequivalent; - } - constexpr operator partial_ordering() const noexcept { // NOLINT - return value_ == 0 ? partial_ordering::equivalent - : (value_ < 0 ? partial_ordering::less - : partial_ordering::greater); - } - // Comparisons - friend constexpr bool operator==( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ == 0; - } - friend constexpr bool operator!=( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ != 0; - } - friend constexpr bool operator<( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ < 0; - } - friend constexpr bool operator<=( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ <= 0; - } - friend constexpr bool operator>( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ > 0; - } - friend constexpr bool operator>=( - weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ >= 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 != v.value_; - } - friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 < v.value_; - } - friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 <= v.value_; - } - friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 > v.value_; - } - friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, - weak_ordering v) noexcept { - return 0 >= v.value_; - } - friend constexpr bool operator==(weak_ordering v1, - weak_ordering v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(weak_ordering v1, - weak_ordering v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less); -ABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(weak_ordering, greater, - compare_internal::ord::greater); - -class strong_ordering - : public compare_internal::strong_ordering_base<strong_ordering> { - explicit constexpr strong_ordering(compare_internal::eq v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - explicit constexpr strong_ordering(compare_internal::ord v) noexcept - : value_(static_cast<compare_internal::value_type>(v)) {} - friend struct compare_internal::strong_ordering_base<strong_ordering>; - - public: - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent); - ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater); - - // Conversions - constexpr operator weak_equality() const noexcept { // NOLINT - return value_ == 0 ? weak_equality::equivalent - : weak_equality::nonequivalent; - } - constexpr operator strong_equality() const noexcept { // NOLINT - return value_ == 0 ? strong_equality::equal : strong_equality::nonequal; - } - constexpr operator partial_ordering() const noexcept { // NOLINT - return value_ == 0 ? partial_ordering::equivalent - : (value_ < 0 ? partial_ordering::less - : partial_ordering::greater); - } - constexpr operator weak_ordering() const noexcept { // NOLINT - return value_ == 0 - ? weak_ordering::equivalent - : (value_ < 0 ? weak_ordering::less : weak_ordering::greater); - } - // Comparisons - friend constexpr bool operator==( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ == 0; - } - friend constexpr bool operator!=( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ != 0; - } - friend constexpr bool operator<( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ < 0; - } - friend constexpr bool operator<=( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ <= 0; - } - friend constexpr bool operator>( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ > 0; - } - friend constexpr bool operator>=( - strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { - return v.value_ >= 0; - } - friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 == v.value_; - } - friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 != v.value_; - } - friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 < v.value_; - } - friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 <= v.value_; - } - friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 > v.value_; - } - friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, - strong_ordering v) noexcept { - return 0 >= v.value_; - } - friend constexpr bool operator==(strong_ordering v1, - strong_ordering v2) noexcept { - return v1.value_ == v2.value_; - } - friend constexpr bool operator!=(strong_ordering v1, - strong_ordering v2) noexcept { - return v1.value_ != v2.value_; - } - - private: - compare_internal::value_type value_; -}; -ABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less); -ABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal); -ABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent, - compare_internal::eq::equivalent); -ABSL_COMPARE_INLINE_INIT(strong_ordering, greater, - compare_internal::ord::greater); - -#undef ABSL_COMPARE_INLINE_BASECLASS_DECL -#undef ABSL_COMPARE_INLINE_SUBCLASS_DECL -#undef ABSL_COMPARE_INLINE_INIT - -namespace compare_internal { -// We also provide these comparator adapter functions for internal absl use. - -// Helper functions to do a boolean comparison of two keys given a boolean -// or three-way comparator. -// SFINAE prevents implicit conversions to bool (such as from int). -template <typename Bool, - absl::enable_if_t<std::is_same<bool, Bool>::value, int> = 0> -constexpr bool compare_result_as_less_than(const Bool r) { return r; } -constexpr bool compare_result_as_less_than(const absl::weak_ordering r) { - return r < 0; -} - -template <typename Compare, typename K, typename LK> -constexpr bool do_less_than_comparison(const Compare &compare, const K &x, - const LK &y) { - return compare_result_as_less_than(compare(x, y)); -} - -// Helper functions to do a three-way comparison of two keys given a boolean or -// three-way comparator. -// SFINAE prevents implicit conversions to int (such as from bool). -template <typename Int, - absl::enable_if_t<std::is_same<int, Int>::value, int> = 0> -constexpr absl::weak_ordering compare_result_as_ordering(const Int c) { - return c < 0 ? absl::weak_ordering::less - : c == 0 ? absl::weak_ordering::equivalent - : absl::weak_ordering::greater; -} -constexpr absl::weak_ordering compare_result_as_ordering( - const absl::weak_ordering c) { - return c; -} - -template < - typename Compare, typename K, typename LK, - absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare( - const K &, const LK &)>>::value, - int> = 0> -constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, - const K &x, const LK &y) { - return compare_result_as_ordering(compare(x, y)); -} -template < - typename Compare, typename K, typename LK, - absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare( - const K &, const LK &)>>::value, - int> = 0> -constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, - const K &x, const LK &y) { - return compare(x, y) ? absl::weak_ordering::less - : compare(y, x) ? absl::weak_ordering::greater - : absl::weak_ordering::equivalent; -} - -} // namespace compare_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_COMPARE_H_ diff --git a/third_party/abseil_cpp/absl/types/compare_test.cc b/third_party/abseil_cpp/absl/types/compare_test.cc deleted file mode 100644 index 8095baf9569f..000000000000 --- a/third_party/abseil_cpp/absl/types/compare_test.cc +++ /dev/null @@ -1,389 +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. - -#include "absl/types/compare.h" - -#include "gtest/gtest.h" -#include "absl/base/casts.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -// This is necessary to avoid a bunch of lint warnings suggesting that we use -// EXPECT_EQ/etc., which doesn't work in this case because they convert the `0` -// to an int, which can't be converted to the unspecified zero type. -bool Identity(bool b) { return b; } - -TEST(Compare, WeakEquality) { - EXPECT_TRUE(Identity(weak_equality::equivalent == 0)); - EXPECT_TRUE(Identity(0 == weak_equality::equivalent)); - EXPECT_TRUE(Identity(weak_equality::nonequivalent != 0)); - EXPECT_TRUE(Identity(0 != weak_equality::nonequivalent)); - const weak_equality values[] = {weak_equality::equivalent, - weak_equality::nonequivalent}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } -} - -TEST(Compare, StrongEquality) { - EXPECT_TRUE(Identity(strong_equality::equal == 0)); - EXPECT_TRUE(Identity(0 == strong_equality::equal)); - EXPECT_TRUE(Identity(strong_equality::nonequal != 0)); - EXPECT_TRUE(Identity(0 != strong_equality::nonequal)); - EXPECT_TRUE(Identity(strong_equality::equivalent == 0)); - EXPECT_TRUE(Identity(0 == strong_equality::equivalent)); - EXPECT_TRUE(Identity(strong_equality::nonequivalent != 0)); - EXPECT_TRUE(Identity(0 != strong_equality::nonequivalent)); - const strong_equality values[] = {strong_equality::equal, - strong_equality::nonequal}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } - EXPECT_TRUE(Identity(strong_equality::equivalent == strong_equality::equal)); - EXPECT_TRUE( - Identity(strong_equality::nonequivalent == strong_equality::nonequal)); -} - -TEST(Compare, PartialOrdering) { - EXPECT_TRUE(Identity(partial_ordering::less < 0)); - EXPECT_TRUE(Identity(0 > partial_ordering::less)); - EXPECT_TRUE(Identity(partial_ordering::less <= 0)); - EXPECT_TRUE(Identity(0 >= partial_ordering::less)); - EXPECT_TRUE(Identity(partial_ordering::equivalent == 0)); - EXPECT_TRUE(Identity(0 == partial_ordering::equivalent)); - EXPECT_TRUE(Identity(partial_ordering::greater > 0)); - EXPECT_TRUE(Identity(0 < partial_ordering::greater)); - EXPECT_TRUE(Identity(partial_ordering::greater >= 0)); - EXPECT_TRUE(Identity(0 <= partial_ordering::greater)); - EXPECT_TRUE(Identity(partial_ordering::unordered != 0)); - EXPECT_TRUE(Identity(0 != partial_ordering::unordered)); - EXPECT_FALSE(Identity(partial_ordering::unordered < 0)); - EXPECT_FALSE(Identity(0 < partial_ordering::unordered)); - EXPECT_FALSE(Identity(partial_ordering::unordered <= 0)); - EXPECT_FALSE(Identity(0 <= partial_ordering::unordered)); - EXPECT_FALSE(Identity(partial_ordering::unordered > 0)); - EXPECT_FALSE(Identity(0 > partial_ordering::unordered)); - EXPECT_FALSE(Identity(partial_ordering::unordered >= 0)); - EXPECT_FALSE(Identity(0 >= partial_ordering::unordered)); - const partial_ordering values[] = { - partial_ordering::less, partial_ordering::equivalent, - partial_ordering::greater, partial_ordering::unordered}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } -} - -TEST(Compare, WeakOrdering) { - EXPECT_TRUE(Identity(weak_ordering::less < 0)); - EXPECT_TRUE(Identity(0 > weak_ordering::less)); - EXPECT_TRUE(Identity(weak_ordering::less <= 0)); - EXPECT_TRUE(Identity(0 >= weak_ordering::less)); - EXPECT_TRUE(Identity(weak_ordering::equivalent == 0)); - EXPECT_TRUE(Identity(0 == weak_ordering::equivalent)); - EXPECT_TRUE(Identity(weak_ordering::greater > 0)); - EXPECT_TRUE(Identity(0 < weak_ordering::greater)); - EXPECT_TRUE(Identity(weak_ordering::greater >= 0)); - EXPECT_TRUE(Identity(0 <= weak_ordering::greater)); - const weak_ordering values[] = { - weak_ordering::less, weak_ordering::equivalent, weak_ordering::greater}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } -} - -TEST(Compare, StrongOrdering) { - EXPECT_TRUE(Identity(strong_ordering::less < 0)); - EXPECT_TRUE(Identity(0 > strong_ordering::less)); - EXPECT_TRUE(Identity(strong_ordering::less <= 0)); - EXPECT_TRUE(Identity(0 >= strong_ordering::less)); - EXPECT_TRUE(Identity(strong_ordering::equal == 0)); - EXPECT_TRUE(Identity(0 == strong_ordering::equal)); - EXPECT_TRUE(Identity(strong_ordering::equivalent == 0)); - EXPECT_TRUE(Identity(0 == strong_ordering::equivalent)); - EXPECT_TRUE(Identity(strong_ordering::greater > 0)); - EXPECT_TRUE(Identity(0 < strong_ordering::greater)); - EXPECT_TRUE(Identity(strong_ordering::greater >= 0)); - EXPECT_TRUE(Identity(0 <= strong_ordering::greater)); - const strong_ordering values[] = { - strong_ordering::less, strong_ordering::equal, strong_ordering::greater}; - for (const auto& lhs : values) { - for (const auto& rhs : values) { - const bool are_equal = &lhs == &rhs; - EXPECT_EQ(lhs == rhs, are_equal); - EXPECT_EQ(lhs != rhs, !are_equal); - } - } - EXPECT_TRUE(Identity(strong_ordering::equivalent == strong_ordering::equal)); -} - -TEST(Compare, Conversions) { - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_equality::equal) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_equality::nonequal) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_equality::equivalent) == 0)); - EXPECT_TRUE(Identity( - implicit_cast<weak_equality>(strong_equality::nonequivalent) != 0)); - - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(partial_ordering::less) != 0)); - EXPECT_TRUE(Identity( - implicit_cast<weak_equality>(partial_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(partial_ordering::greater) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(partial_ordering::unordered) != 0)); - - EXPECT_TRUE(implicit_cast<weak_equality>(weak_ordering::less) != 0); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(weak_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(weak_ordering::greater) != 0)); - - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::less) < 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::less) <= 0)); - EXPECT_TRUE(Identity( - implicit_cast<partial_ordering>(weak_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::greater) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::greater) > 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(weak_ordering::greater) >= 0)); - - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_ordering::equal) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_equality>(strong_ordering::greater) != 0)); - - EXPECT_TRUE( - Identity(implicit_cast<strong_equality>(strong_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<strong_equality>(strong_ordering::equal) == 0)); - EXPECT_TRUE(Identity( - implicit_cast<strong_equality>(strong_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<strong_equality>(strong_ordering::greater) != 0)); - - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::less) < 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::less) <= 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::equal) == 0)); - EXPECT_TRUE(Identity( - implicit_cast<partial_ordering>(strong_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::greater) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::greater) > 0)); - EXPECT_TRUE( - Identity(implicit_cast<partial_ordering>(strong_ordering::greater) >= 0)); - - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::less) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::less) < 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::less) <= 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::equal) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::equivalent) == 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::greater) != 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::greater) > 0)); - EXPECT_TRUE( - Identity(implicit_cast<weak_ordering>(strong_ordering::greater) >= 0)); -} - -struct WeakOrderingLess { - template <typename T> - absl::weak_ordering operator()(const T& a, const T& b) const { - return a < b ? absl::weak_ordering::less - : a == b ? absl::weak_ordering::equivalent - : absl::weak_ordering::greater; - } -}; - -TEST(CompareResultAsLessThan, SanityTest) { - EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(false)); - EXPECT_TRUE(absl::compare_internal::compare_result_as_less_than(true)); - - EXPECT_TRUE( - absl::compare_internal::compare_result_as_less_than(weak_ordering::less)); - EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than( - weak_ordering::equivalent)); - EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than( - weak_ordering::greater)); -} - -TEST(DoLessThanComparison, SanityTest) { - std::less<int> less; - WeakOrderingLess weak; - - EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(less, -1, 0)); - EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(weak, -1, 0)); - - EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 10)); - EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 10)); - - EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 5)); - EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 5)); -} - -TEST(CompareResultAsOrdering, SanityTest) { - EXPECT_TRUE( - Identity(absl::compare_internal::compare_result_as_ordering(-1) < 0)); - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(-1) == 0)); - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0)); - EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::less) < 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::less) == 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::less) > 0)); - - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(0) < 0)); - EXPECT_TRUE( - Identity(absl::compare_internal::compare_result_as_ordering(0) == 0)); - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(0) > 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::equivalent) < 0)); - EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::equivalent) == 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::equivalent) > 0)); - - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(1) < 0)); - EXPECT_FALSE( - Identity(absl::compare_internal::compare_result_as_ordering(1) == 0)); - EXPECT_TRUE( - Identity(absl::compare_internal::compare_result_as_ordering(1) > 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::greater) < 0)); - EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::greater) == 0)); - EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering( - weak_ordering::greater) > 0)); -} - -TEST(DoThreeWayComparison, SanityTest) { - std::less<int> less; - WeakOrderingLess weak; - - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(less, -1, 0) < 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, -1, 0) == 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, -1, 0) > 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(weak, -1, 0) < 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, -1, 0) == 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, -1, 0) > 0)); - - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 10) < 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 10) == 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 10) > 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 10) < 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 10) == 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 10) > 0)); - - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 5) < 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 5) == 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(less, 10, 5) > 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 5) < 0)); - EXPECT_FALSE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 5) == 0)); - EXPECT_TRUE(Identity( - absl::compare_internal::do_three_way_comparison(weak, 10, 5) > 0)); -} - -#ifdef __cpp_inline_variables -TEST(Compare, StaticAsserts) { - static_assert(weak_equality::equivalent == 0, ""); - static_assert(weak_equality::nonequivalent != 0, ""); - - static_assert(strong_equality::equal == 0, ""); - static_assert(strong_equality::nonequal != 0, ""); - static_assert(strong_equality::equivalent == 0, ""); - static_assert(strong_equality::nonequivalent != 0, ""); - - static_assert(partial_ordering::less < 0, ""); - static_assert(partial_ordering::equivalent == 0, ""); - static_assert(partial_ordering::greater > 0, ""); - static_assert(partial_ordering::unordered != 0, ""); - - static_assert(weak_ordering::less < 0, ""); - static_assert(weak_ordering::equivalent == 0, ""); - static_assert(weak_ordering::greater > 0, ""); - - static_assert(strong_ordering::less < 0, ""); - static_assert(strong_ordering::equal == 0, ""); - static_assert(strong_ordering::equivalent == 0, ""); - static_assert(strong_ordering::greater > 0, ""); -} -#endif // __cpp_inline_variables - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h b/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h deleted file mode 100644 index 0cc6884e309e..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_aliases.h +++ /dev/null @@ -1,447 +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. -// -// ----------------------------------------------------------------------------- -// regularity_aliases.h -// ----------------------------------------------------------------------------- -// -// This file contains type aliases of common ConformanceProfiles and Archetypes -// so that they can be directly used by name without creating them from scratch. - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ - -#include "absl/types/internal/conformance_archetype.h" -#include "absl/types/internal/conformance_profile.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Creates both a Profile and a corresponding Archetype with root name "name". -#define ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(name, ...) \ - struct name##Profile : __VA_ARGS__ {}; \ - \ - using name##Archetype = ::absl::types_internal::Archetype<name##Profile>; \ - \ - template <class AbslInternalProfileTag> \ - using name##Archetype##_ = ::absl::types_internal::Archetype< \ - ::absl::types_internal::StrongProfileTypedef<name##Profile, \ - AbslInternalProfileTag>> - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialDefaultConstructor, - ConformanceProfile<default_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowDefaultConstructor, - ConformanceProfile<default_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasDefaultConstructor, ConformanceProfile<default_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialMoveConstructor, ConformanceProfile<default_constructible::maybe, - move_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowMoveConstructor, ConformanceProfile<default_constructible::maybe, - move_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasMoveConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasCopyConstructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasMoveAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasCopyAssign, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasTrivialDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::trivial>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasDestructor, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowEquality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasEquality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowInequality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, - inequality_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasInequality, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowLessThan, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasLessThan, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowLessEqual, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::maybe, - less_equal_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasLessEqual, - ConformanceProfile<default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, - equality_comparable::maybe, inequality_comparable::maybe, - less_than_comparable::maybe, - less_equal_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowGreaterEqual, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasGreaterEqual, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowGreaterThan, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasGreaterThan, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasNothrowSwap, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::nothrow>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasSwap, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::yes>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HasStdHashSpecialization, - ConformanceProfile< - default_constructible::maybe, move_constructible::maybe, - copy_constructible::maybe, move_assignable::maybe, - copy_assignable::maybe, destructible::maybe, equality_comparable::maybe, - inequality_comparable::maybe, less_than_comparable::maybe, - less_equal_comparable::maybe, greater_equal_comparable::maybe, - greater_than_comparable::maybe, swappable::maybe, hashable::yes>); - -//////////////////////////////////////////////////////////////////////////////// -//// The remaining aliases are combinations of the previous aliases. //// -//////////////////////////////////////////////////////////////////////////////// - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Equatable, CombineProfiles<HasEqualityProfile, HasInequalityProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Comparable, - CombineProfiles<EquatableProfile, HasLessThanProfile, HasLessEqualProfile, - HasGreaterEqualProfile, HasGreaterThanProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowEquatable, - CombineProfiles<HasNothrowEqualityProfile, HasNothrowInequalityProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowComparable, - CombineProfiles<NothrowEquatableProfile, HasNothrowLessThanProfile, - HasNothrowLessEqualProfile, HasNothrowGreaterEqualProfile, - HasNothrowGreaterThanProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - Value, - CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile, - HasNothrowMoveAssignProfile, HasCopyAssignProfile, - HasNothrowDestructorProfile, HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableValue, CombineProfiles<EquatableProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableValue, CombineProfiles<ComparableProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleValue, - CombineProfiles<HasDefaultConstructorProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowMoveConstructible, CombineProfiles<HasNothrowMoveConstructorProfile, - HasNothrowDestructorProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableNothrowMoveConstructible, - CombineProfiles<EquatableProfile, NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableNothrowMoveConstructible, - CombineProfiles<ComparableProfile, NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleNothrowMoveConstructible, - CombineProfiles<HasDefaultConstructorProfile, - NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - CopyConstructible, - CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile, - HasNothrowDestructorProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableCopyConstructible, - CombineProfiles<EquatableProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableCopyConstructible, - CombineProfiles<ComparableProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleCopyConstructible, - CombineProfiles<HasDefaultConstructorProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - NothrowMovable, - CombineProfiles<HasNothrowMoveConstructorProfile, - HasNothrowMoveAssignProfile, HasNothrowDestructorProfile, - HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - EquatableNothrowMovable, - CombineProfiles<EquatableProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableNothrowMovable, - CombineProfiles<ComparableProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - DefaultConstructibleNothrowMovable, - CombineProfiles<HasDefaultConstructorProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - TrivialSpecialMemberFunctions, - CombineProfiles<HasTrivialDefaultConstructorProfile, - HasTrivialMoveConstructorProfile, - HasTrivialCopyConstructorProfile, - HasTrivialMoveAssignProfile, HasTrivialCopyAssignProfile, - HasTrivialDestructorProfile, HasNothrowSwapProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - TriviallyComplete, - CombineProfiles<TrivialSpecialMemberFunctionsProfile, ComparableProfile, - HasStdHashSpecializationProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableNothrowMoveConstructible, - CombineProfiles<HasStdHashSpecializationProfile, - NothrowMoveConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableCopyConstructible, - CombineProfiles<HasStdHashSpecializationProfile, CopyConstructibleProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableNothrowMovable, - CombineProfiles<HasStdHashSpecializationProfile, NothrowMovableProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - HashableValue, - CombineProfiles<HasStdHashSpecializationProfile, ValueProfile>); - -ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS( - ComparableHashableValue, - CombineProfiles<HashableValueProfile, ComparableProfile>); - -// The "preferred" profiles that we support in Abseil. -template <template <class...> class Receiver> -using ExpandBasicProfiles = - Receiver<NothrowMoveConstructibleProfile, CopyConstructibleProfile, - NothrowMovableProfile, ValueProfile>; - -// The basic profiles except that they are also all Equatable. -template <template <class...> class Receiver> -using ExpandBasicEquatableProfiles = - Receiver<EquatableNothrowMoveConstructibleProfile, - EquatableCopyConstructibleProfile, EquatableNothrowMovableProfile, - EquatableValueProfile>; - -// The basic profiles except that they are also all Comparable. -template <template <class...> class Receiver> -using ExpandBasicComparableProfiles = - Receiver<ComparableNothrowMoveConstructibleProfile, - ComparableCopyConstructibleProfile, - ComparableNothrowMovableProfile, ComparableValueProfile>; - -// The basic profiles except that they are also all Hashable. -template <template <class...> class Receiver> -using ExpandBasicHashableProfiles = - Receiver<HashableNothrowMoveConstructibleProfile, - HashableCopyConstructibleProfile, HashableNothrowMovableProfile, - HashableValueProfile>; - -// The basic profiles except that they are also all DefaultConstructible. -template <template <class...> class Receiver> -using ExpandBasicDefaultConstructibleProfiles = - Receiver<DefaultConstructibleNothrowMoveConstructibleProfile, - DefaultConstructibleCopyConstructibleProfile, - DefaultConstructibleNothrowMovableProfile, - DefaultConstructibleValueProfile>; - -// The type profiles that we support in Abseil (all of the previous lists). -template <template <class...> class Receiver> -using ExpandSupportedProfiles = Receiver< - NothrowMoveConstructibleProfile, CopyConstructibleProfile, - NothrowMovableProfile, ValueProfile, - EquatableNothrowMoveConstructibleProfile, EquatableCopyConstructibleProfile, - EquatableNothrowMovableProfile, EquatableValueProfile, - ComparableNothrowMoveConstructibleProfile, - ComparableCopyConstructibleProfile, ComparableNothrowMovableProfile, - ComparableValueProfile, DefaultConstructibleNothrowMoveConstructibleProfile, - DefaultConstructibleCopyConstructibleProfile, - DefaultConstructibleNothrowMovableProfile, DefaultConstructibleValueProfile, - HashableNothrowMoveConstructibleProfile, HashableCopyConstructibleProfile, - HashableNothrowMovableProfile, HashableValueProfile>; - -// TODO(calabrese) Include types that have throwing move constructors, since in -// practice we still need to support them because of standard library types with -// (potentially) non-noexcept moves. - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h b/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h deleted file mode 100644 index 2349e0f72635..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_archetype.h +++ /dev/null @@ -1,978 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// conformance_archetype.h -// ----------------------------------------------------------------------------- -// -// This file contains a facility for generating "archetypes" of out of -// "Conformance Profiles" (see "conformance_profiles.h" for more information -// about Conformance Profiles). An archetype is a type that aims to support the -// bare minimum requirements of a given Conformance Profile. For instance, an -// archetype that corresponds to an ImmutableProfile has exactly a nothrow -// move-constructor, a potentially-throwing copy constructor, a nothrow -// destructor, with all other special-member-functions deleted. These archetypes -// are useful for testing to make sure that templates are able to work with the -// kinds of types that they claim to support (i.e. that they do not accidentally -// under-constrain), -// -// The main type template in this file is the Archetype template, which takes -// a Conformance Profile as a template argument and its instantiations are a -// minimum-conforming model of that profile. - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ - -#include <cstddef> -#include <functional> -#include <type_traits> -#include <utility> - -#include "absl/meta/type_traits.h" -#include "absl/types/internal/conformance_profile.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// A minimum-conforming implementation of a type with properties specified in -// `Prof`, where `Prof` is a valid Conformance Profile. -template <class Prof, class /*Enabler*/ = void> -class Archetype; - -// Given an Archetype, obtain the properties of the profile associated with that -// archetype. -template <class Archetype> -struct PropertiesOfArchetype; - -template <class Prof> -struct PropertiesOfArchetype<Archetype<Prof>> { - using type = PropertiesOfT<Prof>; -}; - -template <class Archetype> -using PropertiesOfArchetypeT = typename PropertiesOfArchetype<Archetype>::type; - -// A metafunction to determine if a type is an `Archetype`. -template <class T> -struct IsArchetype : std::false_type {}; - -template <class Prof> -struct IsArchetype<Archetype<Prof>> : std::true_type {}; - -// A constructor tag type used when creating an Archetype with internal state. -struct MakeArchetypeState {}; - -// Data stored within an archetype that is copied/compared/hashed when the -// corresponding operations are used. -using ArchetypeState = std::size_t; - -//////////////////////////////////////////////////////////////////////////////// -// This section of the file defines a chain of base classes for Archetype, // -// where each base defines a specific special member function with the // -// appropriate properties (deleted, noexcept(false), noexcept, or trivial). // -//////////////////////////////////////////////////////////////////////////////// - -// The bottom-most base, which contains the state and the default constructor. -template <default_constructible DefaultConstructibleValue> -struct ArchetypeStateBase { - static_assert(DefaultConstructibleValue == default_constructible::yes || - DefaultConstructibleValue == default_constructible::nothrow, - ""); - - ArchetypeStateBase() noexcept( - DefaultConstructibleValue == - default_constructible:: - nothrow) /*Vacuous archetype_state initialization*/ {} - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -template <> -struct ArchetypeStateBase<default_constructible::maybe> { - explicit ArchetypeStateBase() = delete; - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -template <> -struct ArchetypeStateBase<default_constructible::trivial> { - ArchetypeStateBase() = default; - explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept - : archetype_state(state) {} - - ArchetypeState archetype_state; -}; - -// The move-constructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeMoveConstructor - : ArchetypeStateBase<DefaultConstructibleValue> { - static_assert(MoveConstructibleValue == move_constructible::yes || - MoveConstructibleValue == move_constructible::nothrow, - ""); - - explicit ArchetypeMoveConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveConstructor() = default; - ArchetypeMoveConstructor(ArchetypeMoveConstructor&& other) noexcept( - MoveConstructibleValue == move_constructible::nothrow) - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - other.archetype_state) {} - ArchetypeMoveConstructor(const ArchetypeMoveConstructor&) = default; - ArchetypeMoveConstructor& operator=(ArchetypeMoveConstructor&&) = default; - ArchetypeMoveConstructor& operator=(const ArchetypeMoveConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue> -struct ArchetypeMoveConstructor<DefaultConstructibleValue, - move_constructible::trivial> - : ArchetypeStateBase<DefaultConstructibleValue> { - explicit ArchetypeMoveConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveConstructor() = default; -}; - -// The copy-constructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue> -struct ArchetypeCopyConstructor - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - static_assert(CopyConstructibleValue == copy_constructible::yes || - CopyConstructibleValue == copy_constructible::nothrow, - ""); - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; - ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor(const ArchetypeCopyConstructor& other) noexcept( - CopyConstructibleValue == copy_constructible::nothrow) - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>( - MakeArchetypeState(), other.archetype_state) {} - ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - copy_constructible::maybe> - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; - ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor(const ArchetypeCopyConstructor&) = delete; - ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default; - ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) = - default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue> -struct ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - copy_constructible::trivial> - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue> { - explicit ArchetypeCopyConstructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveConstructor<DefaultConstructibleValue, - MoveConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeCopyConstructor() = default; -}; - -// The move-assign base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeMoveAssign - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, CopyConstructibleValue> { - static_assert(MoveAssignableValue == move_assignable::yes || - MoveAssignableValue == move_assignable::nothrow, - ""); - explicit ArchetypeMoveAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - CopyConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveAssign() = default; - ArchetypeMoveAssign(ArchetypeMoveAssign&&) = default; - ArchetypeMoveAssign(const ArchetypeMoveAssign&) = default; - ArchetypeMoveAssign& operator=(ArchetypeMoveAssign&& other) noexcept( - MoveAssignableValue == move_assignable::nothrow) { - this->archetype_state = other.archetype_state; - return *this; - } - - ArchetypeMoveAssign& operator=(const ArchetypeMoveAssign&) = default; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue> -struct ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, move_assignable::trivial> - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, CopyConstructibleValue> { - explicit ArchetypeMoveAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyConstructor<DefaultConstructibleValue, - MoveConstructibleValue, - CopyConstructibleValue>(MakeArchetypeState(), - state) {} - - ArchetypeMoveAssign() = default; -}; - -// The copy-assign base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue> -struct ArchetypeCopyAssign - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - static_assert(CopyAssignableValue == copy_assignable::yes || - CopyAssignableValue == copy_assignable::nothrow, - ""); - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; - ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default; - ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default; - - ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign& other) noexcept( - CopyAssignableValue == copy_assignable::nothrow) { - this->archetype_state = other.archetype_state; - return *this; - } -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - copy_assignable::maybe> - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; - ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default; - ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default; - ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign&) = delete; -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue> -struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - copy_assignable::trivial> - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue> { - explicit ArchetypeCopyAssign(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue>( - MakeArchetypeState(), state) {} - - ArchetypeCopyAssign() = default; -}; - -// The destructor base -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue, destructible DestructibleValue> -struct ArchetypeDestructor - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue> { - static_assert(DestructibleValue == destructible::yes || - DestructibleValue == destructible::nothrow, - ""); - - explicit ArchetypeDestructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue>(MakeArchetypeState(), state) {} - - ArchetypeDestructor() = default; - ArchetypeDestructor(ArchetypeDestructor&&) = default; - ArchetypeDestructor(const ArchetypeDestructor&) = default; - ArchetypeDestructor& operator=(ArchetypeDestructor&&) = default; - ArchetypeDestructor& operator=(const ArchetypeDestructor&) = default; - ~ArchetypeDestructor() noexcept(DestructibleValue == destructible::nothrow) {} -}; - -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue> -struct ArchetypeDestructor<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue, destructible::trivial> - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue> { - explicit ArchetypeDestructor(MakeArchetypeState, - ArchetypeState state) noexcept - : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue, - CopyConstructibleValue, MoveAssignableValue, - CopyAssignableValue>(MakeArchetypeState(), state) {} - - ArchetypeDestructor() = default; -}; - -// An alias to the top of the chain of bases for special-member functions. -// NOTE: move_constructible::maybe, move_assignable::maybe, and -// destructible::maybe are handled in the top-level type by way of SFINAE. -// Because of this, we never instantiate the base classes with -// move_constructible::maybe, move_assignable::maybe, or destructible::maybe so -// that we minimize the number of different possible type-template -// instantiations. -template <default_constructible DefaultConstructibleValue, - move_constructible MoveConstructibleValue, - copy_constructible CopyConstructibleValue, - move_assignable MoveAssignableValue, - copy_assignable CopyAssignableValue, destructible DestructibleValue> -using ArchetypeSpecialMembersBase = ArchetypeDestructor< - DefaultConstructibleValue, - MoveConstructibleValue != move_constructible::maybe - ? MoveConstructibleValue - : move_constructible::nothrow, - CopyConstructibleValue, - MoveAssignableValue != move_assignable::maybe ? MoveAssignableValue - : move_assignable::nothrow, - CopyAssignableValue, - DestructibleValue != destructible::maybe ? DestructibleValue - : destructible::nothrow>; - -// A function that is used to create an archetype with some associated state. -template <class Arch> -Arch MakeArchetype(ArchetypeState state) noexcept { - static_assert(IsArchetype<Arch>::value, - "The explicit template argument to MakeArchetype is required " - "to be an Archetype."); - return Arch(MakeArchetypeState(), state); -} - -// This is used to conditionally delete "copy" and "move" constructors in a way -// that is consistent with what the ConformanceProfile requires and that also -// strictly enforces the arguments to the copy/move to not come from implicit -// conversions when dealing with the Archetype. -template <class Prof, class T> -constexpr bool ShouldDeleteConstructor() { - return !((PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - std::is_same<T, Archetype<Prof>>::value) || - (PropertiesOfT<Prof>::copy_constructible_support != - copy_constructible::maybe && - (std::is_same<T, const Archetype<Prof>&>::value || - std::is_same<T, Archetype<Prof>&>::value || - std::is_same<T, const Archetype<Prof>>::value))); -} - -// This is used to conditionally delete "copy" and "move" assigns in a way -// that is consistent with what the ConformanceProfile requires and that also -// strictly enforces the arguments to the copy/move to not come from implicit -// conversions when dealing with the Archetype. -template <class Prof, class T> -constexpr bool ShouldDeleteAssign() { - return !( - (PropertiesOfT<Prof>::move_assignable_support != move_assignable::maybe && - std::is_same<T, Archetype<Prof>>::value) || - (PropertiesOfT<Prof>::copy_assignable_support != copy_assignable::maybe && - (std::is_same<T, const Archetype<Prof>&>::value || - std::is_same<T, Archetype<Prof>&>::value || - std::is_same<T, const Archetype<Prof>>::value))); -} - -// TODO(calabrese) Inherit from a chain of secondary bases to pull in the -// associated functions of other concepts. -template <class Prof, class Enabler> -class Archetype : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - static_assert(std::is_same<Enabler, void>::value, - "An explicit type must not be passed as the second template " - "argument to 'Archetype`."); - - // The cases mentioned in these static_asserts are expected to be handled in - // the partial template specializations of Archetype that follow this - // definition. - static_assert(PropertiesOfT<Prof>::destructible_support != - destructible::maybe, - ""); - static_assert(PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe || - PropertiesOfT<Prof>::copy_constructible_support == - copy_constructible::maybe, - ""); - static_assert(PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe || - PropertiesOfT<Prof>::copy_assignable_support == - copy_assignable::maybe, - ""); - - public: - Archetype() = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = default; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support != - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = default; - Archetype& operator=(const Archetype&) = default; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support != - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = default; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support == - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = delete; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -template <class Prof> -class Archetype<Prof, typename std::enable_if< - PropertiesOfT<Prof>::move_constructible_support == - move_constructible::maybe && - PropertiesOfT<Prof>::move_assignable_support != - move_assignable::maybe && - PropertiesOfT<Prof>::destructible_support == - destructible::maybe>::type> - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support> { - public: - Archetype() = default; - Archetype(Archetype&&) = delete; - Archetype(const Archetype&) = default; - Archetype& operator=(Archetype&&) = default; - Archetype& operator=(const Archetype&) = default; - ~Archetype() = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteConstructor<Prof, T>()>::type* = nullptr> - Archetype(T&&) = delete; - - // Disallow moves when requested, and disallow implicit conversions. - template <class T, typename std::enable_if< - ShouldDeleteAssign<Prof, T>()>::type* = nullptr> - Archetype& operator=(T&&) = delete; - - using ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>::archetype_state; - - private: - explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept - : ArchetypeSpecialMembersBase< - PropertiesOfT<Prof>::default_constructible_support, - PropertiesOfT<Prof>::move_constructible_support, - PropertiesOfT<Prof>::copy_constructible_support, - PropertiesOfT<Prof>::move_assignable_support, - PropertiesOfT<Prof>::copy_assignable_support, - PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(), - state) {} - - friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept; -}; - -// Explicitly deleted swap for Archetype if the profile does not require swap. -// It is important to delete it rather than simply leave it out so that the -// "using std::swap;" idiom will result in this deleted overload being picked. -template <class Prof, - absl::enable_if_t<!PropertiesOfT<Prof>::is_swappable, int> = 0> -void swap(Archetype<Prof>&, Archetype<Prof>&) = delete; // NOLINT - -// A conditionally-noexcept swap implementation for Archetype when the profile -// supports swap. -template <class Prof, - absl::enable_if_t<PropertiesOfT<Prof>::is_swappable, int> = 0> -void swap(Archetype<Prof>& lhs, Archetype<Prof>& rhs) // NOLINT - noexcept(PropertiesOfT<Prof>::swappable_support != swappable::yes) { - std::swap(lhs.archetype_state, rhs.archetype_state); -} - -// A convertible-to-bool type that is used as the return type of comparison -// operators since the standard doesn't always require exactly bool. -struct NothrowBool { - explicit NothrowBool() = delete; - ~NothrowBool() = default; - - // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed - // elision makes it not required when returning from a function. - // NothrowBool(NothrowBool const&) = delete; - - NothrowBool& operator=(NothrowBool const&) = delete; - - explicit operator bool() const noexcept { return value; } - - static NothrowBool make(bool const value) noexcept { - return NothrowBool(value); - } - - private: - explicit NothrowBool(bool const value) noexcept : value(value) {} - - bool value; -}; - -// A convertible-to-bool type that is used as the return type of comparison -// operators since the standard doesn't always require exactly bool. -// Note: ExceptionalBool has a conversion operator that is not noexcept, so -// that even when a comparison operator is noexcept, that operation may still -// potentially throw when converted to bool. -struct ExceptionalBool { - explicit ExceptionalBool() = delete; - ~ExceptionalBool() = default; - - // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed - // elision makes it not required when returning from a function. - // ExceptionalBool(ExceptionalBool const&) = delete; - - ExceptionalBool& operator=(ExceptionalBool const&) = delete; - - explicit operator bool() const { return value; } // NOLINT - - static ExceptionalBool make(bool const value) noexcept { - return ExceptionalBool(value); - } - - private: - explicit ExceptionalBool(bool const value) noexcept : value(value) {} - - bool value; -}; - -// The following macro is only used as a helper in this file to stamp out -// comparison operator definitions. It is undefined after usage. -// -// NOTE: Non-nothrow operators throw via their result's conversion to bool even -// though the operation itself is noexcept. -#define ABSL_TYPES_INTERNAL_OP(enum_name, op) \ - template <class Prof> \ - absl::enable_if_t<!PropertiesOfT<Prof>::is_##enum_name, bool> operator op( \ - const Archetype<Prof>&, const Archetype<Prof>&) = delete; \ - \ - template <class Prof> \ - typename absl::enable_if_t< \ - PropertiesOfT<Prof>::is_##enum_name, \ - std::conditional<PropertiesOfT<Prof>::enum_name##_support == \ - enum_name::nothrow, \ - NothrowBool, ExceptionalBool>>::type \ - operator op(const Archetype<Prof>& lhs, \ - const Archetype<Prof>& rhs) noexcept { \ - return absl::conditional_t< \ - PropertiesOfT<Prof>::enum_name##_support == enum_name::nothrow, \ - NothrowBool, ExceptionalBool>::make(lhs.archetype_state op \ - rhs.archetype_state); \ - } - -ABSL_TYPES_INTERNAL_OP(equality_comparable, ==); -ABSL_TYPES_INTERNAL_OP(inequality_comparable, !=); -ABSL_TYPES_INTERNAL_OP(less_than_comparable, <); -ABSL_TYPES_INTERNAL_OP(less_equal_comparable, <=); -ABSL_TYPES_INTERNAL_OP(greater_equal_comparable, >=); -ABSL_TYPES_INTERNAL_OP(greater_than_comparable, >); - -#undef ABSL_TYPES_INTERNAL_OP - -// Base class for std::hash specializations when an Archetype doesn't support -// hashing. -struct PoisonedHash { - PoisonedHash() = delete; - PoisonedHash(const PoisonedHash&) = delete; - PoisonedHash& operator=(const PoisonedHash&) = delete; -}; - -// Base class for std::hash specializations when an Archetype supports hashing. -template <class Prof> -struct EnabledHash { - using argument_type = Archetype<Prof>; - using result_type = std::size_t; - result_type operator()(const argument_type& arg) const { - return std::hash<ArchetypeState>()(arg.archetype_state); - } -}; - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -namespace std { - -template <class Prof> // NOLINT -struct hash<::absl::types_internal::Archetype<Prof>> - : conditional<::absl::types_internal::PropertiesOfT<Prof>::is_hashable, - ::absl::types_internal::EnabledHash<Prof>, - ::absl::types_internal::PoisonedHash>::type {}; - -} // namespace std - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_profile.h b/third_party/abseil_cpp/absl/types/internal/conformance_profile.h deleted file mode 100644 index cf64ff4fcd1e..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_profile.h +++ /dev/null @@ -1,931 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// conformance_profiles.h -// ----------------------------------------------------------------------------- -// -// This file contains templates for representing "Regularity Profiles" and -// concisely-named versions of commonly used Regularity Profiles. -// -// A Regularity Profile is a compile-time description of the types of operations -// that a given type supports, along with properties of those operations when -// they do exist. For instance, a Regularity Profile may describe a type that -// has a move-constructor that is noexcept and a copy constructor that is not -// noexcept. This description can then be examined and passed around to other -// templates for the purposes of asserting expectations on user-defined types -// via a series trait checks, or for determining what kinds of run-time tests -// are able to be performed. -// -// Regularity Profiles are also used when creating "archetypes," which are -// minimum-conforming types that meet all of the requirements of a given -// Regularity Profile. For more information regarding archetypes, see -// "conformance_archetypes.h". - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ - -#include <set> -#include <type_traits> -#include <utility> -#include <vector> - -#include "gtest/gtest.h" -#include "absl/algorithm/container.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/ascii.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/types/internal/conformance_testing_helpers.h" -#include "absl/utility/utility.h" - -// TODO(calabrese) Add support for extending profiles. - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Converts an enum to its underlying integral value. -template <typename Enum> -constexpr absl::underlying_type_t<Enum> UnderlyingValue(Enum value) { - return static_cast<absl::underlying_type_t<Enum>>(value); -} - -// A tag type used in place of a matcher when checking that an assertion result -// does not actually contain any errors. -struct NoError {}; - -// ----------------------------------------------------------------------------- -// ConformanceErrors -// ----------------------------------------------------------------------------- -class ConformanceErrors { - public: - // Setup the error reporting mechanism by seeding it with the name of the type - // that is being tested. - explicit ConformanceErrors(std::string type_name) - : assertion_result_(false), type_name_(std::move(type_name)) { - assertion_result_ << "\n\n" - "Assuming the following type alias:\n" - "\n" - " using _T = " - << type_name_ << ";\n\n"; - outputDivider(); - } - - // Adds the test name to the list of successfully run tests iff it was not - // previously reported as failing. This behavior is useful for tests that - // have multiple parts, where failures and successes are reported individually - // with the same test name. - void addTestSuccess(absl::string_view test_name) { - auto normalized_test_name = absl::AsciiStrToLower(test_name); - - // If the test is already reported as failing, do not add it to the list of - // successes. - if (test_failures_.find(normalized_test_name) == test_failures_.end()) { - test_successes_.insert(std::move(normalized_test_name)); - } - } - - // Streams a single error description into the internal buffer (a visual - // divider is automatically inserted after the error so that multiple errors - // are visibly distinct). - // - // This function increases the error count by 1. - // - // TODO(calabrese) Determine desired behavior when if this function throws. - template <class... P> - void addTestFailure(absl::string_view test_name, const P&... args) { - // Output a message related to the test failure. - assertion_result_ << "\n\n" - "Failed test: " - << test_name << "\n\n"; - addTestFailureImpl(args...); - assertion_result_ << "\n\n"; - outputDivider(); - - auto normalized_test_name = absl::AsciiStrToLower(test_name); - - // If previous parts of this test succeeded, remove it from that set. - test_successes_.erase(normalized_test_name); - - // Add the test name to the list of failed tests. - test_failures_.insert(std::move(normalized_test_name)); - - has_error_ = true; - } - - // Convert this object into a testing::AssertionResult instance such that it - // can be used with gtest. - ::testing::AssertionResult assertionResult() const { - return has_error_ ? assertion_result_ : ::testing::AssertionSuccess(); - } - - // Convert this object into a testing::AssertionResult instance such that it - // can be used with gtest. This overload expects errors, using the specified - // matcher. - ::testing::AssertionResult expectFailedTests( - const std::set<std::string>& test_names) const { - // Since we are expecting nonconformance, output an error message when the - // type actually conformed to the specified profile. - if (!has_error_) { - return ::testing::AssertionFailure() - << "Unexpected conformance of type:\n" - " " - << type_name_ << "\n\n"; - } - - // Get a list of all expected failures that did not actually fail - // (or that were not run). - std::vector<std::string> nonfailing_tests; - absl::c_set_difference(test_names, test_failures_, - std::back_inserter(nonfailing_tests)); - - // Get a list of all "expected failures" that were never actually run. - std::vector<std::string> unrun_tests; - absl::c_set_difference(nonfailing_tests, test_successes_, - std::back_inserter(unrun_tests)); - - // Report when the user specified tests that were not run. - if (!unrun_tests.empty()) { - const bool tests_were_run = - !(test_failures_.empty() && test_successes_.empty()); - - // Prepare an assertion result used in the case that tests pass that were - // expected to fail. - ::testing::AssertionResult result = ::testing::AssertionFailure(); - result << "When testing type:\n " << type_name_ - << "\n\nThe following tests were expected to fail but were not " - "run"; - - if (tests_were_run) result << " (was the test name spelled correctly?)"; - - result << ":\n\n"; - - // List all of the tests that unexpectedly passed. - for (const auto& test_name : unrun_tests) { - result << " " << test_name << "\n"; - } - - if (!tests_were_run) result << "\nNo tests were run."; - - if (!test_failures_.empty()) { - // List test failures - result << "\nThe tests that were run and failed are:\n\n"; - for (const auto& test_name : test_failures_) { - result << " " << test_name << "\n"; - } - } - - if (!test_successes_.empty()) { - // List test successes - result << "\nThe tests that were run and succeeded are:\n\n"; - for (const auto& test_name : test_successes_) { - result << " " << test_name << "\n"; - } - } - - return result; - } - - // If some tests passed when they were expected to fail, alert the caller. - if (nonfailing_tests.empty()) return ::testing::AssertionSuccess(); - - // Prepare an assertion result used in the case that tests pass that were - // expected to fail. - ::testing::AssertionResult unexpected_successes = - ::testing::AssertionFailure(); - unexpected_successes << "When testing type:\n " << type_name_ - << "\n\nThe following tests passed when they were " - "expected to fail:\n\n"; - - // List all of the tests that unexpectedly passed. - for (const auto& test_name : nonfailing_tests) { - unexpected_successes << " " << test_name << "\n"; - } - - return unexpected_successes; - } - - private: - void outputDivider() { - assertion_result_ << "========================================"; - } - - void addTestFailureImpl() {} - - template <class H, class... T> - void addTestFailureImpl(const H& head, const T&... tail) { - assertion_result_ << head; - addTestFailureImpl(tail...); - } - - ::testing::AssertionResult assertion_result_; - std::set<std::string> test_failures_; - std::set<std::string> test_successes_; - std::string type_name_; - bool has_error_ = false; -}; - -template <class T, class /*Enabler*/ = void> -struct PropertiesOfImpl {}; - -template <class T> -struct PropertiesOfImpl<T, absl::void_t<typename T::properties>> { - using type = typename T::properties; -}; - -template <class T> -struct PropertiesOfImpl<T, absl::void_t<typename T::profile_alias_of>> { - using type = typename PropertiesOfImpl<typename T::profile_alias_of>::type; -}; - -template <class T> -struct PropertiesOf : PropertiesOfImpl<T> {}; - -template <class T> -using PropertiesOfT = typename PropertiesOf<T>::type; - -// NOTE: These enums use this naming convention to be consistent with the -// standard trait names, which is useful since it allows us to match up each -// enum name with a corresponding trait name in macro definitions. - -// An enum that describes the various expectations on an operations existence. -enum class function_support { maybe, yes, nothrow, trivial }; - -constexpr const char* PessimisticPropertyDescription(function_support v) { - return v == function_support::maybe - ? "no" - : v == function_support::yes - ? "yes, potentially throwing" - : v == function_support::nothrow ? "yes, nothrow" - : "yes, trivial"; -} - -// Return a string that describes the kind of property support that was -// expected. -inline std::string ExpectedFunctionKindList(function_support min, - function_support max) { - if (min == max) { - std::string result = - absl::StrCat("Expected:\n ", - PessimisticPropertyDescription( - static_cast<function_support>(UnderlyingValue(min))), - "\n"); - return result; - } - - std::string result = "Expected one of:\n"; - for (auto curr_support = UnderlyingValue(min); - curr_support <= UnderlyingValue(max); ++curr_support) { - absl::StrAppend(&result, " ", - PessimisticPropertyDescription( - static_cast<function_support>(curr_support)), - "\n"); - } - - return result; -} - -template <class Enum> -void ExpectModelOfImpl(ConformanceErrors* errors, Enum min_support, - Enum max_support, Enum kind) { - const auto kind_value = UnderlyingValue(kind); - const auto min_support_value = UnderlyingValue(min_support); - const auto max_support_value = UnderlyingValue(max_support); - - if (!(kind_value >= min_support_value && kind_value <= max_support_value)) { - errors->addTestFailure( - PropertyName(kind), "**Failed property expectation**\n\n", - ExpectedFunctionKindList( - static_cast<function_support>(min_support_value), - static_cast<function_support>(max_support_value)), - '\n', "Actual:\n ", - PessimisticPropertyDescription( - static_cast<function_support>(kind_value))); - } else { - errors->addTestSuccess(PropertyName(kind)); - } -} - -#define ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(description, name) \ - enum class name { maybe, yes, nothrow, trivial }; \ - \ - constexpr const char* PropertyName(name v) { return description; } \ - static_assert(true, "") // Force a semicolon when using this macro. - -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for default construction", - default_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move construction", - move_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy construction", - copy_constructible); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move assignment", - move_assignable); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy assignment", - copy_assignable); -ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for destruction", - destructible); - -#undef ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM - -#define ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(description, name) \ - enum class name { maybe, yes, nothrow }; \ - \ - constexpr const char* PropertyName(name v) { return description; } \ - static_assert(true, "") // Force a semicolon when using this macro. - -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for ==", equality_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for !=", inequality_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <", less_than_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <=", less_equal_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >=", - greater_equal_comparable); -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >", greater_than_comparable); - -ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for swap", swappable); - -#undef ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM - -enum class hashable { maybe, yes }; - -constexpr const char* PropertyName(hashable v) { - return "support for std::hash"; -} - -template <class T> -using AlwaysFalse = std::false_type; - -#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(name, property) \ - template <class T> \ - constexpr property property##_support_of() { \ - return std::is_##property<T>::value \ - ? std::is_nothrow_##property<T>::value \ - ? absl::is_trivially_##property<T>::value \ - ? property::trivial \ - : property::nothrow \ - : property::yes \ - : property::maybe; \ - } \ - \ - template <class T, class MinProf, class MaxProf> \ - void ExpectModelOf##name(ConformanceErrors* errors) { \ - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \ - PropertiesOfT<MaxProf>::property##_support, \ - property##_support_of<T>()); \ - } - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(DefaultConstructible, - default_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveConstructible, - move_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyConstructible, - copy_constructible); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveAssignable, - move_assignable); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyAssignable, - copy_assignable); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(Destructible, destructible); - -#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER - -void BoolFunction(bool) noexcept; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction for checking if an operation exists through SFINAE. -// -// `T` is the type to test and Op is an alias containing the expression to test. -template <class T, template <class...> class Op, class = void> -struct IsOpableImpl : std::false_type {}; - -template <class T, template <class...> class Op> -struct IsOpableImpl<T, Op, absl::void_t<Op<T>>> : std::true_type {}; - -template <template <class...> class Op> -struct IsOpable { - template <class T> - using apply = typename IsOpableImpl<T, Op>::type; -}; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction for checking if an operation exists and is also noexcept -// through SFINAE and the noexcept operator. -/// -// `T` is the type to test and Op is an alias containing the expression to test. -template <class T, template <class...> class Op, class = void> -struct IsNothrowOpableImpl : std::false_type {}; - -template <class T, template <class...> class Op> -struct IsNothrowOpableImpl<T, Op, absl::enable_if_t<Op<T>::value>> - : std::true_type {}; - -template <template <class...> class Op> -struct IsNothrowOpable { - template <class T> - using apply = typename IsNothrowOpableImpl<T, Op>::type; -}; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A macro that produces the necessary function for reporting what kind of -// support a specific comparison operation has and a function for reporting an -// error if a given type's support for that operation does not meet the expected -// requirements. -#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(name, property, op) \ - template <class T, \ - class Result = std::integral_constant< \ - bool, noexcept((BoolFunction)(std::declval<const T&>() op \ - std::declval<const T&>()))>> \ - using name = Result; \ - \ - template <class T> \ - constexpr property property##_support_of() { \ - return IsOpable<name>::apply<T>::value \ - ? IsNothrowOpable<name>::apply<T>::value ? property::nothrow \ - : property::yes \ - : property::maybe; \ - } \ - \ - template <class T, class MinProf, class MaxProf> \ - void ExpectModelOf##name(ConformanceErrors* errors) { \ - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \ - PropertiesOfT<MaxProf>::property##_support, \ - property##_support_of<T>()); \ - } -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// Generate the necessary support-checking and error reporting functions for -// each of the comparison operators. -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(EqualityComparable, - equality_comparable, ==); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(InequalityComparable, - inequality_comparable, !=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessThanComparable, - less_than_comparable, <); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessEqualComparable, - less_equal_comparable, <=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterEqualComparable, - greater_equal_comparable, >=); - -ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterThanComparable, - greater_than_comparable, >); - -#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// The necessary support-checking and error-reporting functions for swap. -template <class T> -constexpr swappable swappable_support_of() { - return type_traits_internal::IsSwappable<T>::value - ? type_traits_internal::IsNothrowSwappable<T>::value - ? swappable::nothrow - : swappable::yes - : swappable::maybe; -} - -template <class T, class MinProf, class MaxProf> -void ExpectModelOfSwappable(ConformanceErrors* errors) { - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::swappable_support, - PropertiesOfT<MaxProf>::swappable_support, - swappable_support_of<T>()); -} -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// The necessary support-checking and error-reporting functions for std::hash. -template <class T> -constexpr hashable hashable_support_of() { - return type_traits_internal::IsHashable<T>::value ? hashable::yes - : hashable::maybe; -} - -template <class T, class MinProf, class MaxProf> -void ExpectModelOfHashable(ConformanceErrors* errors) { - (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::hashable_support, - PropertiesOfT<MaxProf>::hashable_support, - hashable_support_of<T>()); -} -// -//////////////////////////////////////////////////////////////////////////////// - -template < - default_constructible DefaultConstructibleValue = - default_constructible::maybe, - move_constructible MoveConstructibleValue = move_constructible::maybe, - copy_constructible CopyConstructibleValue = copy_constructible::maybe, - move_assignable MoveAssignableValue = move_assignable::maybe, - copy_assignable CopyAssignableValue = copy_assignable::maybe, - destructible DestructibleValue = destructible::maybe, - equality_comparable EqualityComparableValue = equality_comparable::maybe, - inequality_comparable InequalityComparableValue = - inequality_comparable::maybe, - less_than_comparable LessThanComparableValue = less_than_comparable::maybe, - less_equal_comparable LessEqualComparableValue = - less_equal_comparable::maybe, - greater_equal_comparable GreaterEqualComparableValue = - greater_equal_comparable::maybe, - greater_than_comparable GreaterThanComparableValue = - greater_than_comparable::maybe, - swappable SwappableValue = swappable::maybe, - hashable HashableValue = hashable::maybe> -struct ConformanceProfile { - using properties = ConformanceProfile; - - static constexpr default_constructible - default_constructible_support = // NOLINT - DefaultConstructibleValue; - - static constexpr move_constructible move_constructible_support = // NOLINT - MoveConstructibleValue; - - static constexpr copy_constructible copy_constructible_support = // NOLINT - CopyConstructibleValue; - - static constexpr move_assignable move_assignable_support = // NOLINT - MoveAssignableValue; - - static constexpr copy_assignable copy_assignable_support = // NOLINT - CopyAssignableValue; - - static constexpr destructible destructible_support = // NOLINT - DestructibleValue; - - static constexpr equality_comparable equality_comparable_support = // NOLINT - EqualityComparableValue; - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - InequalityComparableValue; - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - LessThanComparableValue; - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - LessEqualComparableValue; - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - GreaterEqualComparableValue; - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - GreaterThanComparableValue; - - static constexpr swappable swappable_support = SwappableValue; // NOLINT - - static constexpr hashable hashable_support = HashableValue; // NOLINT - - static constexpr bool is_default_constructible = // NOLINT - DefaultConstructibleValue != default_constructible::maybe; - - static constexpr bool is_move_constructible = // NOLINT - MoveConstructibleValue != move_constructible::maybe; - - static constexpr bool is_copy_constructible = // NOLINT - CopyConstructibleValue != copy_constructible::maybe; - - static constexpr bool is_move_assignable = // NOLINT - MoveAssignableValue != move_assignable::maybe; - - static constexpr bool is_copy_assignable = // NOLINT - CopyAssignableValue != copy_assignable::maybe; - - static constexpr bool is_destructible = // NOLINT - DestructibleValue != destructible::maybe; - - static constexpr bool is_equality_comparable = // NOLINT - EqualityComparableValue != equality_comparable::maybe; - - static constexpr bool is_inequality_comparable = // NOLINT - InequalityComparableValue != inequality_comparable::maybe; - - static constexpr bool is_less_than_comparable = // NOLINT - LessThanComparableValue != less_than_comparable::maybe; - - static constexpr bool is_less_equal_comparable = // NOLINT - LessEqualComparableValue != less_equal_comparable::maybe; - - static constexpr bool is_greater_equal_comparable = // NOLINT - GreaterEqualComparableValue != greater_equal_comparable::maybe; - - static constexpr bool is_greater_than_comparable = // NOLINT - GreaterThanComparableValue != greater_than_comparable::maybe; - - static constexpr bool is_swappable = // NOLINT - SwappableValue != swappable::maybe; - - static constexpr bool is_hashable = // NOLINT - HashableValue != hashable::maybe; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// Compliant SFINAE-friendliness is not always present on the standard library -// implementations that we support. This helper-struct (and associated enum) is -// used as a means to conditionally check the hashability support of a type. -enum class CheckHashability { no, yes }; - -template <class T, CheckHashability ShouldCheckHashability> -struct conservative_hashable_support_of; - -template <class T> -struct conservative_hashable_support_of<T, CheckHashability::no> { - static constexpr hashable Invoke() { return hashable::maybe; } -}; - -template <class T> -struct conservative_hashable_support_of<T, CheckHashability::yes> { - static constexpr hashable Invoke() { return hashable_support_of<T>(); } -}; -// -//////////////////////////////////////////////////////////////////////////////// - -// The ConformanceProfile that is expected based on introspection into the type -// by way of trait checks. -template <class T, CheckHashability ShouldCheckHashability> -struct SyntacticConformanceProfileOf { - using properties = ConformanceProfile< - default_constructible_support_of<T>(), move_constructible_support_of<T>(), - copy_constructible_support_of<T>(), move_assignable_support_of<T>(), - copy_assignable_support_of<T>(), destructible_support_of<T>(), - equality_comparable_support_of<T>(), - inequality_comparable_support_of<T>(), - less_than_comparable_support_of<T>(), - less_equal_comparable_support_of<T>(), - greater_equal_comparable_support_of<T>(), - greater_than_comparable_support_of<T>(), swappable_support_of<T>(), - conservative_hashable_support_of<T, ShouldCheckHashability>::Invoke()>; -}; - -#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, name) \ - template <default_constructible DefaultConstructibleValue, \ - move_constructible MoveConstructibleValue, \ - copy_constructible CopyConstructibleValue, \ - move_assignable MoveAssignableValue, \ - copy_assignable CopyAssignableValue, \ - destructible DestructibleValue, \ - equality_comparable EqualityComparableValue, \ - inequality_comparable InequalityComparableValue, \ - less_than_comparable LessThanComparableValue, \ - less_equal_comparable LessEqualComparableValue, \ - greater_equal_comparable GreaterEqualComparableValue, \ - greater_than_comparable GreaterThanComparableValue, \ - swappable SwappableValue, hashable HashableValue> \ - constexpr type ConformanceProfile< \ - DefaultConstructibleValue, MoveConstructibleValue, \ - CopyConstructibleValue, MoveAssignableValue, CopyAssignableValue, \ - DestructibleValue, EqualityComparableValue, InequalityComparableValue, \ - LessThanComparableValue, LessEqualComparableValue, \ - GreaterEqualComparableValue, GreaterThanComparableValue, SwappableValue, \ - HashableValue>::name - -#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(type) \ - ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, \ - type##_support); \ - ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(bool, is_##type) - -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(default_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_constructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_assignable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_assignable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(destructible); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(equality_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(inequality_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_than_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_equal_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_equal_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_than_comparable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(swappable); -ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(hashable); - -#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF -#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL - -// Retrieve the enum with the minimum underlying value. -// Note: std::min is not constexpr in C++11, which is why this is necessary. -template <class H> -constexpr H MinEnum(H head) { - return head; -} - -template <class H, class N, class... T> -constexpr H MinEnum(H head, N next, T... tail) { - return (UnderlyingValue)(head) < (UnderlyingValue)(next) - ? (MinEnum)(head, tail...) - : (MinEnum)(next, tail...); -} - -template <class... Profs> -struct MinimalProfiles { - static constexpr default_constructible - default_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::default_constructible_support...); - - static constexpr move_constructible move_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::move_constructible_support...); - - static constexpr copy_constructible copy_constructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::copy_constructible_support...); - - static constexpr move_assignable move_assignable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::move_assignable_support...); - - static constexpr copy_assignable copy_assignable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::copy_assignable_support...); - - static constexpr destructible destructible_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::destructible_support...); - - static constexpr equality_comparable equality_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::equality_comparable_support...); - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::inequality_comparable_support...); - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::less_than_comparable_support...); - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...); - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...); - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...); - - static constexpr swappable swappable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::swappable_support...); - - static constexpr hashable hashable_support = // NOLINT - (MinEnum)(PropertiesOfT<Profs>::hashable_support...); - - using properties = ConformanceProfile< - default_constructible_support, move_constructible_support, - copy_constructible_support, move_assignable_support, - copy_assignable_support, destructible_support, - equality_comparable_support, inequality_comparable_support, - less_than_comparable_support, less_equal_comparable_support, - greater_equal_comparable_support, greater_than_comparable_support, - swappable_support, hashable_support>; -}; - -// Retrieve the enum with the greatest underlying value. -// Note: std::max is not constexpr in C++11, which is why this is necessary. -template <class H> -constexpr H MaxEnum(H head) { - return head; -} - -template <class H, class N, class... T> -constexpr H MaxEnum(H head, N next, T... tail) { - return (UnderlyingValue)(next) < (UnderlyingValue)(head) - ? (MaxEnum)(head, tail...) - : (MaxEnum)(next, tail...); -} - -template <class... Profs> -struct CombineProfilesImpl { - static constexpr default_constructible - default_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::default_constructible_support...); - - static constexpr move_constructible move_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::move_constructible_support...); - - static constexpr copy_constructible copy_constructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::copy_constructible_support...); - - static constexpr move_assignable move_assignable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::move_assignable_support...); - - static constexpr copy_assignable copy_assignable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::copy_assignable_support...); - - static constexpr destructible destructible_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::destructible_support...); - - static constexpr equality_comparable equality_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::equality_comparable_support...); - - static constexpr inequality_comparable - inequality_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::inequality_comparable_support...); - - static constexpr less_than_comparable - less_than_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::less_than_comparable_support...); - - static constexpr less_equal_comparable - less_equal_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...); - - static constexpr greater_equal_comparable - greater_equal_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...); - - static constexpr greater_than_comparable - greater_than_comparable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...); - - static constexpr swappable swappable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::swappable_support...); - - static constexpr hashable hashable_support = // NOLINT - (MaxEnum)(PropertiesOfT<Profs>::hashable_support...); - - using properties = ConformanceProfile< - default_constructible_support, move_constructible_support, - copy_constructible_support, move_assignable_support, - copy_assignable_support, destructible_support, - equality_comparable_support, inequality_comparable_support, - less_than_comparable_support, less_equal_comparable_support, - greater_equal_comparable_support, greater_than_comparable_support, - swappable_support, hashable_support>; -}; - -// NOTE: We use this as opposed to a direct alias of CombineProfilesImpl so that -// when named aliases of CombineProfiles are created (such as in -// conformance_aliases.h), we only pay for the combination algorithm on the -// profiles that are actually used. -template <class... Profs> -struct CombineProfiles { - using profile_alias_of = CombineProfilesImpl<Profs...>; -}; - -template <> -struct CombineProfiles<> { - using properties = ConformanceProfile<>; -}; - -template <class Profile, class Tag> -struct StrongProfileTypedef { - using properties = PropertiesOfT<Profile>; -}; - -template <class T, class /*Enabler*/ = void> -struct IsProfileImpl : std::false_type {}; - -template <class T> -struct IsProfileImpl<T, absl::void_t<PropertiesOfT<T>>> : std::true_type {}; - -template <class T> -struct IsProfile : IsProfileImpl<T>::type {}; - -// A tag that describes which set of properties we will check when the user -// requires a strict match in conformance (as opposed to a loose match which -// allows more-refined support of any given operation). -// -// Currently only the RegularityDomain exists and it includes all operations -// that the conformance testing suite knows about. The intent is that if the -// suite is expanded to support extension, such as for checking conformance of -// concepts like Iterators or Containers, additional corresponding domains can -// be created. -struct RegularityDomain {}; - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_testing.h b/third_party/abseil_cpp/absl/types/internal/conformance_testing.h deleted file mode 100644 index 487b0f786b48..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_testing.h +++ /dev/null @@ -1,1386 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// conformance_testing.h -// ----------------------------------------------------------------------------- -// - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_ - -//////////////////////////////////////////////////////////////////////////////// -// // -// Many templates in this file take a `T` and a `Prof` type as explicit // -// template arguments. These are a type to be checked and a // -// "Regularity Profile" that describes what operations that type `T` is // -// expected to support. See "regularity_profiles.h" for more details // -// regarding Regularity Profiles. // -// // -//////////////////////////////////////////////////////////////////////////////// - -#include <cstddef> -#include <set> -#include <tuple> -#include <type_traits> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/ascii.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/types/internal/conformance_aliases.h" -#include "absl/types/internal/conformance_archetype.h" -#include "absl/types/internal/conformance_profile.h" -#include "absl/types/internal/conformance_testing_helpers.h" -#include "absl/types/internal/parentheses.h" -#include "absl/types/internal/transform_args.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Returns true if the compiler incorrectly greedily instantiates constexpr -// templates in any unevaluated context. -constexpr bool constexpr_instantiation_when_unevaluated() { -#if defined(__apple_build_version__) // TODO(calabrese) Make more specific - return true; -#elif defined(__clang__) - return __clang_major__ < 4; -#elif defined(__GNUC__) - // TODO(calabrese) Figure out why gcc 7 fails (seems like a different bug) - return __GNUC__ < 5 || (__GNUC__ == 5 && __GNUC_MINOR__ < 2) || __GNUC__ >= 7; -#else - return false; -#endif -} - -// Returns true if the standard library being used incorrectly produces an error -// when instantiating the definition of a poisoned std::hash specialization. -constexpr bool poisoned_hash_fails_instantiation() { -#if defined(_MSC_VER) && !defined(_LIBCPP_VERSION) - return _MSC_VER < 1914; -#else - return false; -#endif -} - -template <class Fun> -struct GeneratorType { - decltype(std::declval<const Fun&>()()) operator()() const - noexcept(noexcept(std::declval<const Fun&>()())) { - return fun(); - } - - Fun fun; - const char* description; -}; - -// A "make" function for the GeneratorType template that deduces the function -// object type. -template <class Fun, - absl::enable_if_t<IsNullaryCallable<Fun>::value>** = nullptr> -GeneratorType<Fun> Generator(Fun fun, const char* description) { - return GeneratorType<Fun>{absl::move(fun), description}; -} - -// A type that contains a set of nullary function objects that each return an -// instance of the same type and value (though possibly different -// representations, such as +0 and -0 or two vectors with the same elements but -// with different capacities). -template <class... Funs> -struct EquivalenceClassType { - std::tuple<GeneratorType<Funs>...> generators; -}; - -// A "make" function for the EquivalenceClassType template that deduces the -// function object types and is constrained such that a user can only pass in -// function objects that all have the same return type. -template <class... Funs, absl::enable_if_t<AreGeneratorsWithTheSameReturnType< - Funs...>::value>** = nullptr> -EquivalenceClassType<Funs...> EquivalenceClass(GeneratorType<Funs>... funs) { - return {std::make_tuple(absl::move(funs)...)}; -} - -// A type that contains an ordered series of EquivalenceClassTypes, from -// smallest value to largest value. -template <class... EqClasses> -struct OrderedEquivalenceClasses { - std::tuple<EqClasses...> eq_classes; -}; - -// An object containing the parts of a given (name, initialization expression), -// and is capable of generating a string that describes the given. -struct GivenDeclaration { - std::string outputDeclaration(std::size_t width) const { - const std::size_t indent_size = 2; - std::string result = absl::StrCat(" ", name); - - if (!expression.empty()) { - // Indent - result.resize(indent_size + width, ' '); - absl::StrAppend(&result, " = ", expression, ";\n"); - } else { - absl::StrAppend(&result, ";\n"); - } - - return result; - } - - std::string name; - std::string expression; -}; - -// Produce a string that contains all of the givens of an error report. -template <class... Decls> -std::string PrepareGivenContext(const Decls&... decls) { - const std::size_t width = (std::max)({decls.name.size()...}); - return absl::StrCat("Given:\n", decls.outputDeclaration(width)..., "\n"); -} - -//////////////////////////////////////////////////////////////////////////////// -// Function objects that perform a check for each comparison operator // -//////////////////////////////////////////////////////////////////////////////// - -#define ABSL_INTERNAL_EXPECT_OP(name, op) \ - struct Expect##name { \ - template <class T> \ - void operator()(absl::string_view test_name, absl::string_view context, \ - const T& lhs, const T& rhs, absl::string_view lhs_name, \ - absl::string_view rhs_name) const { \ - if (!static_cast<bool>(lhs op rhs)) { \ - errors->addTestFailure( \ - test_name, absl::StrCat(context, \ - "**Unexpected comparison result**\n" \ - "\n" \ - "Expression:\n" \ - " ", \ - lhs_name, " " #op " ", rhs_name, \ - "\n" \ - "\n" \ - "Expected: true\n" \ - " Actual: false")); \ - } else { \ - errors->addTestSuccess(test_name); \ - } \ - } \ - \ - ConformanceErrors* errors; \ - }; \ - \ - struct ExpectNot##name { \ - template <class T> \ - void operator()(absl::string_view test_name, absl::string_view context, \ - const T& lhs, const T& rhs, absl::string_view lhs_name, \ - absl::string_view rhs_name) const { \ - if (lhs op rhs) { \ - errors->addTestFailure( \ - test_name, absl::StrCat(context, \ - "**Unexpected comparison result**\n" \ - "\n" \ - "Expression:\n" \ - " ", \ - lhs_name, " " #op " ", rhs_name, \ - "\n" \ - "\n" \ - "Expected: false\n" \ - " Actual: true")); \ - } else { \ - errors->addTestSuccess(test_name); \ - } \ - } \ - \ - ConformanceErrors* errors; \ - } - -ABSL_INTERNAL_EXPECT_OP(Eq, ==); -ABSL_INTERNAL_EXPECT_OP(Ne, !=); -ABSL_INTERNAL_EXPECT_OP(Lt, <); -ABSL_INTERNAL_EXPECT_OP(Le, <=); -ABSL_INTERNAL_EXPECT_OP(Ge, >=); -ABSL_INTERNAL_EXPECT_OP(Gt, >); - -#undef ABSL_INTERNAL_EXPECT_OP - -// A function object that verifies that two objects hash to the same value by -// way of the std::hash specialization. -struct ExpectSameHash { - template <class T> - void operator()(absl::string_view test_name, absl::string_view context, - const T& lhs, const T& rhs, absl::string_view lhs_name, - absl::string_view rhs_name) const { - if (std::hash<T>()(lhs) != std::hash<T>()(rhs)) { - errors->addTestFailure( - test_name, absl::StrCat(context, - "**Unexpected hash result**\n" - "\n" - "Expression:\n" - " std::hash<T>()(", - lhs_name, ") == std::hash<T>()(", rhs_name, - ")\n" - "\n" - "Expected: true\n" - " Actual: false")); - } else { - errors->addTestSuccess(test_name); - } - } - - ConformanceErrors* errors; -}; - -// A function template that takes two objects and verifies that each comparison -// operator behaves in a way that is consistent with equality. It has "OneWay" -// in the name because the first argument will always be the left-hand operand -// of the corresponding comparison operator and the second argument will -// always be the right-hand operand. It will never switch that order. -// At a higher level in the test suite, the one-way form is called once for each -// of the two possible orders whenever lhs and rhs are not the same initializer. -template <class T, class Prof> -void ExpectOneWayEquality(ConformanceErrors* errors, - absl::string_view test_name, - absl::string_view context, const T& lhs, const T& rhs, - absl::string_view lhs_name, - absl::string_view rhs_name) { - If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke( - ExpectEq{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke( - ExpectNotNe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke( - ExpectNotLt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke( - ExpectLe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke( - ExpectGe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke( - ExpectNotGt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); - - If<PropertiesOfT<Prof>::is_hashable>::Invoke( - ExpectSameHash{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name); -} - -// A function template that takes two objects and verifies that each comparison -// operator behaves in a way that is consistent with equality. This function -// differs from ExpectOneWayEquality in that this will do checks with argument -// order reversed in addition to in-order. -template <class T, class Prof> -void ExpectEquality(ConformanceErrors* errors, absl::string_view test_name, - absl::string_view context, const T& lhs, const T& rhs, - absl::string_view lhs_name, absl::string_view rhs_name) { - (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, lhs, rhs, - lhs_name, rhs_name); - (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, rhs, lhs, - rhs_name, lhs_name); -} - -// Given a generator, makes sure that a generated value and a moved-from -// generated value are equal. -template <class T, class Prof> -struct ExpectMoveConstructOneGenerator { - template <class Fun> - void operator()(const Fun& generator) const { - const T object = generator(); - const T moved_object = absl::move(generator()); // Force no elision. - - (ExpectEquality<T, Prof>)(errors, "Move construction", - PrepareGivenContext( - GivenDeclaration{"const _T object", - generator.description}, - GivenDeclaration{"const _T moved_object", - std::string("std::move(") + - generator.description + - ")"}), - object, moved_object, "object", "moved_object"); - } - - ConformanceErrors* errors; -}; - -// Given a generator, makes sure that a generated value and a copied-from -// generated value are equal. -template <class T, class Prof> -struct ExpectCopyConstructOneGenerator { - template <class Fun> - void operator()(const Fun& generator) const { - const T object = generator(); - const T copied_object = static_cast<const T&>(generator()); - - (ExpectEquality<T, Prof>)(errors, "Copy construction", - PrepareGivenContext( - GivenDeclaration{"const _T object", - generator.description}, - GivenDeclaration{ - "const _T copied_object", - std::string("static_cast<const _T&>(") + - generator.description + ")"}), - object, copied_object, "object", "copied_object"); - } - - ConformanceErrors* errors; -}; - -// Default-construct and do nothing before destruction. -// -// This is useful in exercising the codepath of default construction followed by -// destruction, but does not explicitly test anything. An example of where this -// might fail is a default destructor that default-initializes a scalar and a -// destructor reads the value of that member. Sanitizers can catch this as long -// as our test attempts to execute such a case. -template <class T> -struct ExpectDefaultConstructWithDestruct { - void operator()() const { - // Scoped so that destructor gets called before reporting success. - { - T object; - static_cast<void>(object); - } - - errors->addTestSuccess("Default construction"); - } - - ConformanceErrors* errors; -}; - -// Check move-assign into a default-constructed object. -template <class T, class Prof> -struct ExpectDefaultConstructWithMoveAssign { - template <class Fun> - void operator()(const Fun& generator) const { - const T source_of_truth = generator(); - T object; - object = generator(); - - (ExpectEquality<T, Prof>)(errors, "Move assignment", - PrepareGivenContext( - GivenDeclaration{"const _T object", - generator.description}, - GivenDeclaration{"_T object", ""}, - GivenDeclaration{"object", - generator.description}), - object, source_of_truth, "std::as_const(object)", - "source_of_truth"); - } - - ConformanceErrors* errors; -}; - -// Check copy-assign into a default-constructed object. -template <class T, class Prof> -struct ExpectDefaultConstructWithCopyAssign { - template <class Fun> - void operator()(const Fun& generator) const { - const T source_of_truth = generator(); - T object; - object = static_cast<const T&>(generator()); - - (ExpectEquality<T, Prof>)(errors, "Copy assignment", - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth", - generator.description}, - GivenDeclaration{"_T object", ""}, - GivenDeclaration{ - "object", - std::string("static_cast<const _T&>(") + - generator.description + ")"}), - object, source_of_truth, "std::as_const(object)", - "source_of_truth"); - } - - ConformanceErrors* errors; -}; - -// Perform a self move-assign. -template <class T, class Prof> -struct ExpectSelfMoveAssign { - template <class Fun> - void operator()(const Fun& generator) const { - T object = generator(); - object = absl::move(object); - - // NOTE: Self move-assign results in a valid-but-unspecified state. - - (ExpectEquality<T, Prof>)(errors, "Move assignment", - PrepareGivenContext( - GivenDeclaration{"_T object", - generator.description}, - GivenDeclaration{"object", - "std::move(object)"}), - object, object, "object", "object"); - } - - ConformanceErrors* errors; -}; - -// Perform a self copy-assign. -template <class T, class Prof> -struct ExpectSelfCopyAssign { - template <class Fun> - void operator()(const Fun& generator) const { - const T source_of_truth = generator(); - T object = generator(); - const T& const_object = object; - object = const_object; - - (ExpectEquality<T, Prof>)(errors, "Copy assignment", - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth", - generator.description}, - GivenDeclaration{"_T object", - generator.description}, - GivenDeclaration{"object", - "std::as_const(object)"}), - const_object, source_of_truth, - "std::as_const(object)", "source_of_truth"); - } - - ConformanceErrors* errors; -}; - -// Perform a self-swap. -template <class T, class Prof> -struct ExpectSelfSwap { - template <class Fun> - void operator()(const Fun& generator) const { - const T source_of_truth = generator(); - T object = generator(); - - type_traits_internal::Swap(object, object); - - std::string preliminary_info = absl::StrCat( - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth", generator.description}, - GivenDeclaration{"_T object", generator.description}), - "After performing a self-swap:\n" - " using std::swap;\n" - " swap(object, object);\n" - "\n"); - - (ExpectEquality<T, Prof>)(errors, "Swap", std::move(preliminary_info), - object, source_of_truth, "std::as_const(object)", - "source_of_truth"); - } - - ConformanceErrors* errors; -}; - -// Perform each of the single-generator checks when necessary operations are -// supported. -template <class T, class Prof> -struct ExpectSelfComparison { - template <class Fun> - void operator()(const Fun& generator) const { - const T object = generator(); - (ExpectOneWayEquality<T, Prof>)(errors, "Comparison", - PrepareGivenContext(GivenDeclaration{ - "const _T object", - generator.description}), - object, object, "object", "object"); - } - - ConformanceErrors* errors; -}; - -// Perform each of the single-generator checks when necessary operations are -// supported. -template <class T, class Prof> -struct ExpectConsistency { - template <class Fun> - void operator()(const Fun& generator) const { - If<PropertiesOfT<Prof>::is_move_constructible>::Invoke( - ExpectMoveConstructOneGenerator<T, Prof>{errors}, generator); - - If<PropertiesOfT<Prof>::is_copy_constructible>::Invoke( - ExpectCopyConstructOneGenerator<T, Prof>{errors}, generator); - - If<PropertiesOfT<Prof>::is_default_constructible && - PropertiesOfT<Prof>::is_move_assignable>:: - Invoke(ExpectDefaultConstructWithMoveAssign<T, Prof>{errors}, - generator); - - If<PropertiesOfT<Prof>::is_default_constructible && - PropertiesOfT<Prof>::is_copy_assignable>:: - Invoke(ExpectDefaultConstructWithCopyAssign<T, Prof>{errors}, - generator); - - If<PropertiesOfT<Prof>::is_move_assignable>::Invoke( - ExpectSelfMoveAssign<T, Prof>{errors}, generator); - - If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke( - ExpectSelfCopyAssign<T, Prof>{errors}, generator); - - If<PropertiesOfT<Prof>::is_swappable>::Invoke( - ExpectSelfSwap<T, Prof>{errors}, generator); - } - - ConformanceErrors* errors; -}; - -// Check move-assign with two different values. -template <class T, class Prof> -struct ExpectMoveAssign { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - const T source_of_truth1 = generator1(); - T object = generator0(); - object = generator1(); - - (ExpectEquality<T, Prof>)(errors, "Move assignment", - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth1", - generator1.description}, - GivenDeclaration{"_T object", - generator0.description}, - GivenDeclaration{"object", - generator1.description}), - object, source_of_truth1, "std::as_const(object)", - "source_of_truth1"); - } - - ConformanceErrors* errors; -}; - -// Check copy-assign with two different values. -template <class T, class Prof> -struct ExpectCopyAssign { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - const T source_of_truth1 = generator1(); - T object = generator0(); - object = static_cast<const T&>(generator1()); - - (ExpectEquality<T, Prof>)(errors, "Copy assignment", - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth1", - generator1.description}, - GivenDeclaration{"_T object", - generator0.description}, - GivenDeclaration{ - "object", - std::string("static_cast<const _T&>(") + - generator1.description + ")"}), - object, source_of_truth1, "std::as_const(object)", - "source_of_truth1"); - } - - ConformanceErrors* errors; -}; - -// Check swap with two different values. -template <class T, class Prof> -struct ExpectSwap { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - const T source_of_truth0 = generator0(); - const T source_of_truth1 = generator1(); - T object0 = generator0(); - T object1 = generator1(); - - type_traits_internal::Swap(object0, object1); - - const std::string context = - PrepareGivenContext( - GivenDeclaration{"const _T source_of_truth0", - generator0.description}, - GivenDeclaration{"const _T source_of_truth1", - generator1.description}, - GivenDeclaration{"_T object0", generator0.description}, - GivenDeclaration{"_T object1", generator1.description}) + - "After performing a swap:\n" - " using std::swap;\n" - " swap(object0, object1);\n" - "\n"; - - (ExpectEquality<T, Prof>)(errors, "Swap", context, object0, - source_of_truth1, "std::as_const(object0)", - "source_of_truth1"); - (ExpectEquality<T, Prof>)(errors, "Swap", context, object1, - source_of_truth0, "std::as_const(object1)", - "source_of_truth0"); - } - - ConformanceErrors* errors; -}; - -// Validate that `generator0` and `generator1` produce values that are equal. -template <class T, class Prof> -struct ExpectEquivalenceClassComparison { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - const T object0 = generator0(); - const T object1 = generator1(); - - (ExpectEquality<T, Prof>)(errors, "Comparison", - PrepareGivenContext( - GivenDeclaration{"const _T object0", - generator0.description}, - GivenDeclaration{"const _T object1", - generator1.description}), - object0, object1, "object0", "object1"); - } - - ConformanceErrors* errors; -}; - -// Validate that all objects in the same equivalence-class have the same value. -template <class T, class Prof> -struct ExpectEquivalenceClassConsistency { - template <class Fun0, class Fun1> - void operator()(const Fun0& generator0, const Fun1& generator1) const { - If<PropertiesOfT<Prof>::is_move_assignable>::Invoke( - ExpectMoveAssign<T, Prof>{errors}, generator0, generator1); - - If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke( - ExpectCopyAssign<T, Prof>{errors}, generator0, generator1); - - If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors}, - generator0, generator1); - } - - ConformanceErrors* errors; -}; - -// Given a "lesser" object and a "greater" object, perform every combination of -// comparison operators supported for the type, expecting consistent results. -template <class T, class Prof> -void ExpectOrdered(ConformanceErrors* errors, absl::string_view context, - const T& small, const T& big, absl::string_view small_name, - absl::string_view big_name) { - const absl::string_view test_name = "Comparison"; - - If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke( - ExpectNotEq{errors}, test_name, context, small, big, small_name, - big_name); - If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke( - ExpectNotEq{errors}, test_name, context, big, small, big_name, - small_name); - - If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke( - ExpectNe{errors}, test_name, context, small, big, small_name, big_name); - If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke( - ExpectNe{errors}, test_name, context, big, small, big_name, small_name); - - If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke( - ExpectLt{errors}, test_name, context, small, big, small_name, big_name); - If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke( - ExpectNotLt{errors}, test_name, context, big, small, big_name, - small_name); - - If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke( - ExpectLe{errors}, test_name, context, small, big, small_name, big_name); - If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke( - ExpectNotLe{errors}, test_name, context, big, small, big_name, - small_name); - - If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke( - ExpectNotGe{errors}, test_name, context, small, big, small_name, - big_name); - If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke( - ExpectGe{errors}, test_name, context, big, small, big_name, small_name); - - If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke( - ExpectNotGt{errors}, test_name, context, small, big, small_name, - big_name); - If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke( - ExpectGt{errors}, test_name, context, big, small, big_name, small_name); -} - -// For every two elements of an equivalence class, makes sure that those two -// elements compare equal, including checks with the same argument passed as -// both operands. -template <class T, class Prof> -struct ExpectEquivalenceClassComparisons { - template <class... Funs> - void operator()(EquivalenceClassType<Funs...> eq_class) const { - (ForEachTupleElement)(ExpectSelfComparison<T, Prof>{errors}, - eq_class.generators); - - (ForEveryTwo)(ExpectEquivalenceClassComparison<T, Prof>{errors}, - eq_class.generators); - } - - ConformanceErrors* errors; -}; - -// For every element of an equivalence class, makes sure that the element is -// self-consistent (in other words, if any of move/copy/swap are defined, -// perform those operations and make such that results and operands still -// compare equal to known values whenever it is required for that operation. -template <class T, class Prof> -struct ExpectEquivalenceClass { - template <class... Funs> - void operator()(EquivalenceClassType<Funs...> eq_class) const { - (ForEachTupleElement)(ExpectConsistency<T, Prof>{errors}, - eq_class.generators); - - (ForEveryTwo)(ExpectEquivalenceClassConsistency<T, Prof>{errors}, - eq_class.generators); - } - - ConformanceErrors* errors; -}; - -// Validate that the passed-in argument is a generator of a greater value than -// the one produced by the "small_gen" datamember with respect to all of the -// comparison operators that Prof requires, with both argument orders to test. -template <class T, class Prof, class SmallGenerator> -struct ExpectBiggerGeneratorThanComparisons { - template <class BigGenerator> - void operator()(BigGenerator big_gen) const { - const T small = small_gen(); - const T big = big_gen(); - - (ExpectOrdered<T, Prof>)(errors, - PrepareGivenContext( - GivenDeclaration{"const _T small", - small_gen.description}, - GivenDeclaration{"const _T big", - big_gen.description}), - small, big, "small", "big"); - } - - SmallGenerator small_gen; - ConformanceErrors* errors; -}; - -// Perform all of the move, copy, and swap checks on the value generated by -// `small_gen` and the value generated by `big_gen`. -template <class T, class Prof, class SmallGenerator> -struct ExpectBiggerGeneratorThan { - template <class BigGenerator> - void operator()(BigGenerator big_gen) const { - If<PropertiesOfT<Prof>::is_move_assignable>::Invoke( - ExpectMoveAssign<T, Prof>{errors}, small_gen, big_gen); - If<PropertiesOfT<Prof>::is_move_assignable>::Invoke( - ExpectMoveAssign<T, Prof>{errors}, big_gen, small_gen); - - If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke( - ExpectCopyAssign<T, Prof>{errors}, small_gen, big_gen); - If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke( - ExpectCopyAssign<T, Prof>{errors}, big_gen, small_gen); - - If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors}, - small_gen, big_gen); - } - - SmallGenerator small_gen; - ConformanceErrors* errors; -}; - -// Validate that the result of a generator is greater than the results of all -// generators in an equivalence class with respect to comparisons. -template <class T, class Prof, class SmallGenerator> -struct ExpectBiggerGeneratorThanEqClassesComparisons { - template <class BigEqClass> - void operator()(BigEqClass big_eq_class) const { - (ForEachTupleElement)( - ExpectBiggerGeneratorThanComparisons<T, Prof, SmallGenerator>{small_gen, - errors}, - big_eq_class.generators); - } - - SmallGenerator small_gen; - ConformanceErrors* errors; -}; - -// Validate that the non-comparison binary operations required by Prof are -// correct for the result of each generator of big_eq_class and a generator of -// the logically smaller value returned by small_gen. -template <class T, class Prof, class SmallGenerator> -struct ExpectBiggerGeneratorThanEqClasses { - template <class BigEqClass> - void operator()(BigEqClass big_eq_class) const { - (ForEachTupleElement)( - ExpectBiggerGeneratorThan<T, Prof, SmallGenerator>{small_gen, errors}, - big_eq_class.generators); - } - - SmallGenerator small_gen; - ConformanceErrors* errors; -}; - -// Validate that each equivalence class that is passed is logically less than -// the equivalence classes that comes later on in the argument list. -template <class T, class Prof> -struct ExpectOrderedEquivalenceClassesComparisons { - template <class... BigEqClasses> - struct Impl { - // Validate that the value produced by `small_gen` is less than all of the - // values generated by those of the logically larger equivalence classes. - template <class SmallGenerator> - void operator()(SmallGenerator small_gen) const { - (ForEachTupleElement)(ExpectBiggerGeneratorThanEqClassesComparisons< - T, Prof, SmallGenerator>{small_gen, errors}, - big_eq_classes); - } - - std::tuple<BigEqClasses...> big_eq_classes; - ConformanceErrors* errors; - }; - - // When given no equivalence classes, no validation is necessary. - void operator()() const {} - - template <class SmallEqClass, class... BigEqClasses> - void operator()(SmallEqClass small_eq_class, - BigEqClasses... big_eq_classes) const { - // For each generator in the first equivalence class, make sure that it is - // less than each of those in the logically greater equivalence classes. - (ForEachTupleElement)( - Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...), - errors}, - small_eq_class.generators); - - // Recurse so that all equivalence class combinations are checked. - (*this)(absl::move(big_eq_classes)...); - } - - ConformanceErrors* errors; -}; - -// Validate that the non-comparison binary operations required by Prof are -// correct for the result of each generator of big_eq_classes and a generator of -// the logically smaller value returned by small_gen. -template <class T, class Prof> -struct ExpectOrderedEquivalenceClasses { - template <class... BigEqClasses> - struct Impl { - template <class SmallGenerator> - void operator()(SmallGenerator small_gen) const { - (ForEachTupleElement)( - ExpectBiggerGeneratorThanEqClasses<T, Prof, SmallGenerator>{small_gen, - errors}, - big_eq_classes); - } - - std::tuple<BigEqClasses...> big_eq_classes; - ConformanceErrors* errors; - }; - - // Check that small_eq_class is logically consistent and also is logically - // less than all values in big_eq_classes. - template <class SmallEqClass, class... BigEqClasses> - void operator()(SmallEqClass small_eq_class, - BigEqClasses... big_eq_classes) const { - (ForEachTupleElement)( - Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...), - errors}, - small_eq_class.generators); - - (*this)(absl::move(big_eq_classes)...); - } - - // Terminating case of operator(). - void operator()() const {} - - ConformanceErrors* errors; -}; - -// Validate that a type meets the syntactic requirements of std::hash if the -// range of profiles requires it. -template <class T, class MinProf, class MaxProf> -struct ExpectHashable { - void operator()() const { - ExpectModelOfHashable<T, MinProf, MaxProf>(errors); - } - - ConformanceErrors* errors; -}; - -// Validate that the type `T` meets all of the requirements associated with -// `MinProf` and without going beyond the syntactic properties of `MaxProf`. -template <class T, class MinProf, class MaxProf> -struct ExpectModels { - void operator()(ConformanceErrors* errors) const { - ExpectModelOfDefaultConstructible<T, MinProf, MaxProf>(errors); - ExpectModelOfMoveConstructible<T, MinProf, MaxProf>(errors); - ExpectModelOfCopyConstructible<T, MinProf, MaxProf>(errors); - ExpectModelOfMoveAssignable<T, MinProf, MaxProf>(errors); - ExpectModelOfCopyAssignable<T, MinProf, MaxProf>(errors); - ExpectModelOfDestructible<T, MinProf, MaxProf>(errors); - ExpectModelOfEqualityComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfInequalityComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfLessThanComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfLessEqualComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfGreaterEqualComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfGreaterThanComparable<T, MinProf, MaxProf>(errors); - ExpectModelOfSwappable<T, MinProf, MaxProf>(errors); - - // Only check hashability on compilers that have a compliant default-hash. - If<!poisoned_hash_fails_instantiation()>::Invoke( - ExpectHashable<T, MinProf, MaxProf>{errors}); - } -}; - -// A metafunction that yields a Profile matching the set of properties that are -// safe to be checked (lack-of-hashability is only checked on standard library -// implementations that are standards compliant in that they provide a std::hash -// primary template that is SFINAE-friendly) -template <class LogicalProf, class T> -struct MinimalCheckableProfile { - using type = - MinimalProfiles<PropertiesOfT<LogicalProf>, - PropertiesOfT<SyntacticConformanceProfileOf< - T, !PropertiesOfT<LogicalProf>::is_hashable && - poisoned_hash_fails_instantiation() - ? CheckHashability::no - : CheckHashability::yes>>>; -}; - -// An identity metafunction -template <class T> -struct Always { - using type = T; -}; - -// Validate the T meets all of the necessary requirements of LogicalProf, with -// syntactic requirements defined by the profile range [MinProf, MaxProf]. -template <class T, class LogicalProf, class MinProf, class MaxProf, - class... EqClasses> -ConformanceErrors ExpectRegularityImpl( - OrderedEquivalenceClasses<EqClasses...> vals) { - ConformanceErrors errors((NameOf<T>())); - - If<!constexpr_instantiation_when_unevaluated()>::Invoke( - ExpectModels<T, MinProf, MaxProf>(), &errors); - - using minimal_profile = typename absl::conditional_t< - constexpr_instantiation_when_unevaluated(), Always<LogicalProf>, - MinimalCheckableProfile<LogicalProf, T>>::type; - - If<PropertiesOfT<minimal_profile>::is_default_constructible>::Invoke( - ExpectDefaultConstructWithDestruct<T>{&errors}); - - ////////////////////////////////////////////////////////////////////////////// - // Perform all comparison checks first, since later checks depend on their - // correctness. - // - // Check all of the comparisons for all values in the same equivalence - // class (equal with respect to comparison operators and hash the same). - (ForEachTupleElement)( - ExpectEquivalenceClassComparisons<T, minimal_profile>{&errors}, - vals.eq_classes); - - // Check all of the comparisons for each combination of values that are in - // different equivalence classes (not equal with respect to comparison - // operators). - absl::apply( - ExpectOrderedEquivalenceClassesComparisons<T, minimal_profile>{&errors}, - vals.eq_classes); - // - ////////////////////////////////////////////////////////////////////////////// - - // Perform remaining checks, relying on comparisons. - // TODO(calabrese) short circuit if any comparisons above failed. - (ForEachTupleElement)(ExpectEquivalenceClass<T, minimal_profile>{&errors}, - vals.eq_classes); - - absl::apply(ExpectOrderedEquivalenceClasses<T, minimal_profile>{&errors}, - vals.eq_classes); - - return errors; -} - -// A type that represents a range of profiles that are acceptable to be matched. -// -// `MinProf` is the minimum set of syntactic requirements that must be met. -// -// `MaxProf` is the maximum set of syntactic requirements that must be met. -// This maximum is particularly useful for certain "strictness" checking. Some -// examples for when this is useful: -// -// * Making sure that a type is move-only (rather than simply movable) -// -// * Making sure that a member function is *not* noexcept in cases where it -// cannot be noexcept, such as if a dependent datamember has certain -// operations that are not noexcept. -// -// * Making sure that a type tightly matches a spec, such as the standard. -// -// `LogicalProf` is the Profile for which run-time testing is to take place. -// -// Note: The reason for `LogicalProf` is because it is often the case, when -// dealing with templates, that a declaration of a given operation is specified, -// but whose body would fail to instantiate. Examples include the -// copy-constructor of a standard container when the element-type is move-only, -// or the comparison operators of a standard container when the element-type -// does not have the necessary comparison operations defined. The `LogicalProf` -// parameter allows us to capture the intent of what should be tested at -// run-time, even in the cases where syntactically it might otherwise appear as -// though the type undergoing testing supports more than it actually does. -template <class LogicalProf, class MinProf = LogicalProf, - class MaxProf = MinProf> -struct ProfileRange { - using logical_profile = LogicalProf; - using min_profile = MinProf; - using max_profile = MaxProf; -}; - -// Similar to ProfileRange except that it creates a profile range that is -// coupled with a Domain and is used when testing that a type matches exactly -// the "minimum" requirements of LogicalProf. -template <class StrictnessDomain, class LogicalProf, - class MinProf = LogicalProf, class MaxProf = MinProf> -struct StrictProfileRange { - // We do not yet support extension. - static_assert( - std::is_same<StrictnessDomain, RegularityDomain>::value, - "Currently, the only valid StrictnessDomain is RegularityDomain."); - using strictness_domain = StrictnessDomain; - using logical_profile = LogicalProf; - using min_profile = MinProf; - using max_profile = MaxProf; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction that creates a StrictProfileRange from a Domain and either a -// Profile or ProfileRange. -template <class StrictnessDomain, class ProfOrRange> -struct MakeStrictProfileRange; - -template <class StrictnessDomain, class LogicalProf> -struct MakeStrictProfileRange { - using type = StrictProfileRange<StrictnessDomain, LogicalProf>; -}; - -template <class StrictnessDomain, class LogicalProf, class MinProf, - class MaxProf> -struct MakeStrictProfileRange<StrictnessDomain, - ProfileRange<LogicalProf, MinProf, MaxProf>> { - using type = - StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>; -}; - -template <class StrictnessDomain, class ProfOrRange> -using MakeStrictProfileRangeT = - typename MakeStrictProfileRange<StrictnessDomain, ProfOrRange>::type; -// -//////////////////////////////////////////////////////////////////////////////// - -// A profile in the RegularityDomain with the strongest possible requirements. -using MostStrictProfile = - CombineProfiles<TriviallyCompleteProfile, NothrowComparableProfile>; - -// Forms a ProfileRange that treats the Profile as the bare minimum requirements -// of a type. -template <class LogicalProf, class MinProf = LogicalProf> -using LooseProfileRange = StrictProfileRange<RegularityDomain, LogicalProf, - MinProf, MostStrictProfile>; - -template <class Prof> -using MakeLooseProfileRangeT = Prof; - -//////////////////////////////////////////////////////////////////////////////// -// -// The following classes implement the metafunction ProfileRangeOfT<T> that -// takes either a Profile or ProfileRange and yields the ProfileRange to be -// used during testing. -// -template <class T, class /*Enabler*/ = void> -struct ProfileRangeOfImpl; - -template <class T> -struct ProfileRangeOfImpl<T, absl::void_t<PropertiesOfT<T>>> { - using type = LooseProfileRange<T>; -}; - -template <class T> -struct ProfileRangeOf : ProfileRangeOfImpl<T> {}; - -template <class StrictnessDomain, class LogicalProf, class MinProf, - class MaxProf> -struct ProfileRangeOf< - StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>> { - using type = - StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>; -}; - -template <class T> -using ProfileRangeOfT = typename ProfileRangeOf<T>::type; -// -//////////////////////////////////////////////////////////////////////////////// - -// Extract the logical profile of a range (what will be runtime tested). -template <class T> -using LogicalProfileOfT = typename ProfileRangeOfT<T>::logical_profile; - -// Extract the minimal syntactic profile of a range (error if not at least). -template <class T> -using MinProfileOfT = typename ProfileRangeOfT<T>::min_profile; - -// Extract the maximum syntactic profile of a range (error if more than). -template <class T> -using MaxProfileOfT = typename ProfileRangeOfT<T>::max_profile; - -//////////////////////////////////////////////////////////////////////////////// -// -template <class T> -struct IsProfileOrProfileRange : IsProfile<T>::type {}; - -template <class StrictnessDomain, class LogicalProf, class MinProf, - class MaxProf> -struct IsProfileOrProfileRange< - StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>> - : std::true_type {}; -// -//////////////////////////////////////////////////////////////////////////////// - -// TODO(calabrese): Consider naming the functions in this class the same as -// the macros (defined later on) so that auto-complete leads to the correct name -// and so that a user cannot accidentally call a function rather than the macro -// form. -template <bool ExpectSuccess, class T, class... EqClasses> -struct ExpectConformanceOf { - // Add a value to be tested. Subsequent calls to this function on the same - // object must specify logically "larger" values with respect to the - // comparison operators of the type, if any. - // - // NOTE: This function should not be called directly. A stateless lambda is - // implicitly formed and passed when using the INITIALIZER macro at the bottom - // of this file. - template <class Fun, - absl::enable_if_t<std::is_same< - ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses..., - EquivalenceClassType<Fun>> - initializer(GeneratorType<Fun> fun) && { - return { - {std::tuple_cat(absl::move(ordered_vals.eq_classes), - std::make_tuple((EquivalenceClass)(absl::move(fun))))}, - std::move(expected_failed_tests)}; - } - - template <class... TestNames, - absl::enable_if_t<!ExpectSuccess && sizeof...(EqClasses) == 0 && - absl::conjunction<std::is_convertible< - TestNames, absl::string_view>...>::value>** = - nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...> - due_to(TestNames&&... test_names) && { - (InsertEach)(&expected_failed_tests, - absl::AsciiStrToLower(absl::string_view(test_names))...); - - return {absl::move(ordered_vals), std::move(expected_failed_tests)}; - } - - template <class... TestNames, int = 0, // MSVC disambiguator - absl::enable_if_t<ExpectSuccess && sizeof...(EqClasses) == 0 && - absl::conjunction<std::is_convertible< - TestNames, absl::string_view>...>::value>** = - nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...> - due_to(TestNames&&... test_names) && { - // TODO(calabrese) Instead have DUE_TO only exist via a CRTP base. - // This would produce better errors messages than the static_assert. - static_assert(!ExpectSuccess, - "DUE_TO cannot be called when conformance is expected -- did " - "you mean to use ASSERT_NONCONFORMANCE_OF?"); - } - - // Add a value to be tested. Subsequent calls to this function on the same - // object must specify logically "larger" values with respect to the - // comparison operators of the type, if any. - // - // NOTE: This function should not be called directly. A stateful lambda is - // implicitly formed and passed when using the INITIALIZER macro at the bottom - // of this file. - template <class Fun, - absl::enable_if_t<std::is_same< - ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses..., - EquivalenceClassType<Fun>> - dont_class_directly_stateful_initializer(GeneratorType<Fun> fun) && { - return { - {std::tuple_cat(absl::move(ordered_vals.eq_classes), - std::make_tuple((EquivalenceClass)(absl::move(fun))))}, - std::move(expected_failed_tests)}; - } - - // Add a set of value to be tested, where each value is equal with respect to - // the comparison operators and std::hash specialization, if defined. - template < - class... Funs, - absl::void_t<absl::enable_if_t<std::is_same< - ResultOfGeneratorT<GeneratorType<Funs>>, T>::value>...>** = nullptr> - ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses..., - EquivalenceClassType<Funs...>> - equivalence_class(GeneratorType<Funs>... funs) && { - return {{std::tuple_cat( - absl::move(ordered_vals.eq_classes), - std::make_tuple((EquivalenceClass)(absl::move(funs)...)))}, - std::move(expected_failed_tests)}; - } - - // Execute the tests for the captured set of values, strictly matching a range - // of expected profiles in a given domain. - template < - class ProfRange, - absl::enable_if_t<IsProfileOrProfileRange<ProfRange>::value>** = nullptr> - ABSL_MUST_USE_RESULT ::testing::AssertionResult with_strict_profile( - ProfRange /*profile*/) { - ConformanceErrors test_result = - (ExpectRegularityImpl< - T, LogicalProfileOfT<ProfRange>, MinProfileOfT<ProfRange>, - MaxProfileOfT<ProfRange>>)(absl::move(ordered_vals)); - - return ExpectSuccess ? test_result.assertionResult() - : test_result.expectFailedTests(expected_failed_tests); - } - - // Execute the tests for the captured set of values, loosely matching a range - // of expected profiles (loose in that an interface is allowed to be more - // refined that a profile suggests, such as a type having a noexcept copy - // constructor when all that is required is that the copy constructor exists). - template <class Prof, absl::enable_if_t<IsProfile<Prof>::value>** = nullptr> - ABSL_MUST_USE_RESULT ::testing::AssertionResult with_loose_profile( - Prof /*profile*/) { - ConformanceErrors test_result = - (ExpectRegularityImpl< - T, Prof, Prof, - CombineProfiles<TriviallyCompleteProfile, - NothrowComparableProfile>>)(absl:: - move(ordered_vals)); - - return ExpectSuccess ? test_result.assertionResult() - : test_result.expectFailedTests(expected_failed_tests); - } - - OrderedEquivalenceClasses<EqClasses...> ordered_vals; - std::set<std::string> expected_failed_tests; -}; - -template <class T> -using ExpectConformanceOfType = ExpectConformanceOf</*ExpectSuccess=*/true, T>; - -template <class T> -using ExpectNonconformanceOfType = - ExpectConformanceOf</*ExpectSuccess=*/false, T>; - -struct EquivalenceClassMaker { - // TODO(calabrese) Constrain to callable - template <class Fun> - static GeneratorType<Fun> initializer(GeneratorType<Fun> fun) { - return fun; - } -}; - -// A top-level macro that begins the builder pattern. -// -// The argument here takes the datatype to be tested. -#define ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(...) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if ABSL_INTERNAL_LPAREN \ - const ::testing::AssertionResult gtest_ar = \ - ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectConformanceOfType< \ - __VA_ARGS__>() - -// Akin to ASSERT_CONFORMANCE_OF except that it expects failure and tries to -// match text. -#define ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(...) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if ABSL_INTERNAL_LPAREN \ - const ::testing::AssertionResult gtest_ar = \ - ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectNonconformanceOfType< \ - __VA_ARGS__>() - -//////////////////////////////////////////////////////////////////////////////// -// NOTE: The following macros look like they are recursive, but are not (macros -// cannot recurse). These actually refer to member functions of the same name. -// This is done intentionally so that a user cannot accidentally invoke a -// member function of the conformance-testing suite without going through the -// macro. -//////////////////////////////////////////////////////////////////////////////// - -// Specify expected test failures as comma-separated strings. -#define DUE_TO(...) due_to(__VA_ARGS__) - -// Specify a value to be tested. -// -// Note: Internally, this takes an expression and turns it into the return value -// of lambda that captures no data. The expression is stringized during -// preprocessing so that it can be used in error reports. -#define INITIALIZER(...) \ - initializer(::absl::types_internal::Generator( \ - [] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__))) - -// Specify a value to be tested. -// -// Note: Internally, this takes an expression and turns it into the return value -// of lambda that captures data by reference. The expression is stringized -// during preprocessing so that it can be used in error reports. -#define STATEFUL_INITIALIZER(...) \ - stateful_initializer(::absl::types_internal::Generator( \ - [&] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__))) - -// Used in the builder-pattern. -// -// Takes a series of INITIALIZER and/or STATEFUL_INITIALIZER invocations and -// forwards them along to be tested, grouping them such that the testing suite -// knows that they are supposed to represent the same logical value (the values -// compare the same, hash the same, etc.). -#define EQUIVALENCE_CLASS(...) \ - equivalence_class(ABSL_INTERNAL_TRANSFORM_ARGS( \ - ABSL_INTERNAL_PREPEND_EQ_MAKER, __VA_ARGS__)) - -// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern. -// It takes a Profile as its argument. -// -// This executes the tests and allows types that are "more referined" than the -// profile specifies, but not less. For instance, if the Profile specifies -// noexcept copy-constructiblity, the test will fail if the copy-constructor is -// not noexcept, however, it will succeed if the copy constructor is trivial. -// -// This is useful for testing that a type meets some minimum set of -// requirements. -#define WITH_LOOSE_PROFILE(...) \ - with_loose_profile( \ - ::absl::types_internal::MakeLooseProfileRangeT<__VA_ARGS__>()) \ - ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN; \ - else GTEST_FATAL_FAILURE_(gtest_ar.failure_message()) // NOLINT - -// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern. -// It takes a Domain and a Profile as its arguments. -// -// This executes the tests and disallows types that differ at all from the -// properties of the Profile. For instance, if the Profile specifies noexcept -// copy-constructiblity, the test will fail if the copy constructor is trivial. -// -// This is useful for testing that a type does not do anything more than a -// specification requires, such as to minimize things like Hyrum's Law, or more -// commonly, to prevent a type from being "accidentally" copy-constructible in -// a way that may produce incorrect results, simply because the user forget to -// delete that operation. -#define WITH_STRICT_PROFILE(...) \ - with_strict_profile( \ - ::absl::types_internal::MakeStrictProfileRangeT<__VA_ARGS__>()) \ - ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN; \ - else GTEST_FATAL_FAILURE_(gtest_ar.failure_message()) // NOLINT - -// Internal macro that is used in the internals of the EDSL when forming -// equivalence classes. -#define ABSL_INTERNAL_PREPEND_EQ_MAKER(arg) \ - ::absl::types_internal::EquivalenceClassMaker().arg - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h b/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h deleted file mode 100644 index 00775f960c36..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_ -#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_ - -// Checks to determine whether or not we can use abi::__cxa_demangle -#if (defined(__ANDROID__) || defined(ANDROID)) && !defined(OS_ANDROID) -#define ABSL_INTERNAL_OS_ANDROID -#endif - -// We support certain compilers only. See demangle.h for details. -#if defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__)) -#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0 -#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \ - !defined(__mips__) -#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1 -#elif defined(__clang__) && !defined(_MSC_VER) -#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1 -#else -#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0 -#endif - -#include <tuple> -#include <type_traits> -#include <utility> - -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" -#include "absl/utility/utility.h" - -#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE -#include <cxxabi.h> - -#include <cstdlib> -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace types_internal { - -// Return a readable name for type T. -template <class T> -absl::string_view NameOfImpl() { -// TODO(calabrese) Investigate using debugging:internal_demangle as a fallback. -#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE - int status = 0; - char* demangled_name = nullptr; - - demangled_name = - abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status); - - if (status == 0 && demangled_name != nullptr) { - return demangled_name; - } else { - return typeid(T).name(); - } -#else - return typeid(T).name(); -#endif - // NOTE: We intentionally leak demangled_name so that it remains valid - // throughout the remainder of the program. -} - -// Given a type, returns as nice of a type name as we can produce (demangled). -// -// Note: This currently strips cv-qualifiers and references, but that is okay -// because we only use this internally with unqualified object types. -template <class T> -std::string NameOf() { - static const absl::string_view result = NameOfImpl<T>(); - return std::string(result); -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Metafunction to check if a type is callable with no explicit arguments -template <class Fun, class /*Enabler*/ = void> -struct IsNullaryCallableImpl : std::false_type {}; - -template <class Fun> -struct IsNullaryCallableImpl< - Fun, absl::void_t<decltype(std::declval<const Fun&>()())>> - : std::true_type { - using result_type = decltype(std::declval<const Fun&>()()); - - template <class ValueType> - using for_type = std::is_same<ValueType, result_type>; - - using void_if_true = void; -}; - -template <class Fun> -struct IsNullaryCallable : IsNullaryCallableImpl<Fun> {}; -// -//////////////////////////////////////////////////////////////////////////////// - -// A type that contains a function object that returns an instance of a type -// that is undergoing conformance testing. This function is required to always -// return the same value upon invocation. -template <class Fun> -struct GeneratorType; - -// A type that contains a tuple of GeneratorType<Fun> where each Fun has the -// same return type. The result of each of the different generators should all -// be equal values, though the underlying object representation may differ (such -// as if one returns 0.0 and another return -0.0, or if one returns an empty -// vector and another returns an empty vector with a different capacity. -template <class... Funs> -struct EquivalenceClassType; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction to check if a type is a specialization of EquivalenceClassType -template <class T> -struct IsEquivalenceClass : std::false_type {}; - -template <> -struct IsEquivalenceClass<EquivalenceClassType<>> : std::true_type { - using self = IsEquivalenceClass; - - // A metafunction to check if this EquivalenceClassType is a valid - // EquivalenceClassType for a type `ValueType` that is undergoing testing - template <class ValueType> - using for_type = std::true_type; -}; - -template <class Head, class... Tail> -struct IsEquivalenceClass<EquivalenceClassType<Head, Tail...>> - : std::true_type { - using self = IsEquivalenceClass; - - // The type undergoing conformance testing that this EquivalenceClass - // corresponds to - using result_type = typename IsNullaryCallable<Head>::result_type; - - // A metafunction to check if this EquivalenceClassType is a valid - // EquivalenceClassType for a type `ValueType` that is undergoing testing - template <class ValueType> - using for_type = std::is_same<ValueType, result_type>; -}; -// -//////////////////////////////////////////////////////////////////////////////// - -// A type that contains an ordered series of EquivalenceClassTypes, where the -// the function object of each underlying GeneratorType has the same return type -// -// These equivalence classes are required to be in a logical ascending order -// that is consistent with comparison operators that are defined for the return -// type of each GeneratorType, if any. -template <class... EqClasses> -struct OrderedEquivalenceClasses; - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction to determine the return type of the function object contained -// in a GeneratorType specialization. -template <class T> -struct ResultOfGenerator {}; - -template <class Fun> -struct ResultOfGenerator<GeneratorType<Fun>> { - using type = decltype(std::declval<const Fun&>()()); -}; - -template <class Fun> -using ResultOfGeneratorT = typename ResultOfGenerator<GeneratorType<Fun>>::type; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction that yields true iff each of Funs is a GeneratorType -// specialization and they all contain functions with the same return type -template <class /*Enabler*/, class... Funs> -struct AreGeneratorsWithTheSameReturnTypeImpl : std::false_type {}; - -template <> -struct AreGeneratorsWithTheSameReturnTypeImpl<void> : std::true_type {}; - -template <class Head, class... Tail> -struct AreGeneratorsWithTheSameReturnTypeImpl< - typename std::enable_if<absl::conjunction<std::is_same< - ResultOfGeneratorT<Head>, ResultOfGeneratorT<Tail>>...>::value>::type, - Head, Tail...> : std::true_type {}; - -template <class... Funs> -struct AreGeneratorsWithTheSameReturnType - : AreGeneratorsWithTheSameReturnTypeImpl<void, Funs...>::type {}; -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// A metafunction that yields true iff each of Funs is an EquivalenceClassType -// specialization and they all contain GeneratorType specializations that have -// the same return type -template <class... EqClasses> -struct AreEquivalenceClassesOfTheSameType { - static_assert(sizeof...(EqClasses) != sizeof...(EqClasses), ""); -}; - -template <> -struct AreEquivalenceClassesOfTheSameType<> : std::true_type { - using self = AreEquivalenceClassesOfTheSameType; - - // Metafunction to check that a type is the same as all of the equivalence - // classes, if any. - // Note: In this specialization there are no equivalence classes, so the - // value type is always compatible. - template <class /*ValueType*/> - using for_type = std::true_type; -}; - -template <class... Funs> -struct AreEquivalenceClassesOfTheSameType<EquivalenceClassType<Funs...>> - : std::true_type { - using self = AreEquivalenceClassesOfTheSameType; - - // Metafunction to check that a type is the same as all of the equivalence - // classes, if any. - template <class ValueType> - using for_type = typename IsEquivalenceClass< - EquivalenceClassType<Funs...>>::template for_type<ValueType>; -}; - -template <class... TailEqClasses> -struct AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<>, EquivalenceClassType<>, TailEqClasses...> - : AreEquivalenceClassesOfTheSameType<TailEqClasses...>::self {}; - -template <class HeadNextFun, class... TailNextFuns, class... TailEqClasses> -struct AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<>, EquivalenceClassType<HeadNextFun, TailNextFuns...>, - TailEqClasses...> - : AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadNextFun, TailNextFuns...>, - TailEqClasses...>::self {}; - -template <class HeadHeadFun, class... TailHeadFuns, class... TailEqClasses> -struct AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, EquivalenceClassType<>, - TailEqClasses...> - : AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, - TailEqClasses...>::self {}; - -template <class HeadHeadFun, class... TailHeadFuns, class HeadNextFun, - class... TailNextFuns, class... TailEqClasses> -struct AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, - EquivalenceClassType<HeadNextFun, TailNextFuns...>, TailEqClasses...> - : absl::conditional_t< - IsNullaryCallable<HeadNextFun>::template for_type< - typename IsNullaryCallable<HeadHeadFun>::result_type>::value, - AreEquivalenceClassesOfTheSameType< - EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, - TailEqClasses...>, - std::false_type> {}; -// -//////////////////////////////////////////////////////////////////////////////// - -// Execute a function for each passed-in parameter. -template <class Fun, class... Cases> -void ForEachParameter(const Fun& fun, const Cases&... cases) { - const std::initializer_list<bool> results = { - (static_cast<void>(fun(cases)), true)...}; - - (void)results; -} - -// Execute a function on each passed-in parameter (using a bound function). -template <class Fun> -struct ForEachParameterFun { - template <class... T> - void operator()(const T&... cases) const { - (ForEachParameter)(fun, cases...); - } - - Fun fun; -}; - -// Execute a function on each element of a tuple. -template <class Fun, class Tup> -void ForEachTupleElement(const Fun& fun, const Tup& tup) { - absl::apply(ForEachParameterFun<Fun>{fun}, tup); -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Execute a function for each combination of two elements of a tuple, including -// combinations of an element with itself. -template <class Fun, class... T> -struct ForEveryTwoImpl { - template <class Lhs> - struct WithBoundLhs { - template <class Rhs> - void operator()(const Rhs& rhs) const { - fun(lhs, rhs); - } - - Fun fun; - Lhs lhs; - }; - - template <class Lhs> - void operator()(const Lhs& lhs) const { - (ForEachTupleElement)(WithBoundLhs<Lhs>{fun, lhs}, args); - } - - Fun fun; - std::tuple<T...> args; -}; - -template <class Fun, class... T> -void ForEveryTwo(const Fun& fun, std::tuple<T...> args) { - (ForEachTupleElement)(ForEveryTwoImpl<Fun, T...>{fun, args}, args); -} -// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// -// Insert all values into an associative container -template<class Container> -void InsertEach(Container* cont) { -} - -template<class Container, class H, class... T> -void InsertEach(Container* cont, H&& head, T&&... tail) { - cont->insert(head); - (InsertEach)(cont, tail...); -} -// -//////////////////////////////////////////////////////////////////////////////// -// A template with a nested "Invoke" static-member-function that executes a -// passed-in Callable when `Condition` is true, otherwise it ignores the -// Callable. This is useful for executing a function object with a condition -// that corresponds to whether or not the Callable can be safely instantiated. -// It has some overlapping uses with C++17 `if constexpr`. -template <bool Condition> -struct If; - -template <> -struct If</*Condition =*/false> { - template <class Fun, class... P> - static void Invoke(const Fun& /*fun*/, P&&... /*args*/) {} -}; - -template <> -struct If</*Condition =*/true> { - template <class Fun, class... P> - static void Invoke(const Fun& fun, P&&... args) { - // TODO(calabrese) Use std::invoke equivalent instead of function-call. - fun(absl::forward<P>(args)...); - } -}; - -// -// ABSL_INTERNAL_STRINGIZE(...) -// -// This variadic macro transforms its arguments into a c-string literal after -// expansion. -// -// Example: -// -// ABSL_INTERNAL_STRINGIZE(std::array<int, 10>) -// -// Results in: -// -// "std::array<int, 10>" -#define ABSL_INTERNAL_STRINGIZE(...) ABSL_INTERNAL_STRINGIZE_IMPL((__VA_ARGS__)) -#define ABSL_INTERNAL_STRINGIZE_IMPL(arg) ABSL_INTERNAL_STRINGIZE_IMPL2 arg -#define ABSL_INTERNAL_STRINGIZE_IMPL2(...) #__VA_ARGS__ - -} // namespace types_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_testing_test.cc b/third_party/abseil_cpp/absl/types/internal/conformance_testing_test.cc deleted file mode 100644 index cf262fa6c222..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/conformance_testing_test.cc +++ /dev/null @@ -1,1556 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/types/internal/conformance_testing.h" - -#include <new> -#include <type_traits> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/meta/type_traits.h" -#include "absl/types/internal/conformance_aliases.h" -#include "absl/types/internal/conformance_profile.h" - -namespace { - -namespace ti = absl::types_internal; - -template <class T> -using DefaultConstructibleWithNewImpl = decltype(::new (std::nothrow) T); - -template <class T> -using DefaultConstructibleWithNew = - absl::type_traits_internal::is_detected<DefaultConstructibleWithNewImpl, T>; - -template <class T> -using MoveConstructibleWithNewImpl = - decltype(::new (std::nothrow) T(std::declval<T>())); - -template <class T> -using MoveConstructibleWithNew = - absl::type_traits_internal::is_detected<MoveConstructibleWithNewImpl, T>; - -template <class T> -using CopyConstructibleWithNewImpl = - decltype(::new (std::nothrow) T(std::declval<const T&>())); - -template <class T> -using CopyConstructibleWithNew = - absl::type_traits_internal::is_detected<CopyConstructibleWithNewImpl, T>; - -template <class T, - class Result = - std::integral_constant<bool, noexcept(::new (std::nothrow) T)>> -using NothrowDefaultConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowDefaultConstructibleWithNew = - absl::type_traits_internal::is_detected< - NothrowDefaultConstructibleWithNewImpl, T>; - -template <class T, - class Result = std::integral_constant< - bool, noexcept(::new (std::nothrow) T(std::declval<T>()))>> -using NothrowMoveConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowMoveConstructibleWithNew = - absl::type_traits_internal::is_detected<NothrowMoveConstructibleWithNewImpl, - T>; - -template <class T, - class Result = std::integral_constant< - bool, noexcept(::new (std::nothrow) T(std::declval<const T&>()))>> -using NothrowCopyConstructibleWithNewImpl = - typename std::enable_if<Result::value>::type; - -template <class T> -using NothrowCopyConstructibleWithNew = - absl::type_traits_internal::is_detected<NothrowCopyConstructibleWithNewImpl, - T>; - -// NOTE: ?: is used to verify contextually-convertible to bool and not simply -// implicit or explicit convertibility. -#define ABSL_INTERNAL_COMPARISON_OP_EXPR(op) \ - ((std::declval<const T&>() op std::declval<const T&>()) ? true : true) - -#define ABSL_INTERNAL_COMPARISON_OP_TRAIT(name, op) \ - template <class T> \ - using name##Impl = decltype(ABSL_INTERNAL_COMPARISON_OP_EXPR(op)); \ - \ - template <class T> \ - using name = absl::type_traits_internal::is_detected<name##Impl, T>; \ - \ - template <class T, \ - class Result = std::integral_constant< \ - bool, noexcept(ABSL_INTERNAL_COMPARISON_OP_EXPR(op))>> \ - using Nothrow##name##Impl = typename std::enable_if<Result::value>::type; \ - \ - template <class T> \ - using Nothrow##name = \ - absl::type_traits_internal::is_detected<Nothrow##name##Impl, T> - -ABSL_INTERNAL_COMPARISON_OP_TRAIT(EqualityComparable, ==); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(InequalityComparable, !=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessThanComparable, <); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessEqualComparable, <=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterEqualComparable, >=); -ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterThanComparable, >); - -#undef ABSL_INTERNAL_COMPARISON_OP_TRAIT - -template <class T> -class ProfileTest : public ::testing::Test {}; - -TYPED_TEST_SUITE_P(ProfileTest); - -TYPED_TEST_P(ProfileTest, HasAppropriateConstructionProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::default_constructible_support, - expected_props::default_constructible_support); - - EXPECT_EQ(props::move_constructible_support, - expected_props::move_constructible_support); - - EXPECT_EQ(props::copy_constructible_support, - expected_props::copy_constructible_support); - - EXPECT_EQ(props::destructible_support, expected_props::destructible_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::default_constructible_support, - expected_props::default_constructible_support); - - EXPECT_EQ(arch_props::move_constructible_support, - expected_props::move_constructible_support); - - EXPECT_EQ(arch_props::copy_constructible_support, - expected_props::copy_constructible_support); - - EXPECT_EQ(arch_props::destructible_support, - expected_props::destructible_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Default constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::default_constructible_support, - expected_props::default_constructible_support); - - switch (expected_props::default_constructible_support) { - case ti::default_constructible::maybe: - EXPECT_FALSE(DefaultConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_default_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - } - break; - case ti::default_constructible::yes: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - } - break; - case ti::default_constructible::nothrow: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - } - } - break; - case ti::default_constructible::trivial: - EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_default_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_default_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Move constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::move_constructible_support, - expected_props::move_constructible_support); - - switch (expected_props::move_constructible_support) { - case ti::move_constructible::maybe: - EXPECT_FALSE(MoveConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_move_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - } - break; - case ti::move_constructible::yes: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - } - break; - case ti::move_constructible::nothrow: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - } - } - break; - case ti::move_constructible::trivial: - EXPECT_TRUE(MoveConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_move_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_move_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Copy constructor checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::copy_constructible_support, - expected_props::copy_constructible_support); - - switch (expected_props::copy_constructible_support) { - case ti::copy_constructible::maybe: - EXPECT_FALSE(CopyConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_FALSE(std::is_copy_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - } - break; - case ti::copy_constructible::yes: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - } - break; - case ti::copy_constructible::nothrow: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value); - - // Constructor traits also check the destructor. - if (std::is_nothrow_destructible<arch>::value) { - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - } - } - break; - case ti::copy_constructible::trivial: - EXPECT_TRUE(CopyConstructibleWithNew<arch>::value); - EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value); - - // Standard constructible traits depend on the destructor. - if (std::is_destructible<arch>::value) { - EXPECT_TRUE(std::is_copy_constructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value); - - // Constructor triviality traits require trivially destructible types. - if (absl::is_trivially_destructible<arch>::value) { - EXPECT_TRUE(absl::is_trivially_copy_constructible<arch>::value); - } - } - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Destructible checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::destructible_support, expected_props::destructible_support); - - switch (expected_props::destructible_support) { - case ti::destructible::maybe: - EXPECT_FALSE(std::is_destructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::yes: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_FALSE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::nothrow: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_destructible<arch>::value); - EXPECT_FALSE(absl::is_trivially_destructible<arch>::value); - break; - case ti::destructible::trivial: - EXPECT_TRUE(std::is_destructible<arch>::value); - EXPECT_TRUE(std::is_nothrow_destructible<arch>::value); - EXPECT_TRUE(absl::is_trivially_destructible<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateAssignmentProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::move_assignable_support, - expected_props::move_assignable_support); - - EXPECT_EQ(props::copy_assignable_support, - expected_props::copy_assignable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::move_assignable_support, - expected_props::move_assignable_support); - - EXPECT_EQ(arch_props::copy_assignable_support, - expected_props::copy_assignable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Move assignment checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::move_assignable_support, - expected_props::move_assignable_support); - - switch (expected_props::move_assignable_support) { - case ti::move_assignable::maybe: - EXPECT_FALSE(std::is_move_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::yes: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::nothrow: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value); - break; - case ti::move_assignable::trivial: - EXPECT_TRUE(std::is_move_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value); - EXPECT_TRUE(absl::is_trivially_move_assignable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Copy assignment checks // - ////////////////////////////////////////////////////////////////////////////// - EXPECT_EQ(props::copy_assignable_support, - expected_props::copy_assignable_support); - - switch (expected_props::copy_assignable_support) { - case ti::copy_assignable::maybe: - EXPECT_FALSE(std::is_copy_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::yes: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::nothrow: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value); - break; - case ti::copy_assignable::trivial: - EXPECT_TRUE(std::is_copy_assignable<arch>::value); - EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateComparisonProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::equality_comparable_support, - expected_props::equality_comparable_support); - - EXPECT_EQ(props::inequality_comparable_support, - expected_props::inequality_comparable_support); - - EXPECT_EQ(props::less_than_comparable_support, - expected_props::less_than_comparable_support); - - EXPECT_EQ(props::less_equal_comparable_support, - expected_props::less_equal_comparable_support); - - EXPECT_EQ(props::greater_equal_comparable_support, - expected_props::greater_equal_comparable_support); - - EXPECT_EQ(props::greater_than_comparable_support, - expected_props::greater_than_comparable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::equality_comparable_support, - expected_props::equality_comparable_support); - - EXPECT_EQ(arch_props::inequality_comparable_support, - expected_props::inequality_comparable_support); - - EXPECT_EQ(arch_props::less_than_comparable_support, - expected_props::less_than_comparable_support); - - EXPECT_EQ(arch_props::less_equal_comparable_support, - expected_props::less_equal_comparable_support); - - EXPECT_EQ(arch_props::greater_equal_comparable_support, - expected_props::greater_equal_comparable_support); - - EXPECT_EQ(arch_props::greater_than_comparable_support, - expected_props::greater_than_comparable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Equality comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::equality_comparable_support) { - case ti::equality_comparable::maybe: - EXPECT_FALSE(EqualityComparable<arch>::value); - EXPECT_FALSE(NothrowEqualityComparable<arch>::value); - break; - case ti::equality_comparable::yes: - EXPECT_TRUE(EqualityComparable<arch>::value); - EXPECT_FALSE(NothrowEqualityComparable<arch>::value); - break; - case ti::equality_comparable::nothrow: - EXPECT_TRUE(EqualityComparable<arch>::value); - EXPECT_TRUE(NothrowEqualityComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Inequality comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::inequality_comparable_support) { - case ti::inequality_comparable::maybe: - EXPECT_FALSE(InequalityComparable<arch>::value); - EXPECT_FALSE(NothrowInequalityComparable<arch>::value); - break; - case ti::inequality_comparable::yes: - EXPECT_TRUE(InequalityComparable<arch>::value); - EXPECT_FALSE(NothrowInequalityComparable<arch>::value); - break; - case ti::inequality_comparable::nothrow: - EXPECT_TRUE(InequalityComparable<arch>::value); - EXPECT_TRUE(NothrowInequalityComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Less than comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::less_than_comparable_support) { - case ti::less_than_comparable::maybe: - EXPECT_FALSE(LessThanComparable<arch>::value); - EXPECT_FALSE(NothrowLessThanComparable<arch>::value); - break; - case ti::less_than_comparable::yes: - EXPECT_TRUE(LessThanComparable<arch>::value); - EXPECT_FALSE(NothrowLessThanComparable<arch>::value); - break; - case ti::less_than_comparable::nothrow: - EXPECT_TRUE(LessThanComparable<arch>::value); - EXPECT_TRUE(NothrowLessThanComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Less equal comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::less_equal_comparable_support) { - case ti::less_equal_comparable::maybe: - EXPECT_FALSE(LessEqualComparable<arch>::value); - EXPECT_FALSE(NothrowLessEqualComparable<arch>::value); - break; - case ti::less_equal_comparable::yes: - EXPECT_TRUE(LessEqualComparable<arch>::value); - EXPECT_FALSE(NothrowLessEqualComparable<arch>::value); - break; - case ti::less_equal_comparable::nothrow: - EXPECT_TRUE(LessEqualComparable<arch>::value); - EXPECT_TRUE(NothrowLessEqualComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Greater equal comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::greater_equal_comparable_support) { - case ti::greater_equal_comparable::maybe: - EXPECT_FALSE(GreaterEqualComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value); - break; - case ti::greater_equal_comparable::yes: - EXPECT_TRUE(GreaterEqualComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value); - break; - case ti::greater_equal_comparable::nothrow: - EXPECT_TRUE(GreaterEqualComparable<arch>::value); - EXPECT_TRUE(NothrowGreaterEqualComparable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Greater than comparable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::greater_than_comparable_support) { - case ti::greater_than_comparable::maybe: - EXPECT_FALSE(GreaterThanComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value); - break; - case ti::greater_than_comparable::yes: - EXPECT_TRUE(GreaterThanComparable<arch>::value); - EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value); - break; - case ti::greater_than_comparable::nothrow: - EXPECT_TRUE(GreaterThanComparable<arch>::value); - EXPECT_TRUE(NothrowGreaterThanComparable<arch>::value); - break; - } -} - -TYPED_TEST_P(ProfileTest, HasAppropriateAuxilliaryProperties) { - using profile = typename TypeParam::profile; - using arch = typename TypeParam::arch; - using expected_profile = typename TypeParam::expected_profile; - - using props = ti::PropertiesOfT<profile>; - using arch_props = ti::PropertiesOfArchetypeT<arch>; - using expected_props = ti::PropertiesOfT<expected_profile>; - - // Make sure all of the properties are as expected. - // There are seemingly redundant tests here to make it easier to diagnose - // the specifics of the failure if something were to go wrong. - EXPECT_TRUE((std::is_same<props, arch_props>::value)); - EXPECT_TRUE((std::is_same<props, expected_props>::value)); - EXPECT_TRUE((std::is_same<arch_props, expected_props>::value)); - - EXPECT_EQ(props::swappable_support, expected_props::swappable_support); - - EXPECT_EQ(props::hashable_support, expected_props::hashable_support); - - // Avoid additional error message noise when profile and archetype match with - // each other but were not what was expected. - if (!std::is_same<props, arch_props>::value) { - EXPECT_EQ(arch_props::swappable_support, expected_props::swappable_support); - - EXPECT_EQ(arch_props::hashable_support, expected_props::hashable_support); - } - - ////////////////////////////////////////////////////////////////////////////// - // Swappable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::swappable_support) { - case ti::swappable::maybe: - EXPECT_FALSE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - case ti::swappable::yes: - EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - case ti::swappable::nothrow: - EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value); - EXPECT_TRUE(absl::type_traits_internal::IsNothrowSwappable<arch>::value); - break; - } - - ////////////////////////////////////////////////////////////////////////////// - // Hashable checks // - ////////////////////////////////////////////////////////////////////////////// - switch (expected_props::hashable_support) { - case ti::hashable::maybe: -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - EXPECT_FALSE(absl::type_traits_internal::IsHashable<arch>::value); -#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - break; - case ti::hashable::yes: - EXPECT_TRUE(absl::type_traits_internal::IsHashable<arch>::value); - break; - } -} - -REGISTER_TYPED_TEST_SUITE_P(ProfileTest, HasAppropriateConstructionProperties, - HasAppropriateAssignmentProperties, - HasAppropriateComparisonProperties, - HasAppropriateAuxilliaryProperties); - -template <class Profile, class Arch, class ExpectedProfile> -struct ProfileAndExpectation { - using profile = Profile; - using arch = Arch; - using expected_profile = ExpectedProfile; -}; - -using CoreProfilesToTest = ::testing::Types< - // The terminating case of combine (all properties are "maybe"). - ProfileAndExpectation<ti::CombineProfiles<>, - ti::Archetype<ti::CombineProfiles<>>, - ti::ConformanceProfile<>>, - - // Core default constructor profiles - ProfileAndExpectation< - ti::HasDefaultConstructorProfile, ti::HasDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowDefaultConstructorProfile, - ti::HasNothrowDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialDefaultConstructorProfile, - ti::HasTrivialDefaultConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::trivial>>, - - // Core move constructor profiles - ProfileAndExpectation< - ti::HasMoveConstructorProfile, ti::HasMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowMoveConstructorProfile, - ti::HasNothrowMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialMoveConstructorProfile, - ti::HasTrivialMoveConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::trivial>>, - - // Core copy constructor profiles - ProfileAndExpectation< - ti::HasCopyConstructorProfile, ti::HasCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowCopyConstructorProfile, - ti::HasNothrowCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialCopyConstructorProfile, - ti::HasTrivialCopyConstructorArchetype, - ti::ConformanceProfile<ti::default_constructible::maybe, - ti::move_constructible::maybe, - ti::copy_constructible::trivial>>, - - // Core move assignment profiles - ProfileAndExpectation< - ti::HasMoveAssignProfile, ti::HasMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::yes>>, - ProfileAndExpectation< - ti::HasNothrowMoveAssignProfile, ti::HasNothrowMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialMoveAssignProfile, ti::HasTrivialMoveAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::trivial>>, - - // Core copy assignment profiles - ProfileAndExpectation< - ti::HasCopyAssignProfile, ti::HasCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::yes>>, - ProfileAndExpectation< - ti::HasNothrowCopyAssignProfile, ti::HasNothrowCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialCopyAssignProfile, ti::HasTrivialCopyAssignArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::trivial>>, - - // Core destructor profiles - ProfileAndExpectation< - ti::HasDestructorProfile, ti::HasDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::yes>>, - ProfileAndExpectation< - ti::HasNothrowDestructorProfile, ti::HasNothrowDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - ProfileAndExpectation< - ti::HasTrivialDestructorProfile, ti::HasTrivialDestructorArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::trivial>>, - - // Core equality comparable profiles - ProfileAndExpectation< - ti::HasEqualityProfile, ti::HasEqualityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowEqualityProfile, ti::HasNothrowEqualityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow>>, - - // Core inequality comparable profiles - ProfileAndExpectation< - ti::HasInequalityProfile, ti::HasInequalityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowInequalityProfile, ti::HasNothrowInequalityArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, - ti::inequality_comparable::nothrow>>, - - // Core less than comparable profiles - ProfileAndExpectation< - ti::HasLessThanProfile, ti::HasLessThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowLessThanProfile, ti::HasNothrowLessThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::nothrow>>, - - // Core less equal comparable profiles - ProfileAndExpectation< - ti::HasLessEqualProfile, ti::HasLessEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowLessEqualProfile, ti::HasNothrowLessEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, - ti::less_equal_comparable::nothrow>>, - - // Core greater equal comparable profiles - ProfileAndExpectation< - ti::HasGreaterEqualProfile, ti::HasGreaterEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowGreaterEqualProfile, ti::HasNothrowGreaterEqualArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::nothrow>>, - - // Core greater than comparable profiles - ProfileAndExpectation< - ti::HasGreaterThanProfile, ti::HasGreaterThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::yes>>, - ProfileAndExpectation< - ti::HasNothrowGreaterThanProfile, ti::HasNothrowGreaterThanArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::nothrow>>, - - // Core swappable profiles - ProfileAndExpectation< - ti::HasSwapProfile, ti::HasSwapArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::yes>>, - ProfileAndExpectation< - ti::HasNothrowSwapProfile, ti::HasNothrowSwapArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // Core hashable profiles - ProfileAndExpectation< - ti::HasStdHashSpecializationProfile, - ti::HasStdHashSpecializationArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::maybe, - ti::hashable::yes>>>; - -using CommonProfilesToTest = ::testing::Types< - // NothrowMoveConstructible - ProfileAndExpectation< - ti::NothrowMoveConstructibleProfile, - ti::NothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // CopyConstructible - ProfileAndExpectation< - ti::CopyConstructibleProfile, ti::CopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // NothrowMovable - ProfileAndExpectation< - ti::NothrowMovableProfile, ti::NothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // Value - ProfileAndExpectation< - ti::ValueProfile, ti::ValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - //////////////////////////////////////////////////////////////////////////// - // Common but also DefaultConstructible // - //////////////////////////////////////////////////////////////////////////// - - // DefaultConstructibleNothrowMoveConstructible - ProfileAndExpectation< - ti::DefaultConstructibleNothrowMoveConstructibleProfile, - ti::DefaultConstructibleNothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // DefaultConstructibleCopyConstructible - ProfileAndExpectation< - ti::DefaultConstructibleCopyConstructibleProfile, - ti::DefaultConstructibleCopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow>>, - - // DefaultConstructibleNothrowMovable - ProfileAndExpectation< - ti::DefaultConstructibleNothrowMovableProfile, - ti::DefaultConstructibleNothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - // DefaultConstructibleValue - ProfileAndExpectation< - ti::DefaultConstructibleValueProfile, - ti::DefaultConstructibleValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::yes, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>>; - -using ComparableHelpersProfilesToTest = ::testing::Types< - // Equatable - ProfileAndExpectation< - ti::EquatableProfile, ti::EquatableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes, ti::inequality_comparable::yes>>, - - // Comparable - ProfileAndExpectation< - ti::ComparableProfile, ti::ComparableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // NothrowEquatable - ProfileAndExpectation< - ti::NothrowEquatableProfile, ti::NothrowEquatableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow, - ti::inequality_comparable::nothrow>>, - - // NothrowComparable - ProfileAndExpectation< - ti::NothrowComparableProfile, ti::NothrowComparableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::maybe, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::maybe, - ti::equality_comparable::nothrow, - ti::inequality_comparable::nothrow, - ti::less_than_comparable::nothrow, - ti::less_equal_comparable::nothrow, - ti::greater_equal_comparable::nothrow, - ti::greater_than_comparable::nothrow>>>; - -using CommonComparableProfilesToTest = ::testing::Types< - // ComparableNothrowMoveConstructible - ProfileAndExpectation< - ti::ComparableNothrowMoveConstructibleProfile, - ti::ComparableNothrowMoveConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // ComparableCopyConstructible - ProfileAndExpectation< - ti::ComparableCopyConstructibleProfile, - ti::ComparableCopyConstructibleArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::maybe, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, - ti::greater_than_comparable::yes>>, - - // ComparableNothrowMovable - ProfileAndExpectation< - ti::ComparableNothrowMovableProfile, - ti::ComparableNothrowMovableArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::maybe, ti::move_assignable::nothrow, - ti::copy_assignable::maybe, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow>>, - - // ComparableValue - ProfileAndExpectation< - ti::ComparableValueProfile, ti::ComparableValueArchetype, - ti::ConformanceProfile< - ti::default_constructible::maybe, ti::move_constructible::nothrow, - ti::copy_constructible::yes, ti::move_assignable::nothrow, - ti::copy_assignable::yes, ti::destructible::nothrow, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow>>>; - -using TrivialProfilesToTest = ::testing::Types< - ProfileAndExpectation< - ti::TrivialSpecialMemberFunctionsProfile, - ti::TrivialSpecialMemberFunctionsArchetype, - ti::ConformanceProfile< - ti::default_constructible::trivial, ti::move_constructible::trivial, - ti::copy_constructible::trivial, ti::move_assignable::trivial, - ti::copy_assignable::trivial, ti::destructible::trivial, - ti::equality_comparable::maybe, ti::inequality_comparable::maybe, - ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe, - ti::greater_equal_comparable::maybe, - ti::greater_than_comparable::maybe, ti::swappable::nothrow>>, - - ProfileAndExpectation< - ti::TriviallyCompleteProfile, ti::TriviallyCompleteArchetype, - ti::ConformanceProfile< - ti::default_constructible::trivial, ti::move_constructible::trivial, - ti::copy_constructible::trivial, ti::move_assignable::trivial, - ti::copy_assignable::trivial, ti::destructible::trivial, - ti::equality_comparable::yes, ti::inequality_comparable::yes, - ti::less_than_comparable::yes, ti::less_equal_comparable::yes, - ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes, - ti::swappable::nothrow, ti::hashable::yes>>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(Core, ProfileTest, CoreProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(Common, ProfileTest, CommonProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(ComparableHelpers, ProfileTest, - ComparableHelpersProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(CommonComparable, ProfileTest, - CommonComparableProfilesToTest); -INSTANTIATE_TYPED_TEST_SUITE_P(Trivial, ProfileTest, TrivialProfilesToTest); - -TEST(ConformanceTestingTest, Basic) { - using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile, - ti::NothrowComparableProfile>; - - using lim = std::numeric_limits<float>; - - ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(float) - .INITIALIZER(-lim::infinity()) - .INITIALIZER(lim::lowest()) - .INITIALIZER(-1.f) - .INITIALIZER(-lim::min()) - .EQUIVALENCE_CLASS(INITIALIZER(-0.f), INITIALIZER(0.f)) - .INITIALIZER(lim::min()) - .INITIALIZER(1.f) - .INITIALIZER(lim::max()) - .INITIALIZER(lim::infinity()) - .WITH_STRICT_PROFILE(absl::types_internal::RegularityDomain, profile); -} - -struct BadMoveConstruct { - BadMoveConstruct() = default; - BadMoveConstruct(BadMoveConstruct&& other) noexcept - : value(other.value + 1) {} - BadMoveConstruct& operator=(BadMoveConstruct&& other) noexcept = default; - int value = 0; - - friend bool operator==(BadMoveConstruct const& lhs, - BadMoveConstruct const& rhs) { - return lhs.value == rhs.value; - } - friend bool operator!=(BadMoveConstruct const& lhs, - BadMoveConstruct const& rhs) { - return lhs.value != rhs.value; - } -}; - -struct BadMoveAssign { - BadMoveAssign() = default; - BadMoveAssign(BadMoveAssign&& other) noexcept = default; - BadMoveAssign& operator=(BadMoveAssign&& other) noexcept { - int new_value = other.value + 1; - value = new_value; - return *this; - } - int value = 0; - - friend bool operator==(BadMoveAssign const& lhs, BadMoveAssign const& rhs) { - return lhs.value == rhs.value; - } - friend bool operator!=(BadMoveAssign const& lhs, BadMoveAssign const& rhs) { - return lhs.value != rhs.value; - } -}; - -enum class WhichCompIsBad { eq, ne, lt, le, ge, gt }; - -template <WhichCompIsBad Which> -struct BadCompare { - int value; - - friend bool operator==(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::eq ? lhs.value != rhs.value - : lhs.value == rhs.value; - } - - friend bool operator!=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::ne ? lhs.value == rhs.value - : lhs.value != rhs.value; - } - - friend bool operator<(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::lt ? lhs.value >= rhs.value - : lhs.value < rhs.value; - } - - friend bool operator<=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::le ? lhs.value > rhs.value - : lhs.value <= rhs.value; - } - - friend bool operator>=(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::ge ? lhs.value < rhs.value - : lhs.value >= rhs.value; - } - - friend bool operator>(BadCompare const& lhs, BadCompare const& rhs) { - return Which == WhichCompIsBad::gt ? lhs.value <= rhs.value - : lhs.value > rhs.value; - } -}; - -TEST(ConformanceTestingDeathTest, Failures) { - { - using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile, - ti::NothrowComparableProfile>; - - // Note: The initializers are intentionally in the wrong order. - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(float) - .INITIALIZER(1.f) - .INITIALIZER(0.f) - .WITH_LOOSE_PROFILE(profile); - } - - { - using profile = - ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveConstruct) - .DUE_TO("Move construction") - .INITIALIZER(BadMoveConstruct()) - .WITH_LOOSE_PROFILE(profile); - } - - { - using profile = - ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveAssign) - .DUE_TO("Move assignment") - .INITIALIZER(BadMoveAssign()) - .WITH_LOOSE_PROFILE(profile); - } -} - -TEST(ConformanceTestingDeathTest, CompFailures) { - using profile = ti::ComparableProfile; - - { - using BadComp = BadCompare<WhichCompIsBad::eq>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::ne>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::lt>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::le>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::ge>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } - - { - using BadComp = BadCompare<WhichCompIsBad::gt>; - - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp) - .DUE_TO("Comparison") - .INITIALIZER(BadComp{0}) - .INITIALIZER(BadComp{1}) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfMove { - BadSelfMove() = default; - BadSelfMove(BadSelfMove&&) = default; - BadSelfMove& operator=(BadSelfMove&& other) noexcept { - if (this == &other) { - broken_state = true; - } - return *this; - } - - friend bool operator==(const BadSelfMove& lhs, const BadSelfMove& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfMove& lhs, const BadSelfMove& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfMoveFailure) { - using profile = ti::EquatableNothrowMovableProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfMove) - .DUE_TO("Move assignment") - .INITIALIZER(BadSelfMove()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfCopy { - BadSelfCopy() = default; - BadSelfCopy(BadSelfCopy&&) = default; - BadSelfCopy(const BadSelfCopy&) = default; - BadSelfCopy& operator=(BadSelfCopy&&) = default; - BadSelfCopy& operator=(BadSelfCopy const& other) { - if (this == &other) { - broken_state = true; - } - return *this; - } - - friend bool operator==(const BadSelfCopy& lhs, const BadSelfCopy& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfCopy& lhs, const BadSelfCopy& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfCopyFailure) { - using profile = ti::EquatableValueProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfCopy) - .DUE_TO("Copy assignment") - .INITIALIZER(BadSelfCopy()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadSelfSwap { - friend void swap(BadSelfSwap& lhs, BadSelfSwap& rhs) noexcept { - if (&lhs == &rhs) lhs.broken_state = true; - } - - friend bool operator==(const BadSelfSwap& lhs, const BadSelfSwap& rhs) { - return !(lhs.broken_state || rhs.broken_state); - } - - friend bool operator!=(const BadSelfSwap& lhs, const BadSelfSwap& rhs) { - return lhs.broken_state || rhs.broken_state; - } - - bool broken_state = false; -}; - -TEST(ConformanceTestingDeathTest, SelfSwapFailure) { - using profile = ti::EquatableNothrowMovableProfile; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfSwap) - .DUE_TO("Swap") - .INITIALIZER(BadSelfSwap()) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadDefaultInitializedMoveAssign { - BadDefaultInitializedMoveAssign() : default_initialized(true) {} - explicit BadDefaultInitializedMoveAssign(int v) : value(v) {} - BadDefaultInitializedMoveAssign( - BadDefaultInitializedMoveAssign&& other) noexcept - : value(other.value) {} - BadDefaultInitializedMoveAssign& operator=( - BadDefaultInitializedMoveAssign&& other) noexcept { - value = other.value; - if (default_initialized) ++value; // Bad move if lhs is default initialized - return *this; - } - - friend bool operator==(const BadDefaultInitializedMoveAssign& lhs, - const BadDefaultInitializedMoveAssign& rhs) { - return lhs.value == rhs.value; - } - - friend bool operator!=(const BadDefaultInitializedMoveAssign& lhs, - const BadDefaultInitializedMoveAssign& rhs) { - return lhs.value != rhs.value; - } - - bool default_initialized = false; - int value = 0; -}; - -TEST(ConformanceTestingDeathTest, DefaultInitializedMoveAssignFailure) { - using profile = - ti::CombineProfiles<ti::DefaultConstructibleNothrowMovableProfile, - ti::EquatableProfile>; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedMoveAssign) - .DUE_TO("move assignment") - .INITIALIZER(BadDefaultInitializedMoveAssign(0)) - .WITH_LOOSE_PROFILE(profile); - } -} - -struct BadDefaultInitializedCopyAssign { - BadDefaultInitializedCopyAssign() : default_initialized(true) {} - explicit BadDefaultInitializedCopyAssign(int v) : value(v) {} - BadDefaultInitializedCopyAssign( - BadDefaultInitializedCopyAssign&& other) noexcept - : value(other.value) {} - BadDefaultInitializedCopyAssign(const BadDefaultInitializedCopyAssign& other) - : value(other.value) {} - - BadDefaultInitializedCopyAssign& operator=( - BadDefaultInitializedCopyAssign&& other) noexcept { - value = other.value; - return *this; - } - - BadDefaultInitializedCopyAssign& operator=( - const BadDefaultInitializedCopyAssign& other) { - value = other.value; - if (default_initialized) ++value; // Bad move if lhs is default initialized - return *this; - } - - friend bool operator==(const BadDefaultInitializedCopyAssign& lhs, - const BadDefaultInitializedCopyAssign& rhs) { - return lhs.value == rhs.value; - } - - friend bool operator!=(const BadDefaultInitializedCopyAssign& lhs, - const BadDefaultInitializedCopyAssign& rhs) { - return lhs.value != rhs.value; - } - - bool default_initialized = false; - int value = 0; -}; - -TEST(ConformanceTestingDeathTest, DefaultInitializedAssignFailure) { - using profile = ti::CombineProfiles<ti::DefaultConstructibleValueProfile, - ti::EquatableProfile>; - - { - ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedCopyAssign) - .DUE_TO("copy assignment") - .INITIALIZER(BadDefaultInitializedCopyAssign(0)) - .WITH_LOOSE_PROFILE(profile); - } -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/types/internal/optional.h b/third_party/abseil_cpp/absl/types/internal/optional.h deleted file mode 100644 index 92932b6001b3..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/optional.h +++ /dev/null @@ -1,396 +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. -// -#ifndef ABSL_TYPES_INTERNAL_OPTIONAL_H_ -#define ABSL_TYPES_INTERNAL_OPTIONAL_H_ - -#include <functional> -#include <new> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/inline_variable.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/utility/utility.h" - -// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS -// -// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015. -// __cpp_inheriting_constructors is a predefined macro and a recommended way to -// check for this language feature, but GCC doesn't support it until 5.0 and -// Clang doesn't support it until 3.6. -// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template -// constructor. For example, the following code won't work on MSVC 2015 Update3: -// struct Base { -// int t; -// template <typename T> -// constexpr Base(T t_) : t(t_) {} -// }; -// struct Foo : Base { -// using Base::Base; -// } -// constexpr Foo foo(0); // doesn't work on MSVC 2015 -#if defined(__clang__) -#if __has_feature(cxx_inheriting_constructors) -#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 -#endif -#elif (defined(__GNUC__) && \ - (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \ - (__cpp_inheriting_constructors >= 200802) || \ - (defined(_MSC_VER) && _MSC_VER >= 1910) -#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// Forward declaration -template <typename T> -class optional; - -namespace optional_internal { - -// This tag type is used as a constructor parameter type for `nullopt_t`. -struct init_t { - explicit init_t() = default; -}; - -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 unused = std::is_trivially_destructible<T>::value> -class optional_data_dtor_base { - struct dummy_type { - static_assert(sizeof(T) % sizeof(empty_struct) == 0, ""); - // Use an array to avoid GCC 6 placement-new warning. - empty_struct data[sizeof(T) / sizeof(empty_struct)]; - }; - - protected: - // Whether there is data or not. - bool engaged_; - // Data storage - union { - T data_; - dummy_type dummy_; - }; - - void destruct() noexcept { - if (engaged_) { - data_.~T(); - engaged_ = false; - } - } - - // dummy_ must be initialized for constexpr constructor. - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {} - - template <typename... Args> - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(absl::forward<Args>(args)...) {} - - ~optional_data_dtor_base() { destruct(); } -}; - -// Specialization for trivially destructible type. -template <typename T> -class optional_data_dtor_base<T, true> { - struct dummy_type { - static_assert(sizeof(T) % sizeof(empty_struct) == 0, ""); - // Use array to avoid GCC 6 placement-new warning. - empty_struct data[sizeof(T) / sizeof(empty_struct)]; - }; - - protected: - // Whether there is data or not. - bool engaged_; - // Data storage - union { - T data_; - dummy_type dummy_; - }; - void destruct() noexcept { engaged_ = false; } - - // dummy_ must be initialized for constexpr constructor. - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {} - - template <typename... Args> - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(absl::forward<Args>(args)...) {} -}; - -template <typename T> -class optional_data_base : public optional_data_dtor_base<T> { - protected: - using base = optional_data_dtor_base<T>; -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using base::base; -#else - optional_data_base() = default; - - template <typename... Args> - constexpr explicit optional_data_base(in_place_t t, Args&&... args) - : base(t, absl::forward<Args>(args)...) {} -#endif - - template <typename... Args> - void construct(Args&&... args) { - // Use dummy_'s address to work around casting cv-qualified T* to void*. - ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...); - this->engaged_ = true; - } - - template <typename U> - void assign(U&& u) { - if (this->engaged_) { - this->data_ = std::forward<U>(u); - } else { - construct(std::forward<U>(u)); - } - } -}; - -// TODO(absl-team): Add another class using -// std::is_trivially_move_constructible trait when available to match -// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that -// 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 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 -template <typename T> -class optional_data<T, true> : public optional_data_base<T> { - protected: -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using optional_data_base<T>::optional_data_base; -#else - optional_data() = default; - - template <typename... Args> - constexpr explicit optional_data(in_place_t t, Args&&... args) - : optional_data_base<T>(t, absl::forward<Args>(args)...) {} -#endif -}; - -template <typename T> -class optional_data<T, false> : public optional_data_base<T> { - protected: -#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - using optional_data_base<T>::optional_data_base; -#else - template <typename... Args> - constexpr explicit optional_data(in_place_t t, Args&&... args) - : optional_data_base<T>(t, absl::forward<Args>(args)...) {} -#endif - - optional_data() = default; - - optional_data(const optional_data& rhs) : optional_data_base<T>() { - if (rhs.engaged_) { - this->construct(rhs.data_); - } - } - - optional_data(optional_data&& rhs) noexcept( - absl::default_allocator_is_nothrow::value || - std::is_nothrow_move_constructible<T>::value) - : optional_data_base<T>() { - if (rhs.engaged_) { - this->construct(std::move(rhs.data_)); - } - } - - optional_data& operator=(const optional_data& rhs) { - if (rhs.engaged_) { - this->assign(rhs.data_); - } else { - this->destruct(); - } - return *this; - } - - optional_data& operator=(optional_data&& rhs) noexcept( - std::is_nothrow_move_assignable<T>::value&& - std::is_nothrow_move_constructible<T>::value) { - if (rhs.engaged_) { - this->assign(std::move(rhs.data_)); - } else { - this->destruct(); - } - return *this; - } -}; - -// Ordered by level of restriction, from low to high. -// Copyable implies movable. -enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 }; - -// Base class for enabling/disabling copy/move constructor. -template <copy_traits> -class optional_ctor_base; - -template <> -class optional_ctor_base<copy_traits::copyable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = default; - optional_ctor_base(optional_ctor_base&&) = default; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -template <> -class optional_ctor_base<copy_traits::movable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = delete; - optional_ctor_base(optional_ctor_base&&) = default; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -template <> -class optional_ctor_base<copy_traits::non_movable> { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = delete; - optional_ctor_base(optional_ctor_base&&) = delete; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -// Base class for enabling/disabling copy/move assignment. -template <copy_traits> -class optional_assign_base; - -template <> -class optional_assign_base<copy_traits::copyable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = default; - optional_assign_base& operator=(optional_assign_base&&) = default; -}; - -template <> -class optional_assign_base<copy_traits::movable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = delete; - optional_assign_base& operator=(optional_assign_base&&) = default; -}; - -template <> -class optional_assign_base<copy_traits::non_movable> { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = delete; - optional_assign_base& operator=(optional_assign_base&&) = delete; -}; - -template <typename T> -struct ctor_copy_traits { - static constexpr copy_traits traits = - std::is_copy_constructible<T>::value - ? copy_traits::copyable - : std::is_move_constructible<T>::value ? copy_traits::movable - : copy_traits::non_movable; -}; - -template <typename T> -struct assign_copy_traits { - static constexpr copy_traits traits = - absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value - ? copy_traits::copyable - : absl::is_move_assignable<T>::value && - std::is_move_constructible<T>::value - ? copy_traits::movable - : copy_traits::non_movable; -}; - -// Whether T is constructible or convertible from optional<U>. -template <typename T, typename U> -struct is_constructible_convertible_from_optional - : std::integral_constant< - bool, std::is_constructible<T, optional<U>&>::value || - std::is_constructible<T, optional<U>&&>::value || - std::is_constructible<T, const optional<U>&>::value || - std::is_constructible<T, const optional<U>&&>::value || - std::is_convertible<optional<U>&, T>::value || - std::is_convertible<optional<U>&&, T>::value || - std::is_convertible<const optional<U>&, T>::value || - std::is_convertible<const optional<U>&&, T>::value> {}; - -// Whether T is constructible or convertible or assignable from optional<U>. -template <typename T, typename U> -struct is_constructible_convertible_assignable_from_optional - : std::integral_constant< - bool, is_constructible_convertible_from_optional<T, U>::value || - std::is_assignable<T&, optional<U>&>::value || - std::is_assignable<T&, optional<U>&&>::value || - std::is_assignable<T&, const optional<U>&>::value || - std::is_assignable<T&, const optional<U>&&>::value> {}; - -// Helper function used by [optional.relops], [optional.comp_with_t], -// for checking whether an expression is convertible to bool. -bool convertible_to_bool(bool); - -// Base class for std::hash<absl::optional<T>>: -// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to -// compute the hash; Otherwise, it is disabled. -// Reference N4659 23.14.15 [unord.hash]. -template <typename T, typename = size_t> -struct optional_hash_base { - optional_hash_base() = delete; - optional_hash_base(const optional_hash_base&) = delete; - optional_hash_base(optional_hash_base&&) = delete; - optional_hash_base& operator=(const optional_hash_base&) = delete; - optional_hash_base& operator=(optional_hash_base&&) = delete; -}; - -template <typename T> -struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()( - std::declval<absl::remove_const_t<T> >()))> { - using argument_type = absl::optional<T>; - using result_type = size_t; - size_t operator()(const absl::optional<T>& opt) const { - absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>(); - if (opt) { - return std::hash<absl::remove_const_t<T> >()(*opt); - } else { - return static_cast<size_t>(0x297814aaad196e6dULL); - } - } -}; - -} // namespace optional_internal -ABSL_NAMESPACE_END -} // namespace absl - -#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS - -#endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/parentheses.h b/third_party/abseil_cpp/absl/types/internal/parentheses.h deleted file mode 100644 index 5aebee8fdeb9..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/parentheses.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// parentheses.h -// ----------------------------------------------------------------------------- -// -// This file contains macros that expand to a left parenthesis and a right -// parenthesis. These are in their own file and are generated from macros -// because otherwise clang-format gets confused and clang-format off directives -// do not help. -// -// The parentheses macros are used when wanting to require a rescan before -// expansion of parenthesized text appearing after a function-style macro name. - -#ifndef ABSL_TYPES_INTERNAL_PARENTHESES_H_ -#define ABSL_TYPES_INTERNAL_PARENTHESES_H_ - -#define ABSL_INTERNAL_LPAREN ( - -#define ABSL_INTERNAL_RPAREN ) - -#endif // ABSL_TYPES_INTERNAL_PARENTHESES_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/span.h b/third_party/abseil_cpp/absl/types/internal/span.h deleted file mode 100644 index 112612f4bdae..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/span.h +++ /dev/null @@ -1,128 +0,0 @@ -// -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef ABSL_TYPES_INTERNAL_SPAN_H_ -#define ABSL_TYPES_INTERNAL_SPAN_H_ - -#include <algorithm> -#include <cstddef> -#include <string> -#include <type_traits> - -#include "absl/algorithm/algorithm.h" -#include "absl/base/internal/throw_delegate.h" -#include "absl/meta/type_traits.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace span_internal { -// A constexpr min function -constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; } - -// Wrappers for access to container data pointers. -template <typename C> -constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references) - -> decltype(c.data()) { - return c.data(); -} - -// Before C++17, std::string::data returns a const char* in all cases. -inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references) - int) noexcept { - return &s[0]; -} - -template <typename C> -constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references) - -> decltype(GetDataImpl(c, 0)) { - return GetDataImpl(c, 0); -} - -// Detection idioms for size() and data(). -template <typename C> -using HasSize = - std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>; - -// We want to enable conversion from vector<T*> to Span<const T* const> but -// disable conversion from vector<Derived> to Span<Base>. Here we use -// the fact that U** is convertible to Q* const* if and only if Q is the same -// type or a more cv-qualified version of U. We also decay the result type of -// data() to avoid problems with classes which have a member function data() -// which returns a reference. -template <typename T, typename C> -using HasData = - std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*, - T* const*>; - -// Extracts value type from a Container -template <typename C> -struct ElementType { - using type = typename absl::remove_reference_t<C>::value_type; -}; - -template <typename T, size_t N> -struct ElementType<T (&)[N]> { - using type = T; -}; - -template <typename C> -using ElementT = typename ElementType<C>::type; - -template <typename T> -using EnableIfMutable = - typename std::enable_if<!std::is_const<T>::value, int>::type; - -template <template <typename> class SpanT, typename T> -bool EqualImpl(SpanT<T> a, SpanT<T> b) { - static_assert(std::is_const<T>::value, ""); - return absl::equal(a.begin(), a.end(), b.begin(), b.end()); -} - -template <template <typename> class SpanT, typename T> -bool LessThanImpl(SpanT<T> a, SpanT<T> b) { - // We can't use value_type since that is remove_cv_t<T>, so we go the long way - // around. - static_assert(std::is_const<T>::value, ""); - return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); -} - -// The `IsConvertible` classes here are needed because of the -// `std::is_convertible` bug in libcxx when compiled with GCC. This build -// configuration is used by Android NDK toolchain. Reference link: -// https://bugs.llvm.org/show_bug.cgi?id=27538. -template <typename From, typename To> -struct IsConvertibleHelper { - private: - static std::true_type testval(To); - static std::false_type testval(...); - - public: - using type = decltype(testval(std::declval<From>())); -}; - -template <typename From, typename To> -struct IsConvertible : IsConvertibleHelper<From, To>::type {}; - -// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the -// older version of libcxx is not supported. -template <typename From, typename To> -using EnableIfConvertibleTo = - typename std::enable_if<IsConvertible<From, To>::value>::type; -} // namespace span_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_INTERNAL_SPAN_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/transform_args.h b/third_party/abseil_cpp/absl/types/internal/transform_args.h deleted file mode 100644 index 4a0ab42ac49f..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/transform_args.h +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// transform_args.h -// ----------------------------------------------------------------------------- -// -// This file contains a higher-order macro that "transforms" each element of a -// a variadic argument by a provided secondary macro. - -#ifndef ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_ -#define ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_ - -// -// ABSL_INTERNAL_CAT(a, b) -// -// This macro takes two arguments and concatenates them together via ## after -// expansion. -// -// Example: -// -// ABSL_INTERNAL_CAT(foo_, bar) -// -// Results in: -// -// foo_bar -#define ABSL_INTERNAL_CAT(a, b) ABSL_INTERNAL_CAT_IMPL(a, b) -#define ABSL_INTERNAL_CAT_IMPL(a, b) a##b - -// -// ABSL_INTERNAL_TRANSFORM_ARGS(m, ...) -// -// This macro takes another macro as an argument followed by a trailing series -// of additional parameters (up to 32 additional arguments). It invokes the -// passed-in macro once for each of the additional arguments, with the -// expansions separated by commas. -// -// Example: -// -// ABSL_INTERNAL_TRANSFORM_ARGS(MY_MACRO, a, b, c) -// -// Results in: -// -// MY_MACRO(a), MY_MACRO(b), MY_MACRO(c) -// -// TODO(calabrese) Handle no arguments as a special case. -#define ABSL_INTERNAL_TRANSFORM_ARGS(m, ...) \ - ABSL_INTERNAL_CAT(ABSL_INTERNAL_TRANSFORM_ARGS, \ - ABSL_INTERNAL_NUM_ARGS(__VA_ARGS__)) \ - (m, __VA_ARGS__) - -#define ABSL_INTERNAL_TRANSFORM_ARGS1(m, a0) m(a0) - -#define ABSL_INTERNAL_TRANSFORM_ARGS2(m, a0, a1) m(a0), m(a1) - -#define ABSL_INTERNAL_TRANSFORM_ARGS3(m, a0, a1, a2) m(a0), m(a1), m(a2) - -#define ABSL_INTERNAL_TRANSFORM_ARGS4(m, a0, a1, a2, a3) \ - m(a0), m(a1), m(a2), m(a3) - -#define ABSL_INTERNAL_TRANSFORM_ARGS5(m, a0, a1, a2, a3, a4) \ - m(a0), m(a1), m(a2), m(a3), m(a4) - -#define ABSL_INTERNAL_TRANSFORM_ARGS6(m, a0, a1, a2, a3, a4, a5) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5) - -#define ABSL_INTERNAL_TRANSFORM_ARGS7(m, a0, a1, a2, a3, a4, a5, a6) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6) - -#define ABSL_INTERNAL_TRANSFORM_ARGS8(m, a0, a1, a2, a3, a4, a5, a6, a7) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7) - -#define ABSL_INTERNAL_TRANSFORM_ARGS9(m, a0, a1, a2, a3, a4, a5, a6, a7, a8) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8) - -#define ABSL_INTERNAL_TRANSFORM_ARGS10(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9) - -#define ABSL_INTERNAL_TRANSFORM_ARGS11(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), m(a10) - -#define ABSL_INTERNAL_TRANSFORM_ARGS12(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11) - -#define ABSL_INTERNAL_TRANSFORM_ARGS13(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12) - -#define ABSL_INTERNAL_TRANSFORM_ARGS14(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13) - -#define ABSL_INTERNAL_TRANSFORM_ARGS15(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14) - -#define ABSL_INTERNAL_TRANSFORM_ARGS16(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15) - -#define ABSL_INTERNAL_TRANSFORM_ARGS17(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16) - -#define ABSL_INTERNAL_TRANSFORM_ARGS18(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17) - -#define ABSL_INTERNAL_TRANSFORM_ARGS19(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18) - -#define ABSL_INTERNAL_TRANSFORM_ARGS20(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19) - -#define ABSL_INTERNAL_TRANSFORM_ARGS21(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20) - -#define ABSL_INTERNAL_TRANSFORM_ARGS22(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21) - -#define ABSL_INTERNAL_TRANSFORM_ARGS23(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21, a22) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22) - -#define ABSL_INTERNAL_TRANSFORM_ARGS24(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21, a22, a23) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23) - -#define ABSL_INTERNAL_TRANSFORM_ARGS25(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21, a22, a23, a24) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24) - -#define ABSL_INTERNAL_TRANSFORM_ARGS26( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25) - -#define ABSL_INTERNAL_TRANSFORM_ARGS27( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26) - -#define ABSL_INTERNAL_TRANSFORM_ARGS28( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27) - -#define ABSL_INTERNAL_TRANSFORM_ARGS29( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \ - m(a28) - -#define ABSL_INTERNAL_TRANSFORM_ARGS30( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \ - m(a28), m(a29) - -#define ABSL_INTERNAL_TRANSFORM_ARGS31( \ - m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \ - a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \ - m(a28), m(a29), m(a30) - -#define ABSL_INTERNAL_TRANSFORM_ARGS32(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14, a15, a16, \ - a17, a18, a19, a20, a21, a22, a23, a24, \ - a25, a26, a27, a28, a29, a30, a31) \ - m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \ - m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \ - m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \ - m(a28), m(a29), m(a30), m(a31) - -#define ABSL_INTERNAL_NUM_ARGS_IMPL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ - a10, a11, a12, a13, a14, a15, a16, a17, \ - a18, a19, a20, a21, a22, a23, a24, a25, \ - a26, a27, a28, a29, a30, a31, result, ...) \ - result - -#define ABSL_INTERNAL_FORCE_EXPANSION(...) __VA_ARGS__ - -#define ABSL_INTERNAL_NUM_ARGS(...) \ - ABSL_INTERNAL_FORCE_EXPANSION(ABSL_INTERNAL_NUM_ARGS_IMPL( \ - __VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, \ - 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, )) - -#endif // ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_ diff --git a/third_party/abseil_cpp/absl/types/internal/variant.h b/third_party/abseil_cpp/absl/types/internal/variant.h deleted file mode 100644 index 772008c74e6d..000000000000 --- a/third_party/abseil_cpp/absl/types/internal/variant.h +++ /dev/null @@ -1,1646 +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. -// -// 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_ - -#include <cassert> -#include <cstddef> -#include <cstdlib> -#include <memory> -#include <stdexcept> -#include <tuple> -#include <type_traits> - -#include "absl/base/config.h" -#include "absl/base/internal/identity.h" -#include "absl/base/internal/inline_variable.h" -#include "absl/base/internal/invoke.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/meta/type_traits.h" -#include "absl/types/bad_variant_access.h" -#include "absl/utility/utility.h" - -#if !defined(ABSL_USES_STD_VARIANT) - -namespace absl { -ABSL_NAMESPACE_BEGIN - -template <class... Types> -class variant; - -ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1)); - -template <class T> -struct variant_size; - -template <std::size_t I, class T> -struct variant_alternative; - -namespace variant_internal { - -// NOTE: See specializations below for details. -template <std::size_t I, class T> -struct VariantAlternativeSfinae {}; - -// Requires: I < variant_size_v<T>. -// -// Value: The Ith type of Types... -template <std::size_t I, class T0, class... Tn> -struct VariantAlternativeSfinae<I, variant<T0, Tn...>> - : VariantAlternativeSfinae<I - 1, variant<Tn...>> {}; - -// Value: T0 -template <class T0, class... Ts> -struct VariantAlternativeSfinae<0, variant<T0, Ts...>> { - using type = T0; -}; - -template <std::size_t I, class T> -using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type; - -// NOTE: Requires T to be a reference type. -template <class T, class U> -struct GiveQualsTo; - -template <class T, class U> -struct GiveQualsTo<T&, U> { - using type = U&; -}; - -template <class T, class U> -struct GiveQualsTo<T&&, U> { - using type = U&&; -}; - -template <class T, class U> -struct GiveQualsTo<const T&, U> { - using type = const U&; -}; - -template <class T, class U> -struct GiveQualsTo<const T&&, U> { - using type = const U&&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile T&, U> { - using type = volatile U&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile T&&, U> { - using type = volatile U&&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile const T&, U> { - using type = volatile const U&; -}; - -template <class T, class U> -struct GiveQualsTo<volatile const T&&, U> { - using type = volatile const U&&; -}; - -template <class T, class U> -using GiveQualsToT = typename GiveQualsTo<T, U>::type; - -// Convenience alias, since size_t integral_constant is used a lot in this file. -template <std::size_t I> -using SizeT = std::integral_constant<std::size_t, I>; - -using NPos = SizeT<variant_npos>; - -template <class Variant, class T, class = void> -struct IndexOfConstructedType {}; - -template <std::size_t I, class Variant> -struct VariantAccessResultImpl; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, Variantemplate<T...>&> { - using type = typename absl::variant_alternative<I, variant<T...>>::type&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, const Variantemplate<T...>&> { - using type = - const typename absl::variant_alternative<I, variant<T...>>::type&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, Variantemplate<T...>&&> { - using type = typename absl::variant_alternative<I, variant<T...>>::type&&; -}; - -template <std::size_t I, template <class...> class Variantemplate, class... T> -struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> { - using type = - const typename absl::variant_alternative<I, variant<T...>>::type&&; -}; - -template <std::size_t I, class Variant> -using VariantAccessResult = - typename VariantAccessResultImpl<I, Variant&&>::type; - -// NOTE: This is used instead of std::array to reduce instantiation overhead. -template <class T, std::size_t Size> -struct SimpleArray { - static_assert(Size != 0, ""); - T value[Size]; -}; - -template <class T> -struct AccessedType { - using type = T; -}; - -template <class T> -using AccessedTypeT = typename AccessedType<T>::type; - -template <class T, std::size_t Size> -struct AccessedType<SimpleArray<T, Size>> { - using type = AccessedTypeT<T>; -}; - -template <class T> -constexpr T AccessSimpleArray(const T& value) { - return value; -} - -template <class T, std::size_t Size, class... SizeT> -constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table, - std::size_t head_index, - SizeT... tail_indices) { - return AccessSimpleArray(table.value[head_index], tail_indices...); -} - -// Note: Intentionally is an alias. -template <class T> -using AlwaysZero = SizeT<0>; - -template <class Op, class... Vs> -struct VisitIndicesResultImpl { - using type = absl::result_of_t<Op(AlwaysZero<Vs>...)>; -}; - -template <class Op, class... Vs> -using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type; - -template <class ReturnType, class FunctionObject, class EndIndices, - class BoundIndices> -struct MakeVisitationMatrix; - -template <class ReturnType, class FunctionObject, std::size_t... Indices> -constexpr ReturnType call_with_indices(FunctionObject&& function) { - static_assert( - std::is_same<ReturnType, decltype(std::declval<FunctionObject>()( - SizeT<Indices>()...))>::value, - "Not all visitation overloads have the same return type."); - return absl::forward<FunctionObject>(function)(SizeT<Indices>()...); -} - -template <class ReturnType, class FunctionObject, std::size_t... BoundIndices> -struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>, - index_sequence<BoundIndices...>> { - using ResultType = ReturnType (*)(FunctionObject&&); - static constexpr ResultType Run() { - return &call_with_indices<ReturnType, FunctionObject, - (BoundIndices - 1)...>; - } -}; - -template <typename Is, std::size_t J> -struct AppendToIndexSequence; - -template <typename Is, std::size_t J> -using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type; - -template <std::size_t... Is, std::size_t J> -struct AppendToIndexSequence<index_sequence<Is...>, J> { - using type = index_sequence<Is..., J>; -}; - -template <class ReturnType, class FunctionObject, class EndIndices, - class CurrIndices, class BoundIndices> -struct MakeVisitationMatrixImpl; - -template <class ReturnType, class FunctionObject, class EndIndices, - std::size_t... CurrIndices, class BoundIndices> -struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices, - index_sequence<CurrIndices...>, BoundIndices> { - using ResultType = SimpleArray< - typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices, - index_sequence<>>::ResultType, - sizeof...(CurrIndices)>; - - static constexpr ResultType Run() { - return {{MakeVisitationMatrix< - ReturnType, FunctionObject, EndIndices, - AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}}; - } -}; - -template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex, - std::size_t... TailEndIndices, std::size_t... BoundIndices> -struct MakeVisitationMatrix<ReturnType, FunctionObject, - index_sequence<HeadEndIndex, TailEndIndices...>, - index_sequence<BoundIndices...>> - : MakeVisitationMatrixImpl<ReturnType, FunctionObject, - index_sequence<TailEndIndices...>, - absl::make_index_sequence<HeadEndIndex>, - index_sequence<BoundIndices...>> {}; - -struct UnreachableSwitchCase { - template <class Op> - [[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run( - Op&& /*ignored*/) { -#if ABSL_HAVE_BUILTIN(__builtin_unreachable) || \ - (defined(__GNUC__) && !defined(__clang__)) - __builtin_unreachable(); -#elif defined(_MSC_VER) - __assume(false); -#else - // Try to use assert of false being identified as an unreachable intrinsic. - // NOTE: We use assert directly to increase chances of exploiting an assume - // intrinsic. - assert(false); // NOLINT - - // Hack to silence potential no return warning -- cause an infinite loop. - return Run(absl::forward<Op>(op)); -#endif // Checks for __builtin_unreachable - } -}; - -template <class Op, std::size_t I> -struct ReachableSwitchCase { - static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) { - return absl::base_internal::invoke(absl::forward<Op>(op), SizeT<I>()); - } -}; - -// The number 33 is just a guess at a reasonable maximum to our switch. It is -// not based on any analysis. The reason it is a power of 2 plus 1 instead of a -// power of 2 is because the number was picked to correspond to a power of 2 -// amount of "normal" alternatives, plus one for the possibility of the user -// providing "monostate" in addition to the more natural alternatives. -ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33); - -// Note: The default-definition is for unreachable cases. -template <bool IsReachable> -struct PickCaseImpl { - template <class Op, std::size_t I> - using Apply = UnreachableSwitchCase; -}; - -template <> -struct PickCaseImpl</*IsReachable =*/true> { - template <class Op, std::size_t I> - using Apply = ReachableSwitchCase<Op, I>; -}; - -// Note: This form of dance with template aliases is to make sure that we -// instantiate a number of templates proportional to the number of variant -// alternatives rather than a number of templates proportional to our -// maximum unrolled amount of visitation cases (aliases are effectively -// "free" whereas other template instantiations are costly). -template <class Op, std::size_t I, std::size_t EndIndex> -using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>; - -template <class ReturnType> -[[noreturn]] ReturnType TypedThrowBadVariantAccess() { - absl::variant_internal::ThrowBadVariantAccess(); -} - -// Given N variant sizes, determine the number of cases there would need to be -// in a single switch-statement that would cover every possibility in the -// corresponding N-ary visit operation. -template <std::size_t... NumAlternatives> -struct NumCasesOfSwitch; - -template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives> -struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> { - static constexpr std::size_t value = - (HeadNumAlternatives + 1) * - NumCasesOfSwitch<TailNumAlternatives...>::value; -}; - -template <> -struct NumCasesOfSwitch<> { - static constexpr std::size_t value = 1; -}; - -// A switch statement optimizes better than the table of function pointers. -template <std::size_t EndIndex> -struct VisitIndicesSwitch { - static_assert(EndIndex <= MaxUnrolledVisitCases, - "Maximum unrolled switch size exceeded."); - - template <class Op> - static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) { - switch (i) { - case 0: - return PickCase<Op, 0, EndIndex>::Run(absl::forward<Op>(op)); - case 1: - return PickCase<Op, 1, EndIndex>::Run(absl::forward<Op>(op)); - case 2: - return PickCase<Op, 2, EndIndex>::Run(absl::forward<Op>(op)); - case 3: - return PickCase<Op, 3, EndIndex>::Run(absl::forward<Op>(op)); - case 4: - return PickCase<Op, 4, EndIndex>::Run(absl::forward<Op>(op)); - case 5: - return PickCase<Op, 5, EndIndex>::Run(absl::forward<Op>(op)); - case 6: - return PickCase<Op, 6, EndIndex>::Run(absl::forward<Op>(op)); - case 7: - return PickCase<Op, 7, EndIndex>::Run(absl::forward<Op>(op)); - case 8: - return PickCase<Op, 8, EndIndex>::Run(absl::forward<Op>(op)); - case 9: - return PickCase<Op, 9, EndIndex>::Run(absl::forward<Op>(op)); - case 10: - return PickCase<Op, 10, EndIndex>::Run(absl::forward<Op>(op)); - case 11: - return PickCase<Op, 11, EndIndex>::Run(absl::forward<Op>(op)); - case 12: - return PickCase<Op, 12, EndIndex>::Run(absl::forward<Op>(op)); - case 13: - return PickCase<Op, 13, EndIndex>::Run(absl::forward<Op>(op)); - case 14: - return PickCase<Op, 14, EndIndex>::Run(absl::forward<Op>(op)); - case 15: - return PickCase<Op, 15, EndIndex>::Run(absl::forward<Op>(op)); - case 16: - return PickCase<Op, 16, EndIndex>::Run(absl::forward<Op>(op)); - case 17: - return PickCase<Op, 17, EndIndex>::Run(absl::forward<Op>(op)); - case 18: - return PickCase<Op, 18, EndIndex>::Run(absl::forward<Op>(op)); - case 19: - return PickCase<Op, 19, EndIndex>::Run(absl::forward<Op>(op)); - case 20: - return PickCase<Op, 20, EndIndex>::Run(absl::forward<Op>(op)); - case 21: - return PickCase<Op, 21, EndIndex>::Run(absl::forward<Op>(op)); - case 22: - return PickCase<Op, 22, EndIndex>::Run(absl::forward<Op>(op)); - case 23: - return PickCase<Op, 23, EndIndex>::Run(absl::forward<Op>(op)); - case 24: - return PickCase<Op, 24, EndIndex>::Run(absl::forward<Op>(op)); - case 25: - return PickCase<Op, 25, EndIndex>::Run(absl::forward<Op>(op)); - case 26: - return PickCase<Op, 26, EndIndex>::Run(absl::forward<Op>(op)); - case 27: - return PickCase<Op, 27, EndIndex>::Run(absl::forward<Op>(op)); - case 28: - return PickCase<Op, 28, EndIndex>::Run(absl::forward<Op>(op)); - case 29: - return PickCase<Op, 29, EndIndex>::Run(absl::forward<Op>(op)); - case 30: - return PickCase<Op, 30, EndIndex>::Run(absl::forward<Op>(op)); - case 31: - return PickCase<Op, 31, EndIndex>::Run(absl::forward<Op>(op)); - case 32: - return PickCase<Op, 32, EndIndex>::Run(absl::forward<Op>(op)); - default: - ABSL_ASSERT(i == variant_npos); - return absl::base_internal::invoke(absl::forward<Op>(op), NPos()); - } - } -}; - -template <std::size_t... EndIndices> -struct VisitIndicesFallback { - template <class Op, class... SizeT> - static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) { - return AccessSimpleArray( - MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op, - index_sequence<(EndIndices + 1)...>, - index_sequence<>>::Run(), - (indices + 1)...)(absl::forward<Op>(op)); - } -}; - -// Take an N-dimensional series of indices and convert them into a single index -// without loss of information. The purpose of this is to be able to convert an -// N-ary visit operation into a single switch statement. -template <std::size_t...> -struct FlattenIndices; - -template <std::size_t HeadSize, std::size_t... TailSize> -struct FlattenIndices<HeadSize, TailSize...> { - template<class... SizeType> - static constexpr std::size_t Run(std::size_t head, SizeType... tail) { - return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...); - } -}; - -template <> -struct FlattenIndices<> { - static constexpr std::size_t Run() { return 0; } -}; - -// Take a single "flattened" index (flattened by FlattenIndices) and determine -// the value of the index of one of the logically represented dimensions. -template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize, - std::size_t... TailSize> -struct UnflattenIndex { - static constexpr std::size_t value = - UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value; -}; - -template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize> -struct UnflattenIndex<I, 0, HeadSize, TailSize...> { - static constexpr std::size_t value = (I % HeadSize); -}; - -// The backend for converting an N-ary visit operation into a unary visit. -template <class IndexSequence, std::size_t... EndIndices> -struct VisitIndicesVariadicImpl; - -template <std::size_t... N, std::size_t... EndIndices> -struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> { - // A type that can take an N-ary function object and converts it to a unary - // function object that takes a single, flattened index, and "unflattens" it - // into its individual dimensions when forwarding to the wrapped object. - template <class Op> - struct FlattenedOp { - template <std::size_t I> - VisitIndicesResultT<Op, decltype(EndIndices)...> operator()( - SizeT<I> /*index*/) && { - return base_internal::invoke( - absl::forward<Op>(op), - SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value - - std::size_t{1}>()...); - } - - Op&& op; - }; - - template <class Op, class... SizeType> - static VisitIndicesResultT<Op, decltype(EndIndices)...> Run( - Op&& op, SizeType... i) { - return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run( - FlattenedOp<Op>{absl::forward<Op>(op)}, - FlattenIndices<(EndIndices + std::size_t{1})...>::Run( - (i + std::size_t{1})...)); - } -}; - -template <std::size_t... EndIndices> -struct VisitIndicesVariadic - : VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>, - EndIndices...> {}; - -// This implementation will flatten N-ary visit operations into a single switch -// statement when the number of cases would be less than our maximum specified -// switch-statement size. -// TODO(calabrese) -// Based on benchmarks, determine whether the function table approach actually -// does optimize better than a chain of switch statements and possibly update -// the implementation accordingly. Also consider increasing the maximum switch -// size. -template <std::size_t... EndIndices> -struct VisitIndices - : absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <= - MaxUnrolledVisitCases), - VisitIndicesVariadic<EndIndices...>, - VisitIndicesFallback<EndIndices...>> {}; - -template <std::size_t EndIndex> -struct VisitIndices<EndIndex> - : absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases), - VisitIndicesSwitch<EndIndex>, - VisitIndicesFallback<EndIndex>> {}; - -// Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast` -// below is returning the address of a temporary or local object. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4172) -#endif // _MSC_VER - -// TODO(calabrese) std::launder -// TODO(calabrese) constexpr -// NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a -// MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details. -template <class Self, std::size_t I> -inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) { - return reinterpret_cast<VariantAccessResult<I, Self>>(self); -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -template <class T> -void DeducedDestroy(T& self) { // NOLINT - self.~T(); -} - -// NOTE: This type exists as a single entity for variant and its bases to -// befriend. It contains helper functionality that manipulates the state of the -// variant, such as the implementation of things like assignment and emplace -// operations. -struct VariantCoreAccess { - template <class VariantType> - static typename VariantType::Variant& Derived(VariantType& self) { // NOLINT - return static_cast<typename VariantType::Variant&>(self); - } - - template <class VariantType> - static const typename VariantType::Variant& Derived( - const VariantType& self) { // NOLINT - return static_cast<const typename VariantType::Variant&>(self); - } - - template <class VariantType> - static void Destroy(VariantType& self) { // NOLINT - Derived(self).destroy(); - self.index_ = absl::variant_npos; - } - - template <class Variant> - static void SetIndex(Variant& self, std::size_t i) { // NOLINT - self.index_ = i; - } - - template <class Variant> - static void InitFrom(Variant& self, Variant&& other) { // NOLINT - VisitIndices<absl::variant_size<Variant>::value>::Run( - InitFromVisitor<Variant, Variant&&>{&self, - std::forward<Variant>(other)}, - other.index()); - 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) { - // 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. - // TODO(calabrese) Reduce test case and find a simpler workaround. - return static_cast<VariantAccessResult<I, Variant>>( - 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 { - using DerivedType = typename VType::Variant; - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - if (left->index_ == NewIndex) { - Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right)); - } else { - Derived(*left).template emplace<NewIndex>( - std::move(Access<NewIndex>(*right))); - } - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - Destroy(*left); - } - - VType* left; - VType* right; - }; - - template <class VType> - static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left, - VType* other) { - return {left, other}; - } - - // The implementation of the assignment operation for a variant. - template <class VType> - struct CopyAssignVisitor { - using DerivedType = typename VType::Variant; - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - using New = - typename absl::variant_alternative<NewIndex, DerivedType>::type; - - if (left->index_ == NewIndex) { - Access<NewIndex>(*left) = Access<NewIndex>(*right); - } else if (std::is_nothrow_copy_constructible<New>::value || - !std::is_nothrow_move_constructible<New>::value) { - Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right)); - } else { - Derived(*left) = DerivedType(Derived(*right)); - } - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - Destroy(*left); - } - - VType* left; - const VType* right; - }; - - template <class VType> - static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left, - const VType& other) { - return {left, &other}; - } - - // The implementation of conversion-assignment operations for variant. - template <class Left, class QualifiedNew> - struct ConversionAssignVisitor { - using NewIndex = - variant_internal::IndexOfConstructedType<Left, QualifiedNew>; - - void operator()(SizeT<NewIndex::value> /*old_i*/ - ) const { - Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other); - } - - template <std::size_t OldIndex> - void operator()(SizeT<OldIndex> /*old_i*/ - ) const { - using New = - typename absl::variant_alternative<NewIndex::value, Left>::type; - if (std::is_nothrow_constructible<New, QualifiedNew>::value || - !std::is_nothrow_move_constructible<New>::value) { - left->template emplace<NewIndex::value>( - absl::forward<QualifiedNew>(other)); - } else { - // the standard says "equivalent to - // operator=(variant(std::forward<T>(t)))", but we use `emplace` here - // because the variant's move assignment operator could be deleted. - left->template emplace<NewIndex::value>( - New(absl::forward<QualifiedNew>(other))); - } - } - - Left* left; - QualifiedNew&& other; - }; - - template <class Left, class QualifiedNew> - static ConversionAssignVisitor<Left, QualifiedNew> - MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) { - return {left, absl::forward<QualifiedNew>(qual)}; - } - - // Backend for operations for `emplace()` which destructs `*self` then - // construct a new alternative with `Args...`. - template <std::size_t NewIndex, class Self, class... Args> - static typename absl::variant_alternative<NewIndex, Self>::type& Replace( - Self* self, Args&&... args) { - Destroy(*self); - using New = typename absl::variant_alternative<NewIndex, Self>::type; - New* const result = ::new (static_cast<void*>(&self->state_)) - New(absl::forward<Args>(args)...); - self->index_ = NewIndex; - return *result; - } - - template <class LeftVariant, class QualifiedRightVariant> - struct InitFromVisitor { - template <std::size_t NewIndex> - void operator()(SizeT<NewIndex> /*new_i*/) const { - using Alternative = - typename variant_alternative<NewIndex, LeftVariant>::type; - ::new (static_cast<void*>(&left->state_)) Alternative( - Access<NewIndex>(std::forward<QualifiedRightVariant>(right))); - } - - void operator()(SizeT<absl::variant_npos> /*new_i*/) const { - // This space intentionally left blank. - } - LeftVariant* left; - QualifiedRightVariant&& right; - }; -}; - -template <class Expected, class... T> -struct IndexOfImpl; - -template <class Expected> -struct IndexOfImpl<Expected> { - using IndexFromEnd = SizeT<0>; - using MatchedIndexFromEnd = IndexFromEnd; - using MultipleMatches = std::false_type; -}; - -template <class Expected, class Head, class... Tail> -struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> { - using IndexFromEnd = - SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>; -}; - -template <class Expected, class... Tail> -struct IndexOfImpl<Expected, Expected, Tail...> - : IndexOfImpl<Expected, Tail...> { - using IndexFromEnd = - SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>; - using MatchedIndexFromEnd = IndexFromEnd; - using MultipleMatches = std::integral_constant< - bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>; -}; - -template <class Expected, class... Types> -struct IndexOfMeta { - using Results = IndexOfImpl<Expected, Types...>; - static_assert(!Results::MultipleMatches::value, - "Attempted to access a variant by specifying a type that " - "matches more than one alternative."); - static_assert(Results::MatchedIndexFromEnd::value != 0, - "Attempted to access a variant by specifying a type that does " - "not match any alternative."); - using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>; -}; - -template <class Expected, class... Types> -using IndexOf = typename IndexOfMeta<Expected, Types...>::type; - -template <class Variant, class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl; - -// Terminating case encountered once we've checked all of the alternatives -template <class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {}; - -// Case where T is not Head -template <class Head, class... Tail, class T, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex> - : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {}; - -// Case where T is Head -template <class Head, class... Tail, std::size_t CurrIndex> -struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex> - : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value == - sizeof...(Tail) - ? CurrIndex - : CurrIndex + sizeof...(Tail) + 1> {}; - -template <class Variant, class T> -struct UnambiguousIndexOf; - -struct NoMatch { - struct type {}; -}; - -template <class... Alts, class T> -struct UnambiguousIndexOf<variant<Alts...>, T> - : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value != - sizeof...(Alts), - UnambiguousIndexOfImpl<variant<Alts...>, T, 0>, - NoMatch>::type::type {}; - -template <class T, std::size_t /*Dummy*/> -using UnambiguousTypeOfImpl = T; - -template <class Variant, class T> -using UnambiguousTypeOfT = - UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>; - -template <class H, class... T> -class VariantStateBase; - -// This is an implementation of the "imaginary function" that is described in -// [variant.ctor] -// It is used in order to determine which alternative to construct during -// initialization from some type T. -template <class Variant, std::size_t I = 0> -struct ImaginaryFun; - -template <std::size_t I> -struct ImaginaryFun<variant<>, I> { - static void Run() = delete; -}; - -template <class H, class... T, std::size_t I> -struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> { - using ImaginaryFun<variant<T...>, I + 1>::Run; - - // NOTE: const& and && are used instead of by-value due to lack of guaranteed - // move elision of C++17. This may have other minor differences, but tests - // pass. - static SizeT<I> Run(const H&, SizeT<I>); - static SizeT<I> Run(H&&, SizeT<I>); -}; - -// The following metafunctions are used in constructor and assignment -// constraints. -template <class Self, class T> -struct IsNeitherSelfNorInPlace : std::true_type {}; - -template <class Self> -struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {}; - -template <class Self, class T> -struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {}; - -template <class Self, std::size_t I> -struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {}; - -template <class Variant, class T, class = void> -struct ConversionIsPossibleImpl : std::false_type {}; - -template <class Variant, class T> -struct ConversionIsPossibleImpl< - Variant, T, - void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> - : std::true_type {}; - -template <class Variant, class T> -struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {}; - -template <class Variant, class T> -struct IndexOfConstructedType< - Variant, T, - void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> - : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {}; - -template <std::size_t... Is> -struct ContainsVariantNPos - : absl::negation<std::is_same< // NOLINT - absl::integer_sequence<bool, 0 <= Is...>, - absl::integer_sequence<bool, Is != absl::variant_npos...>>> {}; - -template <class Op, class... QualifiedVariants> -using RawVisitResult = - absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>; - -// NOTE: The spec requires that all return-paths yield the same type and is not -// SFINAE-friendly, so we can deduce the return type by examining the first -// result. If it's not callable, then we get an error, but are compliant and -// fast to compile. -// TODO(calabrese) Possibly rewrite in a way that yields better compile errors -// at the cost of longer compile-times. -template <class Op, class... QualifiedVariants> -struct VisitResultImpl { - using type = - absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>; -}; - -// Done in two steps intentionally so that we don't cause substitution to fail. -template <class Op, class... QualifiedVariants> -using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type; - -template <class Op, class... QualifiedVariants> -struct PerformVisitation { - using ReturnType = VisitResult<Op, QualifiedVariants...>; - - template <std::size_t... Is> - constexpr ReturnType operator()(SizeT<Is>... indices) const { - return Run(typename ContainsVariantNPos<Is...>::type{}, - absl::index_sequence_for<QualifiedVariants...>(), indices...); - } - - 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>( - absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...); - } - - template <std::size_t... TupIs, std::size_t... Is> - [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/, - index_sequence<TupIs...>, SizeT<Is>...) const { - absl::variant_internal::ThrowBadVariantAccess(); - } - - // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations - // Attempts using lambda variadic captures fail on current GCC. - std::tuple<QualifiedVariants&&...> variant_tup; - Op&& op; -}; - -template <class... T> -union Union; - -// We want to allow for variant<> to be trivial. For that, we need the default -// constructor to be trivial, which means we can't define it ourselves. -// Instead, we use a non-default constructor that takes NoopConstructorTag -// that doesn't affect the triviality of the types. -struct NoopConstructorTag {}; - -template <std::size_t I> -struct EmplaceTag {}; - -template <> -union Union<> { - constexpr explicit Union(NoopConstructorTag) noexcept {} -}; - -// Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined -// deleted destructor from the `std::is_destructible` check below. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4624) -#endif // _MSC_VER - -template <class Head, class... Tail> -union Union<Head, Tail...> { - using TailUnion = Union<Tail...>; - - explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept - : tail(NoopConstructorTag()) {} - - template <class... P> - explicit constexpr Union(EmplaceTag<0>, P&&... args) - : head(absl::forward<P>(args)...) {} - - template <std::size_t I, class... P> - explicit constexpr Union(EmplaceTag<I>, P&&... args) - : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {} - - Head head; - TailUnion tail; -}; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -// TODO(calabrese) Just contain a Union in this union (certain configs fail). -template <class... T> -union DestructibleUnionImpl; - -template <> -union DestructibleUnionImpl<> { - constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {} -}; - -template <class Head, class... Tail> -union DestructibleUnionImpl<Head, Tail...> { - using TailUnion = DestructibleUnionImpl<Tail...>; - - explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept - : tail(NoopConstructorTag()) {} - - template <class... P> - explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args) - : head(absl::forward<P>(args)...) {} - - template <std::size_t I, class... P> - explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args) - : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {} - - ~DestructibleUnionImpl() {} - - Head head; - TailUnion tail; -}; - -// This union type is destructible even if one or more T are not trivially -// destructible. In the case that all T are trivially destructible, then so is -// this resultant type. -template <class... T> -using DestructibleUnion = - absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>, - DestructibleUnionImpl<T...>>; - -// Deepest base, containing the actual union and the discriminator -template <class H, class... T> -class VariantStateBase { - protected: - using Variant = variant<H, T...>; - - template <class LazyH = H, - class ConstructibleH = absl::enable_if_t< - std::is_default_constructible<LazyH>::value, LazyH>> - constexpr VariantStateBase() noexcept( - std::is_nothrow_default_constructible<ConstructibleH>::value) - : state_(EmplaceTag<0>()), index_(0) {} - - template <std::size_t I, class... P> - explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args) - : state_(tag, absl::forward<P>(args)...), index_(I) {} - - explicit constexpr VariantStateBase(NoopConstructorTag) - : state_(NoopConstructorTag()), index_(variant_npos) {} - - void destroy() {} // Does nothing (shadowed in child if non-trivial) - - DestructibleUnion<H, T...> state_; - std::size_t index_; -}; - -using absl::internal::identity; - -// OverloadSet::Overload() is a unary function which is overloaded to -// take any of the element types of the variant, by reference-to-const. -// The return type of the overload on T is identity<T>, so that you -// can statically determine which overload was called. -// -// Overload() is not defined, so it can only be called in unevaluated -// contexts. -template <typename... Ts> -struct OverloadSet; - -template <typename T, typename... Ts> -struct OverloadSet<T, Ts...> : OverloadSet<Ts...> { - using Base = OverloadSet<Ts...>; - static identity<T> Overload(const T&); - using Base::Overload; -}; - -template <> -struct OverloadSet<> { - // For any case not handled above. - static void Overload(...); -}; - -template <class T> -using LessThanResult = decltype(std::declval<T>() < std::declval<T>()); - -template <class T> -using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>()); - -template <class T> -using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>()); - -template <class T> -using GreaterThanOrEqualResult = - decltype(std::declval<T>() >= std::declval<T>()); - -template <class T> -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, - bool>; - -template <class... T> -using RequireAllHaveNotEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, NotEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveLessThanT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, LessThanResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveLessThanOrEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, LessThanOrEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveGreaterThanOrEqualT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, GreaterThanOrEqualResult, T>...>::value, - bool>; - -template <class... T> -using RequireAllHaveGreaterThanT = - absl::enable_if_t<absl::conjunction<is_detected_convertible< - bool, GreaterThanResult, T>...>::value, - bool>; - -// Helper template containing implementations details of variant that can't go -// in the private section. For convenience, this takes the variant type as a -// single template parameter. -template <typename T> -struct VariantHelper; - -template <typename... Ts> -struct VariantHelper<variant<Ts...>> { - // Type metafunction which returns the element type selected if - // OverloadSet::Overload() is well-formed when called with argument type U. - template <typename U> - using BestMatch = decltype( - variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>())); - - // Type metafunction which returns true if OverloadSet::Overload() is - // well-formed when called with argument type U. - // CanAccept can't be just an alias because there is a MSVC bug on parameter - // pack expansion involving decltype. - template <typename U> - struct CanAccept : - std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {}; - - // Type metafunction which returns true if Other is an instantiation of - // variant, and variants's converting constructor from Other will be - // well-formed. We will use this to remove constructors that would be - // ill-formed from the overload set. - template <typename Other> - struct CanConvertFrom; - - template <typename... Us> - struct CanConvertFrom<variant<Us...>> - : public absl::conjunction<CanAccept<Us>...> {}; -}; - -// A type with nontrivial copy ctor and trivial move ctor. -struct TrivialMoveOnly { - TrivialMoveOnly(TrivialMoveOnly&&) = default; -}; - -// Trait class to detect whether a type is trivially move constructible. -// A union's defaulted copy/move constructor is deleted if any variant member's -// copy/move constructor is nontrivial. -template <typename T> -struct IsTriviallyMoveConstructible: - std::is_move_constructible<Union<T, TrivialMoveOnly>> {}; - -// To guarantee triviality of all special-member functions that can be trivial, -// we use a chain of conditional bases for each one. -// The order of inheritance of bases from child to base are logically: -// -// variant -// VariantCopyAssignBase -// VariantMoveAssignBase -// VariantCopyBase -// VariantMoveBase -// VariantStateBaseDestructor -// VariantStateBase -// -// Note that there is a separate branch at each base that is dependent on -// whether or not that corresponding special-member-function can be trivial in -// the resultant variant type. - -template <class... T> -class VariantStateBaseDestructorNontrivial; - -template <class... T> -class VariantMoveBaseNontrivial; - -template <class... T> -class VariantCopyBaseNontrivial; - -template <class... T> -class VariantMoveAssignBaseNontrivial; - -template <class... T> -class VariantCopyAssignBaseNontrivial; - -// Base that is dependent on whether or not the destructor can be trivial. -template <class... T> -using VariantStateBaseDestructor = - absl::conditional_t<std::is_destructible<Union<T...>>::value, - VariantStateBase<T...>, - VariantStateBaseDestructorNontrivial<T...>>; - -// Base that is dependent on whether or not the move-constructor can be -// implicitly generated by the compiler (trivial or deleted). -// Previously we were using `std::is_move_constructible<Union<T...>>` to check -// whether all Ts have trivial move constructor, but it ran into a GCC bug: -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866 -// So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to -// work around the bug. -template <class... T> -using VariantMoveBase = absl::conditional_t< - absl::disjunction< - absl::negation<absl::conjunction<std::is_move_constructible<T>...>>, - absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value, - VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>; - -// Base that is dependent on whether or not the copy-constructor can be trivial. -template <class... T> -using VariantCopyBase = absl::conditional_t< - absl::disjunction< - absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>, - std::is_copy_constructible<Union<T...>>>::value, - VariantMoveBase<T...>, VariantCopyBaseNontrivial<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<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<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> -using VariantBase = VariantCopyAssignBase<T...>; - -template <class... T> -class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> { - private: - using Base = VariantStateBase<T...>; - - protected: - using Base::Base; - - VariantStateBaseDestructorNontrivial() = default; - VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) = - default; - VariantStateBaseDestructorNontrivial( - const VariantStateBaseDestructorNontrivial&) = default; - VariantStateBaseDestructorNontrivial& operator=( - VariantStateBaseDestructorNontrivial&&) = default; - VariantStateBaseDestructorNontrivial& operator=( - const VariantStateBaseDestructorNontrivial&) = default; - - struct Destroyer { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - variant_internal::AccessUnion(self->state_, i).~Alternative(); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const { - // This space intentionally left blank - } - - VariantStateBaseDestructorNontrivial* self; - }; - - void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); } - - ~VariantStateBaseDestructorNontrivial() { destroy(); } - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> { - private: - using Base = VariantStateBaseDestructor<T...>; - - protected: - using Base::Base; - - struct Construct { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - ::new (static_cast<void*>(&self->state_)) Alternative( - variant_internal::AccessUnion(absl::move(other->state_), i)); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const {} - - VariantMoveBaseNontrivial* self; - VariantMoveBaseNontrivial* other; - }; - - VariantMoveBaseNontrivial() = default; - VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept( - absl::conjunction<std::is_nothrow_move_constructible<T>...>::value) - : Base(NoopConstructorTag()) { - VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_); - index_ = other.index_; - } - - VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default; - - VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default; - VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) = - default; - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> { - private: - using Base = VariantMoveBase<T...>; - - protected: - using Base::Base; - - VariantCopyBaseNontrivial() = default; - VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default; - - struct Construct { - template <std::size_t I> - void operator()(SizeT<I> i) const { - using Alternative = - typename absl::variant_alternative<I, variant<T...>>::type; - ::new (static_cast<void*>(&self->state_)) - Alternative(variant_internal::AccessUnion(other->state_, i)); - } - - void operator()(SizeT<absl::variant_npos> /*i*/) const {} - - VariantCopyBaseNontrivial* self; - const VariantCopyBaseNontrivial* other; - }; - - VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other) - : Base(NoopConstructorTag()) { - VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_); - index_ = other.index_; - } - - VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default; - VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) = - default; - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> { - friend struct VariantCoreAccess; - - private: - using Base = VariantCopyBase<T...>; - - protected: - using Base::Base; - - VariantMoveAssignBaseNontrivial() = default; - VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default; - VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) = - default; - VariantMoveAssignBaseNontrivial& operator=( - VariantMoveAssignBaseNontrivial const&) = default; - - VariantMoveAssignBaseNontrivial& - operator=(VariantMoveAssignBaseNontrivial&& other) noexcept( - absl::conjunction<std::is_nothrow_move_constructible<T>..., - std::is_nothrow_move_assignable<T>...>::value) { - VisitIndices<sizeof...(T)>::Run( - VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_); - return *this; - } - - protected: - using Base::index_; - using Base::state_; -}; - -template <class... T> -class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> { - friend struct VariantCoreAccess; - - private: - using Base = VariantMoveAssignBase<T...>; - - protected: - using Base::Base; - - VariantCopyAssignBaseNontrivial() = default; - VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default; - VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) = - default; - VariantCopyAssignBaseNontrivial& operator=( - VariantCopyAssignBaseNontrivial&&) = default; - - VariantCopyAssignBaseNontrivial& operator=( - const VariantCopyAssignBaseNontrivial& other) { - VisitIndices<sizeof...(T)>::Run( - VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_); - return *this; - } - - protected: - using Base::index_; - using Base::state_; -}; - -//////////////////////////////////////// -// Visitors for Comparison Operations // -//////////////////////////////////////// - -template <class... Types> -struct EqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct NotEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct LessThanOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct GreaterThanOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return false; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct LessThanOrEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w); - } -}; - -template <class... Types> -struct GreaterThanOrEqualsOp { - const variant<Types...>* v; - const variant<Types...>* w; - - constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { - return true; - } - - template <std::size_t I> - constexpr bool operator()(SizeT<I> /*v_i*/) const { - return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w); - } -}; - -// Precondition: v.index() == w.index(); -template <class... Types> -struct SwapSameIndex { - variant<Types...>* v; - variant<Types...>* w; - template <std::size_t I> - void operator()(SizeT<I>) const { - type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v), - VariantCoreAccess::Access<I>(*w)); - } - - void operator()(SizeT<variant_npos>) const {} -}; - -// TODO(calabrese) do this from a different namespace for proper adl usage -template <class... Types> -struct Swap { - variant<Types...>* v; - variant<Types...>* w; - - void generic_swap() const { - variant<Types...> tmp(std::move(*w)); - VariantCoreAccess::Destroy(*w); - VariantCoreAccess::InitFrom(*w, std::move(*v)); - VariantCoreAccess::Destroy(*v); - VariantCoreAccess::InitFrom(*v, std::move(tmp)); - } - - void operator()(SizeT<absl::variant_npos> /*w_i*/) const { - if (!v->valueless_by_exception()) { - generic_swap(); - } - } - - template <std::size_t Wi> - void operator()(SizeT<Wi> /*w_i*/) { - if (v->index() == Wi) { - VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi); - } else { - generic_swap(); - } - } -}; - -template <typename Variant, typename = void, typename... Ts> -struct VariantHashBase { - VariantHashBase() = delete; - VariantHashBase(const VariantHashBase&) = delete; - VariantHashBase(VariantHashBase&&) = delete; - VariantHashBase& operator=(const VariantHashBase&) = delete; - VariantHashBase& operator=(VariantHashBase&&) = delete; -}; - -struct VariantHashVisitor { - template <typename T> - size_t operator()(const T& t) { - return std::hash<T>{}(t); - } -}; - -template <typename Variant, typename... Ts> -struct VariantHashBase<Variant, - absl::enable_if_t<absl::conjunction< - type_traits_internal::IsHashable<Ts>...>::value>, - Ts...> { - using argument_type = Variant; - using result_type = size_t; - size_t operator()(const Variant& var) const { - type_traits_internal::AssertHashEnabled<Ts...>(); - if (var.valueless_by_exception()) { - return 239799884; - } - size_t result = VisitIndices<variant_size<Variant>::value>::Run( - PerformVisitation<VariantHashVisitor, const Variant&>{ - std::forward_as_tuple(var), VariantHashVisitor{}}, - var.index()); - // Combine the index and the hash result in order to distinguish - // std::variant<int, int> holding the same value as different alternative. - return result ^ var.index(); - } -}; - -} // namespace variant_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // !defined(ABSL_USES_STD_VARIANT) -#endif // ABSL_TYPES_variant_internal_H_ diff --git a/third_party/abseil_cpp/absl/types/optional.h b/third_party/abseil_cpp/absl/types/optional.h deleted file mode 100644 index 61540cfdb26a..000000000000 --- a/third_party/abseil_cpp/absl/types/optional.h +++ /dev/null @@ -1,776 +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. -// -// ----------------------------------------------------------------------------- -// optional.h -// ----------------------------------------------------------------------------- -// -// This header file defines the `absl::optional` type for holding a value which -// may or may not be present. This type is useful for providing value semantics -// for operations that may either wish to return or hold "something-or-nothing". -// -// Example: -// -// // A common way to signal operation failure is to provide an output -// // parameter and a bool return type: -// bool AcquireResource(const Input&, Resource * out); -// -// // Providing an absl::optional return type provides a cleaner API: -// absl::optional<Resource> AcquireResource(const Input&); -// -// `absl::optional` is a C++11 compatible version of the C++17 `std::optional` -// abstraction and is designed to be a drop-in replacement for code compliant -// with C++17. -#ifndef ABSL_TYPES_OPTIONAL_H_ -#define ABSL_TYPES_OPTIONAL_H_ - -#include "absl/base/config.h" // TODO(calabrese) IWYU removal? -#include "absl/utility/utility.h" - -#ifdef ABSL_USES_STD_OPTIONAL - -#include <optional> // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_optional_access; -using std::optional; -using std::make_optional; -using std::nullopt_t; -using std::nullopt; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_OPTIONAL - -#include <cassert> -#include <functional> -#include <initializer_list> -#include <type_traits> -#include <utility> - -#include "absl/base/attributes.h" -#include "absl/base/internal/inline_variable.h" -#include "absl/meta/type_traits.h" -#include "absl/types/bad_optional_access.h" -#include "absl/types/internal/optional.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// nullopt_t -// -// Class type for `absl::nullopt` used to indicate an `absl::optional<T>` type -// that does not contain a value. -struct nullopt_t { - // It must not be default-constructible to avoid ambiguity for opt = {}. - explicit constexpr nullopt_t(optional_internal::init_t) noexcept {} -}; - -// nullopt -// -// A tag constant of type `absl::nullopt_t` used to indicate an empty -// `absl::optional` in certain functions, such as construction or assignment. -ABSL_INTERNAL_INLINE_CONSTEXPR(nullopt_t, nullopt, - nullopt_t(optional_internal::init_t())); - -// ----------------------------------------------------------------------------- -// absl::optional -// ----------------------------------------------------------------------------- -// -// A value of type `absl::optional<T>` holds either a value of `T` or an -// "empty" value. When it holds a value of `T`, it stores it as a direct -// sub-object, so `sizeof(optional<T>)` is approximately -// `sizeof(T) + sizeof(bool)`. -// -// This implementation is based on the specification in the latest draft of the -// C++17 `std::optional` specification as of May 2017, section 20.6. -// -// Differences between `absl::optional<T>` and `std::optional<T>` include: -// -// * `constexpr` is not used for non-const member functions. -// (dependency on some differences between C++11 and C++14.) -// * `absl::nullopt` and `absl::in_place` are not declared `constexpr`. We -// need the inline variable support in C++17 for external linkage. -// * Throws `absl::bad_optional_access` instead of -// `std::bad_optional_access`. -// * `make_optional()` cannot be declared `constexpr` due to the absence of -// guaranteed copy elision. -// * The move constructor's `noexcept` specification is stronger, i.e. if the -// default allocator is non-throwing (via setting -// `ABSL_ALLOCATOR_NOTHROW`), it evaluates to `noexcept(true)`, because -// we assume -// a) move constructors should only throw due to allocation failure and -// b) if T's move constructor allocates, it uses the same allocation -// function as the default allocator. -// -template <typename T> -class optional : private optional_internal::optional_data<T>, - private optional_internal::optional_ctor_base< - optional_internal::ctor_copy_traits<T>::traits>, - private optional_internal::optional_assign_base< - optional_internal::assign_copy_traits<T>::traits> { - using data_base = optional_internal::optional_data<T>; - - public: - typedef T value_type; - - // Constructors - - // Constructs an `optional` holding an empty value, NOT a default constructed - // `T`. - constexpr optional() noexcept {} - - // Constructs an `optional` initialized with `nullopt` to hold an empty value. - constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit) - - // Copy constructor, standard semantics - optional(const optional&) = default; - - // Move constructor, standard semantics - optional(optional&&) = default; - - // Constructs a non-empty `optional` direct-initialized value of type `T` from - // the arguments `std::forward<Args>(args)...` within the `optional`. - // (The `in_place_t` is a tag used to indicate that the contained object - // should be constructed in-place.) - template <typename InPlaceT, typename... Args, - absl::enable_if_t<absl::conjunction< - std::is_same<InPlaceT, in_place_t>, - std::is_constructible<T, Args&&...> >::value>* = nullptr> - constexpr explicit optional(InPlaceT, Args&&... args) - : data_base(in_place_t(), absl::forward<Args>(args)...) {} - - // Constructs a non-empty `optional` direct-initialized value of type `T` from - // the arguments of an initializer_list and `std::forward<Args>(args)...`. - // (The `in_place_t` is a tag used to indicate that the contained object - // should be constructed in-place.) - template <typename U, typename... Args, - typename = typename std::enable_if<std::is_constructible< - T, std::initializer_list<U>&, Args&&...>::value>::type> - constexpr explicit optional(in_place_t, std::initializer_list<U> il, - Args&&... args) - : data_base(in_place_t(), il, absl::forward<Args>(args)...) { - } - - // Value constructor (implicit) - template < - typename U = T, - typename std::enable_if< - absl::conjunction<absl::negation<std::is_same< - in_place_t, typename std::decay<U>::type> >, - absl::negation<std::is_same< - optional<T>, typename std::decay<U>::type> >, - std::is_convertible<U&&, T>, - std::is_constructible<T, U&&> >::value, - bool>::type = false> - constexpr optional(U&& v) : data_base(in_place_t(), absl::forward<U>(v)) {} - - // Value constructor (explicit) - template < - typename U = T, - typename std::enable_if< - absl::conjunction<absl::negation<std::is_same< - in_place_t, typename std::decay<U>::type>>, - absl::negation<std::is_same< - optional<T>, typename std::decay<U>::type>>, - absl::negation<std::is_convertible<U&&, T>>, - std::is_constructible<T, U&&>>::value, - bool>::type = false> - explicit constexpr optional(U&& v) - : data_base(in_place_t(), absl::forward<U>(v)) {} - - // Converting copy constructor (implicit) - template <typename U, - typename std::enable_if< - absl::conjunction< - absl::negation<std::is_same<T, U> >, - std::is_constructible<T, const U&>, - absl::negation< - optional_internal:: - is_constructible_convertible_from_optional<T, U> >, - std::is_convertible<const U&, T> >::value, - bool>::type = false> - optional(const optional<U>& rhs) { - if (rhs) { - this->construct(*rhs); - } - } - - // Converting copy constructor (explicit) - template <typename U, - typename std::enable_if< - absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, - absl::negation< - optional_internal:: - is_constructible_convertible_from_optional<T, U>>, - absl::negation<std::is_convertible<const U&, T>>>::value, - bool>::type = false> - explicit optional(const optional<U>& rhs) { - if (rhs) { - this->construct(*rhs); - } - } - - // Converting move constructor (implicit) - template <typename U, - typename std::enable_if< - absl::conjunction< - absl::negation<std::is_same<T, U> >, - std::is_constructible<T, U&&>, - absl::negation< - optional_internal:: - is_constructible_convertible_from_optional<T, U> >, - std::is_convertible<U&&, T> >::value, - bool>::type = false> - optional(optional<U>&& rhs) { - if (rhs) { - this->construct(std::move(*rhs)); - } - } - - // Converting move constructor (explicit) - template < - typename U, - typename std::enable_if< - absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>, - absl::negation< - optional_internal::is_constructible_convertible_from_optional< - T, U>>, - absl::negation<std::is_convertible<U&&, T>>>::value, - bool>::type = false> - explicit optional(optional<U>&& rhs) { - if (rhs) { - this->construct(std::move(*rhs)); - } - } - - // Destructor. Trivial if `T` is trivially destructible. - ~optional() = default; - - // Assignment Operators - - // Assignment from `nullopt` - // - // Example: - // - // struct S { int value; }; - // optional<S> opt = absl::nullopt; // Could also use opt = { }; - optional& operator=(nullopt_t) noexcept { - this->destruct(); - return *this; - } - - // Copy assignment operator, standard semantics - optional& operator=(const optional& src) = default; - - // Move assignment operator, standard semantics - optional& operator=(optional&& src) = default; - - // Value assignment operators - template < - typename U = T, - typename = typename std::enable_if<absl::conjunction< - absl::negation< - std::is_same<optional<T>, typename std::decay<U>::type>>, - absl::negation< - absl::conjunction<std::is_scalar<T>, - std::is_same<T, typename std::decay<U>::type>>>, - std::is_constructible<T, U>, std::is_assignable<T&, U>>::value>::type> - optional& operator=(U&& v) { - this->assign(std::forward<U>(v)); - return *this; - } - - template < - typename U, - typename = typename std::enable_if<absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>, - absl::negation< - optional_internal:: - is_constructible_convertible_assignable_from_optional< - T, U>>>::value>::type> - optional& operator=(const optional<U>& rhs) { - if (rhs) { - this->assign(*rhs); - } else { - this->destruct(); - } - return *this; - } - - template <typename U, - typename = typename std::enable_if<absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U>, - std::is_assignable<T&, U>, - absl::negation< - optional_internal:: - is_constructible_convertible_assignable_from_optional< - T, U>>>::value>::type> - optional& operator=(optional<U>&& rhs) { - if (rhs) { - this->assign(std::move(*rhs)); - } else { - this->destruct(); - } - return *this; - } - - // Modifiers - - // optional::reset() - // - // Destroys the inner `T` value of an `absl::optional` if one is present. - ABSL_ATTRIBUTE_REINITIALIZES void reset() noexcept { this->destruct(); } - - // optional::emplace() - // - // (Re)constructs the underlying `T` in-place with the given forwarded - // arguments. - // - // Example: - // - // optional<Foo> opt; - // opt.emplace(arg1,arg2,arg3); // Constructs Foo(arg1,arg2,arg3) - // - // If the optional is non-empty, and the `args` refer to subobjects of the - // current object, then behaviour is undefined, because the current object - // will be destructed before the new object is constructed with `args`. - template <typename... Args, - typename = typename std::enable_if< - std::is_constructible<T, Args&&...>::value>::type> - T& emplace(Args&&... args) { - this->destruct(); - this->construct(std::forward<Args>(args)...); - return reference(); - } - - // Emplace reconstruction overload for an initializer list and the given - // forwarded arguments. - // - // Example: - // - // struct Foo { - // Foo(std::initializer_list<int>); - // }; - // - // optional<Foo> opt; - // opt.emplace({1,2,3}); // Constructs Foo({1,2,3}) - template <typename U, typename... Args, - typename = typename std::enable_if<std::is_constructible< - T, std::initializer_list<U>&, Args&&...>::value>::type> - T& emplace(std::initializer_list<U> il, Args&&... args) { - this->destruct(); - this->construct(il, std::forward<Args>(args)...); - return reference(); - } - - // Swaps - - // Swap, standard semantics - void swap(optional& rhs) noexcept( - std::is_nothrow_move_constructible<T>::value&& - type_traits_internal::IsNothrowSwappable<T>::value) { - if (*this) { - if (rhs) { - type_traits_internal::Swap(**this, *rhs); - } else { - rhs.construct(std::move(**this)); - this->destruct(); - } - } else { - if (rhs) { - this->construct(std::move(*rhs)); - rhs.destruct(); - } else { - // No effect (swap(disengaged, disengaged)). - } - } - } - - // Observers - - // optional::operator->() - // - // Accesses the underlying `T` value's member `m` of an `optional`. If the - // `optional` is empty, behavior is undefined. - // - // If you need myOpt->foo in constexpr, use (*myOpt).foo instead. - const T* operator->() const { - ABSL_HARDENING_ASSERT(this->engaged_); - return std::addressof(this->data_); - } - T* operator->() { - ABSL_HARDENING_ASSERT(this->engaged_); - return std::addressof(this->data_); - } - - // optional::operator*() - // - // Accesses the underlying `T` value of an `optional`. If the `optional` is - // empty, behavior is undefined. - constexpr const T& operator*() const& { - return ABSL_HARDENING_ASSERT(this->engaged_), reference(); - } - T& operator*() & { - ABSL_HARDENING_ASSERT(this->engaged_); - return reference(); - } - constexpr const T&& operator*() const && { - return ABSL_HARDENING_ASSERT(this->engaged_), absl::move(reference()); - } - T&& operator*() && { - ABSL_HARDENING_ASSERT(this->engaged_); - return std::move(reference()); - } - - // optional::operator bool() - // - // Returns false if and only if the `optional` is empty. - // - // if (opt) { - // // do something with *opt or opt->; - // } else { - // // opt is empty. - // } - // - constexpr explicit operator bool() const noexcept { return this->engaged_; } - - // optional::has_value() - // - // Determines whether the `optional` contains a value. Returns `false` if and - // only if `*this` is empty. - constexpr bool has_value() const noexcept { return this->engaged_; } - -// Suppress bogus warning on MSVC: MSVC complains call to reference() after -// throw_bad_optional_access() is unreachable. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4702) -#endif // _MSC_VER - // optional::value() - // - // Returns a reference to an `optional`s underlying value. The constness - // and lvalue/rvalue-ness of the `optional` is preserved to the view of - // the `T` sub-object. Throws `absl::bad_optional_access` when the `optional` - // is empty. - constexpr const T& value() const & { - return static_cast<bool>(*this) - ? reference() - : (optional_internal::throw_bad_optional_access(), reference()); - } - T& value() & { - return static_cast<bool>(*this) - ? reference() - : (optional_internal::throw_bad_optional_access(), reference()); - } - T&& value() && { // NOLINT(build/c++11) - return std::move( - static_cast<bool>(*this) - ? reference() - : (optional_internal::throw_bad_optional_access(), reference())); - } - constexpr const T&& value() const && { // NOLINT(build/c++11) - return absl::move( - static_cast<bool>(*this) - ? reference() - : (optional_internal::throw_bad_optional_access(), reference())); - } -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - - // optional::value_or() - // - // Returns either the value of `T` or a passed default `v` if the `optional` - // is empty. - template <typename U> - constexpr T value_or(U&& v) const& { - static_assert(std::is_copy_constructible<value_type>::value, - "optional<T>::value_or: T must be copy constructible"); - static_assert(std::is_convertible<U&&, value_type>::value, - "optional<T>::value_or: U must be convertible to T"); - return static_cast<bool>(*this) - ? **this - : static_cast<T>(absl::forward<U>(v)); - } - template <typename U> - T value_or(U&& v) && { // NOLINT(build/c++11) - static_assert(std::is_move_constructible<value_type>::value, - "optional<T>::value_or: T must be move constructible"); - static_assert(std::is_convertible<U&&, value_type>::value, - "optional<T>::value_or: U must be convertible to T"); - return static_cast<bool>(*this) ? std::move(**this) - : static_cast<T>(std::forward<U>(v)); - } - - private: - // Private accessors for internal storage viewed as reference to T. - constexpr const T& reference() const { return this->data_; } - T& reference() { return this->data_; } - - // T constraint checks. You can't have an optional of nullopt_t, in_place_t - // or a reference. - static_assert( - !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value, - "optional<nullopt_t> is not allowed."); - static_assert( - !std::is_same<in_place_t, typename std::remove_cv<T>::type>::value, - "optional<in_place_t> is not allowed."); - static_assert(!std::is_reference<T>::value, - "optional<reference> is not allowed."); -}; - -// Non-member functions - -// swap() -// -// Performs a swap between two `absl::optional` objects, using standard -// semantics. -template <typename T, typename std::enable_if< - std::is_move_constructible<T>::value && - type_traits_internal::IsSwappable<T>::value, - bool>::type = false> -void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) { - a.swap(b); -} - -// make_optional() -// -// Creates a non-empty `optional<T>` where the type of `T` is deduced. An -// `absl::optional` can also be explicitly instantiated with -// `make_optional<T>(v)`. -// -// Note: `make_optional()` constructions may be declared `constexpr` for -// trivially copyable types `T`. Non-trivial types require copy elision -// support in C++17 for `make_optional` to support `constexpr` on such -// non-trivial types. -// -// Example: -// -// constexpr absl::optional<int> opt = absl::make_optional(1); -// static_assert(opt.value() == 1, ""); -template <typename T> -constexpr optional<typename std::decay<T>::type> make_optional(T&& v) { - return optional<typename std::decay<T>::type>(absl::forward<T>(v)); -} - -template <typename T, typename... Args> -constexpr optional<T> make_optional(Args&&... args) { - return optional<T>(in_place_t(), absl::forward<Args>(args)...); -} - -template <typename T, typename U, typename... Args> -constexpr optional<T> make_optional(std::initializer_list<U> il, - Args&&... args) { - return optional<T>(in_place_t(), il, - absl::forward<Args>(args)...); -} - -// Relational operators [optional.relops] - -// Empty optionals are considered equal to each other and less than non-empty -// optionals. Supports relations between optional<T> and optional<U>, between -// optional<T> and U, and between optional<T> and nullopt. -// -// Note: We're careful to support T having non-bool relationals. - -// Requires: The expression, e.g. "*x == *y" shall be well-formed and its result -// shall be convertible to bool. -// The C++17 (N4606) "Returns:" statements are translated into -// code in an obvious way here, and the original text retained as function docs. -// Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true; -// otherwise *x == *y. -template <typename T, typename U> -constexpr auto operator==(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x == *y)) { - return static_cast<bool>(x) != static_cast<bool>(y) - ? false - : static_cast<bool>(x) == false ? true - : static_cast<bool>(*x == *y); -} - -// Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false; -// otherwise *x != *y. -template <typename T, typename U> -constexpr auto operator!=(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x != *y)) { - return static_cast<bool>(x) != static_cast<bool>(y) - ? true - : static_cast<bool>(x) == false ? false - : static_cast<bool>(*x != *y); -} -// Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y. -template <typename T, typename U> -constexpr auto operator<(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x < *y)) { - return !y ? false : !x ? true : static_cast<bool>(*x < *y); -} -// Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y. -template <typename T, typename U> -constexpr auto operator>(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x > *y)) { - return !x ? false : !y ? true : static_cast<bool>(*x > *y); -} -// Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y. -template <typename T, typename U> -constexpr auto operator<=(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x <= *y)) { - return !x ? true : !y ? false : static_cast<bool>(*x <= *y); -} -// Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y. -template <typename T, typename U> -constexpr auto operator>=(const optional<T>& x, const optional<U>& y) - -> decltype(optional_internal::convertible_to_bool(*x >= *y)) { - return !y ? true : !x ? false : static_cast<bool>(*x >= *y); -} - -// Comparison with nullopt [optional.nullops] -// The C++17 (N4606) "Returns:" statements are used directly here. -template <typename T> -constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept { - return !x; -} -template <typename T> -constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept { - return !x; -} -template <typename T> -constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept { - return static_cast<bool>(x); -} -template <typename T> -constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept { - return static_cast<bool>(x); -} -template <typename T> -constexpr bool operator<(const optional<T>&, nullopt_t) noexcept { - return false; -} -template <typename T> -constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept { - return static_cast<bool>(x); -} -template <typename T> -constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept { - return !x; -} -template <typename T> -constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept { - return true; -} -template <typename T> -constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept { - return static_cast<bool>(x); -} -template <typename T> -constexpr bool operator>(nullopt_t, const optional<T>&) noexcept { - return false; -} -template <typename T> -constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept { - return true; -} -template <typename T> -constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept { - return !x; -} - -// Comparison with T [optional.comp_with_t] - -// Requires: The expression, e.g. "*x == v" shall be well-formed and its result -// shall be convertible to bool. -// The C++17 (N4606) "Equivalent to:" statements are used directly here. -template <typename T, typename U> -constexpr auto operator==(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x == v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x == v) : false; -} -template <typename T, typename U> -constexpr auto operator==(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v == *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v == *x) : false; -} -template <typename T, typename U> -constexpr auto operator!=(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x != v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x != v) : true; -} -template <typename T, typename U> -constexpr auto operator!=(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v != *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v != *x) : true; -} -template <typename T, typename U> -constexpr auto operator<(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x < v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x < v) : true; -} -template <typename T, typename U> -constexpr auto operator<(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v < *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v < *x) : false; -} -template <typename T, typename U> -constexpr auto operator<=(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x <= v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x <= v) : true; -} -template <typename T, typename U> -constexpr auto operator<=(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v <= *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v <= *x) : false; -} -template <typename T, typename U> -constexpr auto operator>(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x > v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x > v) : false; -} -template <typename T, typename U> -constexpr auto operator>(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v > *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v > *x) : true; -} -template <typename T, typename U> -constexpr auto operator>=(const optional<T>& x, const U& v) - -> decltype(optional_internal::convertible_to_bool(*x >= v)) { - return static_cast<bool>(x) ? static_cast<bool>(*x >= v) : false; -} -template <typename T, typename U> -constexpr auto operator>=(const U& v, const optional<T>& x) - -> decltype(optional_internal::convertible_to_bool(v >= *x)) { - return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true; -} - -ABSL_NAMESPACE_END -} // namespace absl - -namespace std { - -// std::hash specialization for absl::optional. -template <typename T> -struct hash<absl::optional<T> > - : absl::optional_internal::optional_hash_base<T> {}; - -} // namespace std - -#undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS - -#endif // ABSL_USES_STD_OPTIONAL - -#endif // ABSL_TYPES_OPTIONAL_H_ diff --git a/third_party/abseil_cpp/absl/types/optional_exception_safety_test.cc b/third_party/abseil_cpp/absl/types/optional_exception_safety_test.cc deleted file mode 100644 index 8e5fe851dbb7..000000000000 --- a/third_party/abseil_cpp/absl/types/optional_exception_safety_test.cc +++ /dev/null @@ -1,292 +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/optional.h" - -#include "absl/base/config.h" - -// This test is a no-op when absl::optional is an alias for std::optional and -// when exceptions are not enabled. -#if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS) - -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace { - -using ::testing::AssertionFailure; -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::MakeExceptionSafetyTester; - -using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>; -using Optional = absl::optional<Thrower>; - -using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; -using MoveOptional = absl::optional<MoveThrower>; - -constexpr int kInitialInteger = 5; -constexpr int kUpdatedInteger = 10; - -template <typename OptionalT> -bool ValueThrowsBadOptionalAccess(const OptionalT& optional) try { - return (static_cast<void>(optional.value()), false); -} catch (const absl::bad_optional_access&) { - return true; -} - -template <typename OptionalT> -AssertionResult OptionalInvariants(OptionalT* optional_ptr) { - // Check the current state post-throw for validity - auto& optional = *optional_ptr; - - if (optional.has_value() && ValueThrowsBadOptionalAccess(optional)) { - return AssertionFailure() - << "Optional with value should not throw bad_optional_access when " - "accessing the value."; - } - if (!optional.has_value() && !ValueThrowsBadOptionalAccess(optional)) { - return AssertionFailure() - << "Optional without a value should throw bad_optional_access when " - "accessing the value."; - } - - // Reset to a known state - optional.reset(); - - // Confirm that the known post-reset state is valid - if (optional.has_value()) { - return AssertionFailure() - << "Optional should not contain a value after being reset."; - } - if (!ValueThrowsBadOptionalAccess(optional)) { - return AssertionFailure() << "Optional should throw bad_optional_access " - "when accessing the value after being reset."; - } - - return AssertionSuccess(); -} - -template <typename OptionalT> -AssertionResult CheckDisengaged(OptionalT* optional_ptr) { - auto& optional = *optional_ptr; - - if (optional.has_value()) { - return AssertionFailure() - << "Expected optional to not contain a value but a value was found."; - } - - return AssertionSuccess(); -} - -template <typename OptionalT> -AssertionResult CheckEngaged(OptionalT* optional_ptr) { - auto& optional = *optional_ptr; - - if (!optional.has_value()) { - return AssertionFailure() - << "Expected optional to contain a value but no value was found."; - } - - return AssertionSuccess(); -} - -TEST(OptionalExceptionSafety, ThrowingConstructors) { - auto thrower_nonempty = Optional(Thrower(kInitialInteger)); - testing::TestThrowingCtor<Optional>(thrower_nonempty); - - auto integer_nonempty = absl::optional<int>(kInitialInteger); - testing::TestThrowingCtor<Optional>(integer_nonempty); - testing::TestThrowingCtor<Optional>(std::move(integer_nonempty)); // NOLINT - - testing::TestThrowingCtor<Optional>(kInitialInteger); - using ThrowerVec = std::vector<Thrower, testing::ThrowingAllocator<Thrower>>; - testing::TestThrowingCtor<absl::optional<ThrowerVec>>( - absl::in_place, - std::initializer_list<Thrower>{Thrower(), Thrower(), Thrower()}, - testing::ThrowingAllocator<Thrower>()); -} - -TEST(OptionalExceptionSafety, NothrowConstructors) { - // This constructor is marked noexcept. If it throws, the program will - // terminate. - testing::TestThrowingCtor<MoveOptional>(MoveOptional(kUpdatedInteger)); -} - -TEST(OptionalExceptionSafety, Emplace) { - // Test the basic guarantee plus test the result of optional::has_value() - // is false in all cases - 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)); - - auto emplace_thrower_directly = [](Optional* optional_ptr) { - optional_ptr->emplace(kUpdatedInteger); - }; - EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_directly)); - EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_directly)); - - auto emplace_thrower_copy = [](Optional* optional_ptr) { - auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor); - optional_ptr->emplace(thrower); - }; - EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_copy)); - EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_copy)); -} - -TEST(OptionalExceptionSafety, EverythingThrowsSwap) { - // Test the basic guarantee plus test the result of optional::has_value() - // remains the same - auto test = - MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); - auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithContracts(CheckDisengaged<Optional>); - auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithContracts(CheckEngaged<Optional>); - - auto swap_empty = [](Optional* optional_ptr) { - auto empty = Optional(); - optional_ptr->swap(empty); - }; - EXPECT_TRUE(engaged_test_nonempty.Test(swap_empty)); - - auto swap_nonempty = [](Optional* optional_ptr) { - auto nonempty = - Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor); - optional_ptr->swap(nonempty); - }; - EXPECT_TRUE(disengaged_test_empty.Test(swap_nonempty)); - EXPECT_TRUE(engaged_test_nonempty.Test(swap_nonempty)); -} - -TEST(OptionalExceptionSafety, NoThrowMoveSwap) { - // Tests the nothrow guarantee for optional of T with non-throwing move - { - auto empty = MoveOptional(); - auto nonempty = MoveOptional(kInitialInteger); - EXPECT_TRUE(testing::TestNothrowOp([&]() { nonempty.swap(empty); })); - } - { - auto nonempty = MoveOptional(kUpdatedInteger); - auto empty = MoveOptional(); - EXPECT_TRUE(testing::TestNothrowOp([&]() { empty.swap(nonempty); })); - } - { - auto nonempty_from = MoveOptional(kUpdatedInteger); - auto nonempty_to = MoveOptional(kInitialInteger); - EXPECT_TRUE( - testing::TestNothrowOp([&]() { nonempty_to.swap(nonempty_from); })); - } -} - -TEST(OptionalExceptionSafety, CopyAssign) { - // Test the basic guarantee plus test the result of optional::has_value() - // remains the same - auto test = - MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); - auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithContracts(CheckDisengaged<Optional>); - auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithContracts(CheckEngaged<Optional>); - - auto copyassign_nonempty = [](Optional* optional_ptr) { - auto nonempty = - Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor); - *optional_ptr = nonempty; - }; - EXPECT_TRUE(disengaged_test_empty.Test(copyassign_nonempty)); - EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_nonempty)); - - auto copyassign_thrower = [](Optional* optional_ptr) { - auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor); - *optional_ptr = thrower; - }; - EXPECT_TRUE(disengaged_test_empty.Test(copyassign_thrower)); - EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_thrower)); -} - -TEST(OptionalExceptionSafety, MoveAssign) { - // Test the basic guarantee plus test the result of optional::has_value() - // remains the same - auto test = - MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>); - auto disengaged_test_empty = test.WithInitialValue(Optional()) - .WithContracts(CheckDisengaged<Optional>); - auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger)) - .WithContracts(CheckEngaged<Optional>); - - auto moveassign_empty = [](Optional* optional_ptr) { - auto empty = Optional(); - *optional_ptr = std::move(empty); - }; - EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_empty)); - - auto moveassign_nonempty = [](Optional* optional_ptr) { - auto nonempty = - Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor); - *optional_ptr = std::move(nonempty); - }; - EXPECT_TRUE(disengaged_test_empty.Test(moveassign_nonempty)); - EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_nonempty)); - - auto moveassign_thrower = [](Optional* optional_ptr) { - auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor); - *optional_ptr = std::move(thrower); - }; - EXPECT_TRUE(disengaged_test_empty.Test(moveassign_thrower)); - EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_thrower)); -} - -TEST(OptionalExceptionSafety, NothrowMoveAssign) { - // Tests the nothrow guarantee for optional of T with non-throwing move - { - auto empty = MoveOptional(); - auto nonempty = MoveOptional(kInitialInteger); - EXPECT_TRUE(testing::TestNothrowOp([&]() { nonempty = std::move(empty); })); - } - { - auto nonempty = MoveOptional(kInitialInteger); - auto empty = MoveOptional(); - EXPECT_TRUE(testing::TestNothrowOp([&]() { empty = std::move(nonempty); })); - } - { - auto nonempty_from = MoveOptional(kUpdatedInteger); - auto nonempty_to = MoveOptional(kInitialInteger); - EXPECT_TRUE(testing::TestNothrowOp( - [&]() { nonempty_to = std::move(nonempty_from); })); - } - { - auto thrower = MoveThrower(kUpdatedInteger); - auto empty = MoveOptional(); - EXPECT_TRUE(testing::TestNothrowOp([&]() { empty = std::move(thrower); })); - } - { - auto thrower = MoveThrower(kUpdatedInteger); - auto nonempty = MoveOptional(kInitialInteger); - EXPECT_TRUE( - testing::TestNothrowOp([&]() { nonempty = std::move(thrower); })); - } -} - -} // namespace - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // #if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS) diff --git a/third_party/abseil_cpp/absl/types/optional_test.cc b/third_party/abseil_cpp/absl/types/optional_test.cc deleted file mode 100644 index 7ef142cb9937..000000000000 --- a/third_party/abseil_cpp/absl/types/optional_test.cc +++ /dev/null @@ -1,1659 +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/optional.h" - -// This test is a no-op when absl::optional is an alias for std::optional. -#if !defined(ABSL_USES_STD_OPTIONAL) - -#include <string> -#include <type_traits> -#include <utility> - -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/base/internal/raw_logging.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" - -struct Hashable {}; - -namespace std { -template <> -struct hash<Hashable> { - size_t operator()(const Hashable&) { return 0; } -}; -} // namespace std - -struct NonHashable {}; - -namespace { - -std::string TypeQuals(std::string&) { return "&"; } -std::string TypeQuals(std::string&&) { return "&&"; } -std::string TypeQuals(const std::string&) { return "c&"; } -std::string TypeQuals(const std::string&&) { return "c&&"; } - -struct StructorListener { - int construct0 = 0; - int construct1 = 0; - int construct2 = 0; - int listinit = 0; - int copy = 0; - int move = 0; - int copy_assign = 0; - int move_assign = 0; - int destruct = 0; - int volatile_copy = 0; - int volatile_move = 0; - int volatile_copy_assign = 0; - int volatile_move_assign = 0; -}; - -// Suppress MSVC warnings. -// 4521: multiple copy constructors specified -// 4522: multiple assignment operators specified -// We wrote multiple of them to test that the correct overloads are selected. -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4521) -#pragma warning( disable : 4522) -#endif -struct Listenable { - static StructorListener* listener; - - Listenable() { ++listener->construct0; } - explicit Listenable(int /*unused*/) { ++listener->construct1; } - Listenable(int /*unused*/, int /*unused*/) { ++listener->construct2; } - Listenable(std::initializer_list<int> /*unused*/) { ++listener->listinit; } - Listenable(const Listenable& /*unused*/) { ++listener->copy; } - Listenable(const volatile Listenable& /*unused*/) { - ++listener->volatile_copy; - } - Listenable(volatile Listenable&& /*unused*/) { ++listener->volatile_move; } - Listenable(Listenable&& /*unused*/) { ++listener->move; } - Listenable& operator=(const Listenable& /*unused*/) { - ++listener->copy_assign; - return *this; - } - Listenable& operator=(Listenable&& /*unused*/) { - ++listener->move_assign; - return *this; - } - // use void return type instead of volatile T& to work around GCC warning - // when the assignment's returned reference is ignored. - void operator=(const volatile Listenable& /*unused*/) volatile { - ++listener->volatile_copy_assign; - } - void operator=(volatile Listenable&& /*unused*/) volatile { - ++listener->volatile_move_assign; - } - ~Listenable() { ++listener->destruct; } -}; -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -StructorListener* Listenable::listener = nullptr; - -// ABSL_HAVE_NO_CONSTEXPR_INITIALIZER_LIST is defined to 1 when the standard -// library implementation doesn't marked initializer_list's default constructor -// constexpr. The C++11 standard doesn't specify constexpr on it, but C++14 -// added it. However, libstdc++ 4.7 marked it constexpr. -#if defined(_LIBCPP_VERSION) && \ - (_LIBCPP_STD_VER <= 11 || defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)) -#define ABSL_HAVE_NO_CONSTEXPR_INITIALIZER_LIST 1 -#endif - -struct ConstexprType { - enum CtorTypes { - kCtorDefault, - kCtorInt, - kCtorInitializerList, - kCtorConstChar - }; - constexpr ConstexprType() : x(kCtorDefault) {} - constexpr explicit ConstexprType(int i) : x(kCtorInt) {} -#ifndef ABSL_HAVE_NO_CONSTEXPR_INITIALIZER_LIST - constexpr ConstexprType(std::initializer_list<int> il) - : x(kCtorInitializerList) {} -#endif - constexpr ConstexprType(const char*) // NOLINT(runtime/explicit) - : x(kCtorConstChar) {} - int x; -}; - -struct Copyable { - Copyable() {} - Copyable(const Copyable&) {} - Copyable& operator=(const Copyable&) { return *this; } -}; - -struct MoveableThrow { - MoveableThrow() {} - MoveableThrow(MoveableThrow&&) {} - MoveableThrow& operator=(MoveableThrow&&) { return *this; } -}; - -struct MoveableNoThrow { - MoveableNoThrow() {} - MoveableNoThrow(MoveableNoThrow&&) noexcept {} - MoveableNoThrow& operator=(MoveableNoThrow&&) noexcept { return *this; } -}; - -struct NonMovable { - NonMovable() {} - NonMovable(const NonMovable&) = delete; - NonMovable& operator=(const NonMovable&) = delete; - NonMovable(NonMovable&&) = delete; - NonMovable& operator=(NonMovable&&) = delete; -}; - -struct NoDefault { - NoDefault() = delete; - NoDefault(const NoDefault&) {} - NoDefault& operator=(const NoDefault&) { return *this; } -}; - -struct ConvertsFromInPlaceT { - ConvertsFromInPlaceT(absl::in_place_t) {} // NOLINT -}; - -TEST(optionalTest, DefaultConstructor) { - absl::optional<int> empty; - EXPECT_FALSE(empty); - constexpr absl::optional<int> cempty; - static_assert(!cempty.has_value(), ""); - EXPECT_TRUE( - std::is_nothrow_default_constructible<absl::optional<int>>::value); -} - -TEST(optionalTest, nulloptConstructor) { - absl::optional<int> empty(absl::nullopt); - EXPECT_FALSE(empty); - constexpr absl::optional<int> cempty{absl::nullopt}; - static_assert(!cempty.has_value(), ""); - EXPECT_TRUE((std::is_nothrow_constructible<absl::optional<int>, - absl::nullopt_t>::value)); -} - -TEST(optionalTest, CopyConstructor) { - { - absl::optional<int> empty, opt42 = 42; - absl::optional<int> empty_copy(empty); - EXPECT_FALSE(empty_copy); - absl::optional<int> opt42_copy(opt42); - EXPECT_TRUE(opt42_copy); - EXPECT_EQ(42, *opt42_copy); - } - { - absl::optional<const int> empty, opt42 = 42; - absl::optional<const int> empty_copy(empty); - EXPECT_FALSE(empty_copy); - absl::optional<const int> opt42_copy(opt42); - EXPECT_TRUE(opt42_copy); - EXPECT_EQ(42, *opt42_copy); - } - { - absl::optional<volatile int> empty, opt42 = 42; - absl::optional<volatile int> empty_copy(empty); - EXPECT_FALSE(empty_copy); - absl::optional<volatile int> opt42_copy(opt42); - EXPECT_TRUE(opt42_copy); - EXPECT_EQ(42, *opt42_copy); - } - // test copyablility - EXPECT_TRUE(std::is_copy_constructible<absl::optional<int>>::value); - EXPECT_TRUE(std::is_copy_constructible<absl::optional<Copyable>>::value); - EXPECT_FALSE( - std::is_copy_constructible<absl::optional<MoveableThrow>>::value); - EXPECT_FALSE( - std::is_copy_constructible<absl::optional<MoveableNoThrow>>::value); - EXPECT_FALSE(std::is_copy_constructible<absl::optional<NonMovable>>::value); - - EXPECT_FALSE( - absl::is_trivially_copy_constructible<absl::optional<Copyable>>::value); -#if defined(ABSL_USES_STD_OPTIONAL) && defined(__GLIBCXX__) - // libstdc++ std::optional implementation (as of 7.2) has a bug: when T is - // trivially copyable, optional<T> is not trivially copyable (due to one of - // its base class is unconditionally nontrivial). -#define ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG 1 -#endif -#ifndef ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG - EXPECT_TRUE( - absl::is_trivially_copy_constructible<absl::optional<int>>::value); - EXPECT_TRUE( - absl::is_trivially_copy_constructible<absl::optional<const int>>::value); -#ifndef _MSC_VER - // See defect report "Trivial copy/move constructor for class with volatile - // member" at - // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2094 - // A class with non-static data member of volatile-qualified type should still - // have a trivial copy constructor if the data member is trivial. - // Also a cv-qualified scalar type should be trivially copyable. - EXPECT_TRUE(absl::is_trivially_copy_constructible< - absl::optional<volatile int>>::value); -#endif // _MSC_VER -#endif // ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG - - // constexpr copy constructor for trivially copyable types - { - constexpr absl::optional<int> o1; - constexpr absl::optional<int> o2 = o1; - static_assert(!o2, ""); - } - { - constexpr absl::optional<int> o1 = 42; - constexpr absl::optional<int> o2 = o1; - static_assert(o2, ""); - static_assert(*o2 == 42, ""); - } - { - struct TrivialCopyable { - constexpr TrivialCopyable() : x(0) {} - constexpr explicit TrivialCopyable(int i) : x(i) {} - int x; - }; - constexpr absl::optional<TrivialCopyable> o1(42); - constexpr absl::optional<TrivialCopyable> o2 = o1; - static_assert(o2, ""); - static_assert((*o2).x == 42, ""); -#ifndef ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG - EXPECT_TRUE(absl::is_trivially_copy_constructible< - absl::optional<TrivialCopyable>>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible< - absl::optional<const TrivialCopyable>>::value); -#endif - // When testing with VS 2017 15.3, there seems to be a bug in MSVC - // std::optional when T is volatile-qualified. So skipping this test. - // Bug report: - // https://connect.microsoft.com/VisualStudio/feedback/details/3142534 -#if defined(ABSL_USES_STD_OPTIONAL) && defined(_MSC_VER) && _MSC_VER >= 1911 -#define ABSL_MSVC_OPTIONAL_VOLATILE_COPY_BUG 1 -#endif -#ifndef ABSL_MSVC_OPTIONAL_VOLATILE_COPY_BUG - EXPECT_FALSE(std::is_copy_constructible< - absl::optional<volatile TrivialCopyable>>::value); -#endif - } -} - -TEST(optionalTest, MoveConstructor) { - absl::optional<int> empty, opt42 = 42; - absl::optional<int> empty_move(std::move(empty)); - EXPECT_FALSE(empty_move); - absl::optional<int> opt42_move(std::move(opt42)); - EXPECT_TRUE(opt42_move); - EXPECT_EQ(42, opt42_move); - // test movability - EXPECT_TRUE(std::is_move_constructible<absl::optional<int>>::value); - EXPECT_TRUE(std::is_move_constructible<absl::optional<Copyable>>::value); - EXPECT_TRUE(std::is_move_constructible<absl::optional<MoveableThrow>>::value); - EXPECT_TRUE( - std::is_move_constructible<absl::optional<MoveableNoThrow>>::value); - EXPECT_FALSE(std::is_move_constructible<absl::optional<NonMovable>>::value); - // test noexcept - EXPECT_TRUE(std::is_nothrow_move_constructible<absl::optional<int>>::value); -#ifndef ABSL_USES_STD_OPTIONAL - EXPECT_EQ( - absl::default_allocator_is_nothrow::value, - std::is_nothrow_move_constructible<absl::optional<MoveableThrow>>::value); -#endif - EXPECT_TRUE(std::is_nothrow_move_constructible< - absl::optional<MoveableNoThrow>>::value); -} - -TEST(optionalTest, Destructor) { - struct Trivial {}; - - struct NonTrivial { - NonTrivial(const NonTrivial&) {} - NonTrivial& operator=(const NonTrivial&) { return *this; } - ~NonTrivial() {} - }; - - EXPECT_TRUE(std::is_trivially_destructible<absl::optional<int>>::value); - EXPECT_TRUE(std::is_trivially_destructible<absl::optional<Trivial>>::value); - EXPECT_FALSE( - std::is_trivially_destructible<absl::optional<NonTrivial>>::value); -} - -TEST(optionalTest, InPlaceConstructor) { - constexpr absl::optional<ConstexprType> opt0{absl::in_place_t()}; - static_assert(opt0, ""); - static_assert((*opt0).x == ConstexprType::kCtorDefault, ""); - constexpr absl::optional<ConstexprType> opt1{absl::in_place_t(), 1}; - static_assert(opt1, ""); - static_assert((*opt1).x == ConstexprType::kCtorInt, ""); -#ifndef ABSL_HAVE_NO_CONSTEXPR_INITIALIZER_LIST - constexpr absl::optional<ConstexprType> opt2{absl::in_place_t(), {1, 2}}; - static_assert(opt2, ""); - static_assert((*opt2).x == ConstexprType::kCtorInitializerList, ""); -#endif - - EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>, - absl::in_place_t>::value)); - EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>, - const absl::in_place_t&>::value)); - EXPECT_TRUE( - (std::is_constructible<absl::optional<ConvertsFromInPlaceT>, - absl::in_place_t, absl::in_place_t>::value)); - - EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>, - absl::in_place_t>::value)); - EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>, - absl::in_place_t&&>::value)); -} - -// template<U=T> optional(U&&); -TEST(optionalTest, ValueConstructor) { - constexpr absl::optional<int> opt0(0); - static_assert(opt0, ""); - static_assert(*opt0 == 0, ""); - EXPECT_TRUE((std::is_convertible<int, absl::optional<int>>::value)); - // Copy initialization ( = "abc") won't work due to optional(optional&&) - // is not constexpr. Use list initialization instead. This invokes - // absl::optional<ConstexprType>::absl::optional<U>(U&&), with U = const char - // (&) [4], which direct-initializes the ConstexprType value held by the - // optional via ConstexprType::ConstexprType(const char*). - constexpr absl::optional<ConstexprType> opt1 = {"abc"}; - static_assert(opt1, ""); - static_assert(ConstexprType::kCtorConstChar == (*opt1).x, ""); - EXPECT_TRUE( - (std::is_convertible<const char*, absl::optional<ConstexprType>>::value)); - // direct initialization - constexpr absl::optional<ConstexprType> opt2{2}; - static_assert(opt2, ""); - static_assert(ConstexprType::kCtorInt == (*opt2).x, ""); - EXPECT_FALSE( - (std::is_convertible<int, absl::optional<ConstexprType>>::value)); - - // this invokes absl::optional<int>::optional(int&&) - // NOTE: this has different behavior than assignment, e.g. - // "opt3 = {};" clears the optional rather than setting the value to 0 - // According to C++17 standard N4659 [over.ics.list] 16.3.3.1.5, (9.2)- "if - // the initializer list has no elements, the implicit conversion is the - // identity conversion", so `optional(int&&)` should be a better match than - // `optional(optional&&)` which is a user-defined conversion. - // Note: GCC 7 has a bug with this overload selection when compiled with - // `-std=c++17`. -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 7 && \ - __cplusplus == 201703L -#define ABSL_GCC7_OVER_ICS_LIST_BUG 1 -#endif -#ifndef ABSL_GCC7_OVER_ICS_LIST_BUG - constexpr absl::optional<int> opt3({}); - static_assert(opt3, ""); - static_assert(*opt3 == 0, ""); -#endif - - // this invokes the move constructor with a default constructed optional - // because non-template function is a better match than template function. - absl::optional<ConstexprType> opt4({}); - EXPECT_FALSE(opt4); -} - -struct Implicit {}; - -struct Explicit {}; - -struct Convert { - Convert(const Implicit&) // NOLINT(runtime/explicit) - : implicit(true), move(false) {} - Convert(Implicit&&) // NOLINT(runtime/explicit) - : implicit(true), move(true) {} - explicit Convert(const Explicit&) : implicit(false), move(false) {} - explicit Convert(Explicit&&) : implicit(false), move(true) {} - - bool implicit; - bool move; -}; - -struct ConvertFromOptional { - ConvertFromOptional(const Implicit&) // NOLINT(runtime/explicit) - : implicit(true), move(false), from_optional(false) {} - ConvertFromOptional(Implicit&&) // NOLINT(runtime/explicit) - : implicit(true), move(true), from_optional(false) {} - ConvertFromOptional( - const absl::optional<Implicit>&) // NOLINT(runtime/explicit) - : implicit(true), move(false), from_optional(true) {} - ConvertFromOptional(absl::optional<Implicit>&&) // NOLINT(runtime/explicit) - : implicit(true), move(true), from_optional(true) {} - explicit ConvertFromOptional(const Explicit&) - : implicit(false), move(false), from_optional(false) {} - explicit ConvertFromOptional(Explicit&&) - : implicit(false), move(true), from_optional(false) {} - explicit ConvertFromOptional(const absl::optional<Explicit>&) - : implicit(false), move(false), from_optional(true) {} - explicit ConvertFromOptional(absl::optional<Explicit>&&) - : implicit(false), move(true), from_optional(true) {} - - bool implicit; - bool move; - bool from_optional; -}; - -TEST(optionalTest, ConvertingConstructor) { - absl::optional<Implicit> i_empty; - absl::optional<Implicit> i(absl::in_place); - absl::optional<Explicit> e_empty; - absl::optional<Explicit> e(absl::in_place); - { - // implicitly constructing absl::optional<Convert> from - // absl::optional<Implicit> - absl::optional<Convert> empty = i_empty; - EXPECT_FALSE(empty); - absl::optional<Convert> opt_copy = i; - EXPECT_TRUE(opt_copy); - EXPECT_TRUE(opt_copy->implicit); - EXPECT_FALSE(opt_copy->move); - absl::optional<Convert> opt_move = absl::optional<Implicit>(absl::in_place); - EXPECT_TRUE(opt_move); - EXPECT_TRUE(opt_move->implicit); - EXPECT_TRUE(opt_move->move); - } - { - // explicitly constructing absl::optional<Convert> from - // absl::optional<Explicit> - absl::optional<Convert> empty(e_empty); - EXPECT_FALSE(empty); - absl::optional<Convert> opt_copy(e); - EXPECT_TRUE(opt_copy); - EXPECT_FALSE(opt_copy->implicit); - EXPECT_FALSE(opt_copy->move); - EXPECT_FALSE((std::is_convertible<const absl::optional<Explicit>&, - absl::optional<Convert>>::value)); - absl::optional<Convert> opt_move{absl::optional<Explicit>(absl::in_place)}; - EXPECT_TRUE(opt_move); - EXPECT_FALSE(opt_move->implicit); - EXPECT_TRUE(opt_move->move); - EXPECT_FALSE((std::is_convertible<absl::optional<Explicit>&&, - absl::optional<Convert>>::value)); - } - { - // implicitly constructing absl::optional<ConvertFromOptional> from - // absl::optional<Implicit> via - // ConvertFromOptional(absl::optional<Implicit>&&) check that - // ConvertFromOptional(Implicit&&) is NOT called - static_assert( - std::is_convertible<absl::optional<Implicit>, - absl::optional<ConvertFromOptional>>::value, - ""); - absl::optional<ConvertFromOptional> opt0 = i_empty; - EXPECT_TRUE(opt0); - EXPECT_TRUE(opt0->implicit); - EXPECT_FALSE(opt0->move); - EXPECT_TRUE(opt0->from_optional); - absl::optional<ConvertFromOptional> opt1 = absl::optional<Implicit>(); - EXPECT_TRUE(opt1); - EXPECT_TRUE(opt1->implicit); - EXPECT_TRUE(opt1->move); - EXPECT_TRUE(opt1->from_optional); - } - { - // implicitly constructing absl::optional<ConvertFromOptional> from - // absl::optional<Explicit> via - // ConvertFromOptional(absl::optional<Explicit>&&) check that - // ConvertFromOptional(Explicit&&) is NOT called - absl::optional<ConvertFromOptional> opt0(e_empty); - EXPECT_TRUE(opt0); - EXPECT_FALSE(opt0->implicit); - EXPECT_FALSE(opt0->move); - EXPECT_TRUE(opt0->from_optional); - EXPECT_FALSE( - (std::is_convertible<const absl::optional<Explicit>&, - absl::optional<ConvertFromOptional>>::value)); - absl::optional<ConvertFromOptional> opt1{absl::optional<Explicit>()}; - EXPECT_TRUE(opt1); - EXPECT_FALSE(opt1->implicit); - EXPECT_TRUE(opt1->move); - EXPECT_TRUE(opt1->from_optional); - EXPECT_FALSE( - (std::is_convertible<absl::optional<Explicit>&&, - absl::optional<ConvertFromOptional>>::value)); - } -} - -TEST(optionalTest, StructorBasic) { - StructorListener listener; - Listenable::listener = &listener; - { - absl::optional<Listenable> empty; - EXPECT_FALSE(empty); - absl::optional<Listenable> opt0(absl::in_place); - EXPECT_TRUE(opt0); - absl::optional<Listenable> opt1(absl::in_place, 1); - EXPECT_TRUE(opt1); - absl::optional<Listenable> opt2(absl::in_place, 1, 2); - EXPECT_TRUE(opt2); - } - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.construct1); - EXPECT_EQ(1, listener.construct2); - EXPECT_EQ(3, listener.destruct); -} - -TEST(optionalTest, CopyMoveStructor) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> original(absl::in_place); - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(0, listener.copy); - EXPECT_EQ(0, listener.move); - absl::optional<Listenable> copy(original); - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.copy); - EXPECT_EQ(0, listener.move); - absl::optional<Listenable> move(std::move(original)); - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.copy); - EXPECT_EQ(1, listener.move); -} - -TEST(optionalTest, ListInit) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> listinit1(absl::in_place, {1}); - absl::optional<Listenable> listinit2(absl::in_place, {1, 2}); - EXPECT_EQ(2, listener.listinit); -} - -TEST(optionalTest, AssignFromNullopt) { - absl::optional<int> opt(1); - opt = absl::nullopt; - EXPECT_FALSE(opt); - - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> opt1(absl::in_place); - opt1 = absl::nullopt; - EXPECT_FALSE(opt1); - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.destruct); - - EXPECT_TRUE(( - std::is_nothrow_assignable<absl::optional<int>, absl::nullopt_t>::value)); - EXPECT_TRUE((std::is_nothrow_assignable<absl::optional<Listenable>, - absl::nullopt_t>::value)); -} - -TEST(optionalTest, CopyAssignment) { - const absl::optional<int> empty, opt1 = 1, opt2 = 2; - absl::optional<int> empty_to_opt1, opt1_to_opt2, opt2_to_empty; - - EXPECT_FALSE(empty_to_opt1); - empty_to_opt1 = empty; - EXPECT_FALSE(empty_to_opt1); - empty_to_opt1 = opt1; - EXPECT_TRUE(empty_to_opt1); - EXPECT_EQ(1, empty_to_opt1.value()); - - EXPECT_FALSE(opt1_to_opt2); - opt1_to_opt2 = opt1; - EXPECT_TRUE(opt1_to_opt2); - EXPECT_EQ(1, opt1_to_opt2.value()); - opt1_to_opt2 = opt2; - EXPECT_TRUE(opt1_to_opt2); - EXPECT_EQ(2, opt1_to_opt2.value()); - - EXPECT_FALSE(opt2_to_empty); - opt2_to_empty = opt2; - EXPECT_TRUE(opt2_to_empty); - EXPECT_EQ(2, opt2_to_empty.value()); - opt2_to_empty = empty; - EXPECT_FALSE(opt2_to_empty); - - 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); - - struct Trivial { - int i; - }; - struct NonTrivial { - NonTrivial& operator=(const NonTrivial&) { return *this; } - int i; - }; - - EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial>::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. -#ifndef ABSL_USES_STD_OPTIONAL - { - StructorListener listener; - Listenable::listener = &listener; - - absl::optional<volatile Listenable> empty, set(absl::in_place); - EXPECT_EQ(1, listener.construct0); - absl::optional<volatile Listenable> empty_to_empty, empty_to_set, - set_to_empty(absl::in_place), set_to_set(absl::in_place); - EXPECT_EQ(3, listener.construct0); - empty_to_empty = empty; // no effect - empty_to_set = set; // copy construct - set_to_empty = empty; // destruct - set_to_set = set; // copy assign - EXPECT_EQ(1, listener.volatile_copy); - EXPECT_EQ(0, listener.volatile_move); - EXPECT_EQ(1, listener.destruct); - EXPECT_EQ(1, listener.volatile_copy_assign); - } -#endif // ABSL_USES_STD_OPTIONAL -} - -TEST(optionalTest, MoveAssignment) { - { - StructorListener listener; - Listenable::listener = &listener; - - absl::optional<Listenable> empty1, empty2, set1(absl::in_place), - set2(absl::in_place); - EXPECT_EQ(2, listener.construct0); - absl::optional<Listenable> empty_to_empty, empty_to_set, - set_to_empty(absl::in_place), set_to_set(absl::in_place); - EXPECT_EQ(4, listener.construct0); - empty_to_empty = std::move(empty1); - empty_to_set = std::move(set1); - set_to_empty = std::move(empty2); - set_to_set = std::move(set2); - EXPECT_EQ(0, listener.copy); - EXPECT_EQ(1, listener.move); - EXPECT_EQ(1, listener.destruct); - EXPECT_EQ(1, listener.move_assign); - } - // std::optional doesn't support volatile nontrivial types. -#ifndef ABSL_USES_STD_OPTIONAL - { - StructorListener listener; - Listenable::listener = &listener; - - absl::optional<volatile Listenable> empty1, empty2, set1(absl::in_place), - set2(absl::in_place); - EXPECT_EQ(2, listener.construct0); - absl::optional<volatile Listenable> empty_to_empty, empty_to_set, - set_to_empty(absl::in_place), set_to_set(absl::in_place); - EXPECT_EQ(4, listener.construct0); - empty_to_empty = std::move(empty1); // no effect - empty_to_set = std::move(set1); // move construct - set_to_empty = std::move(empty2); // destruct - set_to_set = std::move(set2); // move assign - EXPECT_EQ(0, listener.volatile_copy); - EXPECT_EQ(1, listener.volatile_move); - EXPECT_EQ(1, listener.destruct); - EXPECT_EQ(1, listener.volatile_move_assign); - } -#endif // ABSL_USES_STD_OPTIONAL - 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); - EXPECT_TRUE( - std::is_nothrow_move_assignable<absl::optional<MoveableNoThrow>>::value); -} - -struct NoConvertToOptional { - // disable implicit conversion from const NoConvertToOptional& - // to absl::optional<NoConvertToOptional>. - NoConvertToOptional(const NoConvertToOptional&) = delete; -}; - -struct CopyConvert { - CopyConvert(const NoConvertToOptional&); - CopyConvert& operator=(const CopyConvert&) = delete; - CopyConvert& operator=(const NoConvertToOptional&); -}; - -struct CopyConvertFromOptional { - CopyConvertFromOptional(const NoConvertToOptional&); - CopyConvertFromOptional(const absl::optional<NoConvertToOptional>&); - CopyConvertFromOptional& operator=(const CopyConvertFromOptional&) = delete; - CopyConvertFromOptional& operator=(const NoConvertToOptional&); - CopyConvertFromOptional& operator=( - const absl::optional<NoConvertToOptional>&); -}; - -struct MoveConvert { - MoveConvert(NoConvertToOptional&&); - MoveConvert& operator=(const MoveConvert&) = delete; - MoveConvert& operator=(NoConvertToOptional&&); -}; - -struct MoveConvertFromOptional { - MoveConvertFromOptional(NoConvertToOptional&&); - MoveConvertFromOptional(absl::optional<NoConvertToOptional>&&); - MoveConvertFromOptional& operator=(const MoveConvertFromOptional&) = delete; - MoveConvertFromOptional& operator=(NoConvertToOptional&&); - MoveConvertFromOptional& operator=(absl::optional<NoConvertToOptional>&&); -}; - -// template <typename U = T> absl::optional<T>& operator=(U&& v); -TEST(optionalTest, ValueAssignment) { - absl::optional<int> opt; - EXPECT_FALSE(opt); - opt = 42; - EXPECT_TRUE(opt); - EXPECT_EQ(42, opt.value()); - opt = absl::nullopt; - EXPECT_FALSE(opt); - opt = 42; - EXPECT_TRUE(opt); - EXPECT_EQ(42, opt.value()); - opt = 43; - EXPECT_TRUE(opt); - EXPECT_EQ(43, opt.value()); - opt = {}; // this should clear optional - EXPECT_FALSE(opt); - - opt = {44}; - EXPECT_TRUE(opt); - EXPECT_EQ(44, opt.value()); - - // U = const NoConvertToOptional& - EXPECT_TRUE((std::is_assignable<absl::optional<CopyConvert>&, - const NoConvertToOptional&>::value)); - // U = const absl::optional<NoConvertToOptional>& - EXPECT_TRUE((std::is_assignable<absl::optional<CopyConvertFromOptional>&, - const NoConvertToOptional&>::value)); - // U = const NoConvertToOptional& triggers SFINAE because - // std::is_constructible_v<MoveConvert, const NoConvertToOptional&> is false - EXPECT_FALSE((std::is_assignable<absl::optional<MoveConvert>&, - const NoConvertToOptional&>::value)); - // U = NoConvertToOptional - EXPECT_TRUE((std::is_assignable<absl::optional<MoveConvert>&, - NoConvertToOptional&&>::value)); - // U = const NoConvertToOptional& triggers SFINAE because - // std::is_constructible_v<MoveConvertFromOptional, const - // NoConvertToOptional&> is false - EXPECT_FALSE((std::is_assignable<absl::optional<MoveConvertFromOptional>&, - const NoConvertToOptional&>::value)); - // U = NoConvertToOptional - EXPECT_TRUE((std::is_assignable<absl::optional<MoveConvertFromOptional>&, - NoConvertToOptional&&>::value)); - // U = const absl::optional<NoConvertToOptional>& - EXPECT_TRUE( - (std::is_assignable<absl::optional<CopyConvertFromOptional>&, - const absl::optional<NoConvertToOptional>&>::value)); - // U = absl::optional<NoConvertToOptional> - EXPECT_TRUE( - (std::is_assignable<absl::optional<MoveConvertFromOptional>&, - absl::optional<NoConvertToOptional>&&>::value)); -} - -// template <typename U> absl::optional<T>& operator=(const absl::optional<U>& -// rhs); template <typename U> absl::optional<T>& operator=(absl::optional<U>&& -// rhs); -TEST(optionalTest, ConvertingAssignment) { - absl::optional<int> opt_i; - absl::optional<char> opt_c('c'); - opt_i = opt_c; - EXPECT_TRUE(opt_i); - EXPECT_EQ(*opt_c, *opt_i); - opt_i = absl::optional<char>(); - EXPECT_FALSE(opt_i); - opt_i = absl::optional<char>('d'); - EXPECT_TRUE(opt_i); - EXPECT_EQ('d', *opt_i); - - absl::optional<std::string> opt_str; - absl::optional<const char*> opt_cstr("abc"); - opt_str = opt_cstr; - EXPECT_TRUE(opt_str); - EXPECT_EQ(std::string("abc"), *opt_str); - opt_str = absl::optional<const char*>(); - EXPECT_FALSE(opt_str); - opt_str = absl::optional<const char*>("def"); - EXPECT_TRUE(opt_str); - EXPECT_EQ(std::string("def"), *opt_str); - - // operator=(const absl::optional<U>&) with U = NoConvertToOptional - EXPECT_TRUE( - (std::is_assignable<absl::optional<CopyConvert>, - const absl::optional<NoConvertToOptional>&>::value)); - // operator=(const absl::optional<U>&) with U = NoConvertToOptional - // triggers SFINAE because - // std::is_constructible_v<MoveConvert, const NoConvertToOptional&> is false - EXPECT_FALSE( - (std::is_assignable<absl::optional<MoveConvert>&, - const absl::optional<NoConvertToOptional>&>::value)); - // operator=(absl::optional<U>&&) with U = NoConvertToOptional - EXPECT_TRUE( - (std::is_assignable<absl::optional<MoveConvert>&, - absl::optional<NoConvertToOptional>&&>::value)); - // operator=(const absl::optional<U>&) with U = NoConvertToOptional triggers - // SFINAE because std::is_constructible_v<MoveConvertFromOptional, const - // NoConvertToOptional&> is false. operator=(U&&) with U = const - // absl::optional<NoConverToOptional>& triggers SFINAE because - // std::is_constructible<MoveConvertFromOptional, - // absl::optional<NoConvertToOptional>&&> is true. - EXPECT_FALSE( - (std::is_assignable<absl::optional<MoveConvertFromOptional>&, - const absl::optional<NoConvertToOptional>&>::value)); -} - -TEST(optionalTest, ResetAndHasValue) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> opt; - EXPECT_FALSE(opt); - EXPECT_FALSE(opt.has_value()); - opt.emplace(); - EXPECT_TRUE(opt); - EXPECT_TRUE(opt.has_value()); - opt.reset(); - EXPECT_FALSE(opt); - EXPECT_FALSE(opt.has_value()); - EXPECT_EQ(1, listener.destruct); - opt.reset(); - EXPECT_FALSE(opt); - EXPECT_FALSE(opt.has_value()); - - constexpr absl::optional<int> empty; - static_assert(!empty.has_value(), ""); - constexpr absl::optional<int> nonempty(1); - static_assert(nonempty.has_value(), ""); -} - -TEST(optionalTest, Emplace) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> opt; - EXPECT_FALSE(opt); - opt.emplace(1); - EXPECT_TRUE(opt); - opt.emplace(1, 2); - EXPECT_EQ(1, listener.construct1); - EXPECT_EQ(1, listener.construct2); - EXPECT_EQ(1, listener.destruct); - - absl::optional<std::string> o; - EXPECT_TRUE((std::is_same<std::string&, decltype(o.emplace("abc"))>::value)); - std::string& ref = o.emplace("abc"); - EXPECT_EQ(&ref, &o.value()); -} - -TEST(optionalTest, ListEmplace) { - StructorListener listener; - Listenable::listener = &listener; - absl::optional<Listenable> opt; - EXPECT_FALSE(opt); - opt.emplace({1}); - EXPECT_TRUE(opt); - opt.emplace({1, 2}); - EXPECT_EQ(2, listener.listinit); - EXPECT_EQ(1, listener.destruct); - - absl::optional<Listenable> o; - EXPECT_TRUE((std::is_same<Listenable&, decltype(o.emplace({1}))>::value)); - Listenable& ref = o.emplace({1}); - EXPECT_EQ(&ref, &o.value()); -} - -TEST(optionalTest, Swap) { - absl::optional<int> opt_empty, opt1 = 1, opt2 = 2; - EXPECT_FALSE(opt_empty); - EXPECT_TRUE(opt1); - EXPECT_EQ(1, opt1.value()); - EXPECT_TRUE(opt2); - EXPECT_EQ(2, opt2.value()); - swap(opt_empty, opt1); - EXPECT_FALSE(opt1); - EXPECT_TRUE(opt_empty); - EXPECT_EQ(1, opt_empty.value()); - EXPECT_TRUE(opt2); - EXPECT_EQ(2, opt2.value()); - swap(opt_empty, opt1); - EXPECT_FALSE(opt_empty); - EXPECT_TRUE(opt1); - EXPECT_EQ(1, opt1.value()); - EXPECT_TRUE(opt2); - EXPECT_EQ(2, opt2.value()); - swap(opt1, opt2); - EXPECT_FALSE(opt_empty); - EXPECT_TRUE(opt1); - EXPECT_EQ(2, opt1.value()); - EXPECT_TRUE(opt2); - EXPECT_EQ(1, opt2.value()); - - EXPECT_TRUE(noexcept(opt1.swap(opt2))); - EXPECT_TRUE(noexcept(swap(opt1, opt2))); -} - -template <int v> -struct DeletedOpAddr { - int value = v; - constexpr DeletedOpAddr() = default; - constexpr const DeletedOpAddr<v>* operator&() const = delete; // NOLINT - DeletedOpAddr<v>* operator&() = delete; // NOLINT -}; - -// The static_assert featuring a constexpr call to operator->() is commented out -// to document the fact that the current implementation of absl::optional<T> -// expects such usecases to be malformed and not compile. -TEST(optionalTest, OperatorAddr) { - constexpr int v = -1; - { // constexpr - constexpr absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{}); - static_assert(opt.has_value(), ""); - // static_assert(opt->value == v, ""); - static_assert((*opt).value == v, ""); - } - { // non-constexpr - const absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{}); - EXPECT_TRUE(opt.has_value()); - EXPECT_TRUE(opt->value == v); - EXPECT_TRUE((*opt).value == v); - } -} - -TEST(optionalTest, PointerStuff) { - absl::optional<std::string> opt(absl::in_place, "foo"); - EXPECT_EQ("foo", *opt); - const auto& opt_const = opt; - EXPECT_EQ("foo", *opt_const); - EXPECT_EQ(opt->size(), 3); - EXPECT_EQ(opt_const->size(), 3); - - constexpr absl::optional<ConstexprType> opt1(1); - static_assert((*opt1).x == ConstexprType::kCtorInt, ""); -} - -// gcc has a bug pre 4.9.1 where it doesn't do correct overload resolution -// when overloads are const-qualified and *this is an raluve. -// Skip that test to make the build green again when using the old compiler. -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59296 is fixed in 4.9.1. -#if defined(__GNUC__) && !defined(__clang__) -#define GCC_VERSION (__GNUC__ * 10000 \ - + __GNUC_MINOR__ * 100 \ - + __GNUC_PATCHLEVEL__) -#if GCC_VERSION < 40901 -#define ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG -#endif -#endif - -// MSVC has a bug with "cv-qualifiers in class construction", fixed in 2017. See -// https://docs.microsoft.com/en-us/cpp/cpp-conformance-improvements-2017#bug-fixes -// The compiler some incorrectly ingores the cv-qualifier when generating a -// class object via a constructor call. For example: -// -// class optional { -// constexpr T&& value() &&; -// constexpr const T&& value() const &&; -// } -// -// using COI = const absl::optional<int>; -// static_assert(2 == COI(2).value(), ""); // const && -// -// This should invoke the "const &&" overload but since it ignores the const -// qualifier it finds the "&&" overload the best candidate. -#if defined(_MSC_VER) && _MSC_VER < 1910 -#define ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG -#endif - -TEST(optionalTest, Value) { - using O = absl::optional<std::string>; - using CO = const absl::optional<std::string>; - using OC = absl::optional<const std::string>; - O lvalue(absl::in_place, "lvalue"); - CO clvalue(absl::in_place, "clvalue"); - OC lvalue_c(absl::in_place, "lvalue_c"); - EXPECT_EQ("lvalue", lvalue.value()); - EXPECT_EQ("clvalue", clvalue.value()); - EXPECT_EQ("lvalue_c", lvalue_c.value()); - EXPECT_EQ("xvalue", O(absl::in_place, "xvalue").value()); - EXPECT_EQ("xvalue_c", OC(absl::in_place, "xvalue_c").value()); -#ifndef ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG - EXPECT_EQ("cxvalue", CO(absl::in_place, "cxvalue").value()); -#endif - EXPECT_EQ("&", TypeQuals(lvalue.value())); - EXPECT_EQ("c&", TypeQuals(clvalue.value())); - EXPECT_EQ("c&", TypeQuals(lvalue_c.value())); - EXPECT_EQ("&&", TypeQuals(O(absl::in_place, "xvalue").value())); -#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \ - !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) - EXPECT_EQ("c&&", TypeQuals(CO(absl::in_place, "cxvalue").value())); -#endif - EXPECT_EQ("c&&", TypeQuals(OC(absl::in_place, "xvalue_c").value())); - - // test on volatile type - using OV = absl::optional<volatile int>; - OV lvalue_v(absl::in_place, 42); - EXPECT_EQ(42, lvalue_v.value()); - EXPECT_EQ(42, OV(42).value()); - EXPECT_TRUE((std::is_same<volatile int&, decltype(lvalue_v.value())>::value)); - EXPECT_TRUE((std::is_same<volatile int&&, decltype(OV(42).value())>::value)); - - // test exception throw on value() - absl::optional<int> empty; -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW((void)empty.value(), absl::bad_optional_access); -#else - EXPECT_DEATH_IF_SUPPORTED((void)empty.value(), "Bad optional access"); -#endif - - // test constexpr value() - constexpr absl::optional<int> o1(1); - static_assert(1 == o1.value(), ""); // const & -#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) - using COI = const absl::optional<int>; - static_assert(2 == COI(2).value(), ""); // const && -#endif -} - -TEST(optionalTest, DerefOperator) { - using O = absl::optional<std::string>; - using CO = const absl::optional<std::string>; - using OC = absl::optional<const std::string>; - O lvalue(absl::in_place, "lvalue"); - CO clvalue(absl::in_place, "clvalue"); - OC lvalue_c(absl::in_place, "lvalue_c"); - EXPECT_EQ("lvalue", *lvalue); - EXPECT_EQ("clvalue", *clvalue); - EXPECT_EQ("lvalue_c", *lvalue_c); - EXPECT_EQ("xvalue", *O(absl::in_place, "xvalue")); - EXPECT_EQ("xvalue_c", *OC(absl::in_place, "xvalue_c")); -#ifndef ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG - EXPECT_EQ("cxvalue", *CO(absl::in_place, "cxvalue")); -#endif - EXPECT_EQ("&", TypeQuals(*lvalue)); - EXPECT_EQ("c&", TypeQuals(*clvalue)); - EXPECT_EQ("&&", TypeQuals(*O(absl::in_place, "xvalue"))); -#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \ - !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) - EXPECT_EQ("c&&", TypeQuals(*CO(absl::in_place, "cxvalue"))); -#endif - EXPECT_EQ("c&&", TypeQuals(*OC(absl::in_place, "xvalue_c"))); - - // test on volatile type - using OV = absl::optional<volatile int>; - OV lvalue_v(absl::in_place, 42); - EXPECT_EQ(42, *lvalue_v); - EXPECT_EQ(42, *OV(42)); - EXPECT_TRUE((std::is_same<volatile int&, decltype(*lvalue_v)>::value)); - EXPECT_TRUE((std::is_same<volatile int&&, decltype(*OV(42))>::value)); - - constexpr absl::optional<int> opt1(1); - static_assert(*opt1 == 1, ""); -#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) - using COI = const absl::optional<int>; - static_assert(*COI(2) == 2, ""); -#endif -} - -TEST(optionalTest, ValueOr) { - absl::optional<double> opt_empty, opt_set = 1.2; - EXPECT_EQ(42.0, opt_empty.value_or(42)); - EXPECT_EQ(1.2, opt_set.value_or(42)); - EXPECT_EQ(42.0, absl::optional<double>().value_or(42)); - EXPECT_EQ(1.2, absl::optional<double>(1.2).value_or(42)); - - constexpr absl::optional<double> copt_empty, copt_set = {1.2}; - static_assert(42.0 == copt_empty.value_or(42), ""); - static_assert(1.2 == copt_set.value_or(42), ""); -#ifndef ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG - using COD = const absl::optional<double>; - static_assert(42.0 == COD().value_or(42), ""); - static_assert(1.2 == COD(1.2).value_or(42), ""); -#endif -} - -// make_optional cannot be constexpr until C++17 -TEST(optionalTest, make_optional) { - auto opt_int = absl::make_optional(42); - EXPECT_TRUE((std::is_same<decltype(opt_int), absl::optional<int>>::value)); - EXPECT_EQ(42, opt_int); - - StructorListener listener; - Listenable::listener = &listener; - - absl::optional<Listenable> opt0 = absl::make_optional<Listenable>(); - EXPECT_EQ(1, listener.construct0); - absl::optional<Listenable> opt1 = absl::make_optional<Listenable>(1); - EXPECT_EQ(1, listener.construct1); - absl::optional<Listenable> opt2 = absl::make_optional<Listenable>(1, 2); - EXPECT_EQ(1, listener.construct2); - absl::optional<Listenable> opt3 = absl::make_optional<Listenable>({1}); - absl::optional<Listenable> opt4 = absl::make_optional<Listenable>({1, 2}); - EXPECT_EQ(2, listener.listinit); - - // Constexpr tests on trivially copyable types - // optional<T> has trivial copy/move ctors when T is trivially copyable. - // For nontrivial types with constexpr constructors, we need copy elision in - // C++17 for make_optional to be constexpr. - { - constexpr absl::optional<int> c_opt = absl::make_optional(42); - static_assert(c_opt.value() == 42, ""); - } - { - struct TrivialCopyable { - constexpr TrivialCopyable() : x(0) {} - constexpr explicit TrivialCopyable(int i) : x(i) {} - int x; - }; - - constexpr TrivialCopyable v; - constexpr absl::optional<TrivialCopyable> c_opt0 = absl::make_optional(v); - static_assert((*c_opt0).x == 0, ""); - constexpr absl::optional<TrivialCopyable> c_opt1 = - absl::make_optional<TrivialCopyable>(); - static_assert((*c_opt1).x == 0, ""); - constexpr absl::optional<TrivialCopyable> c_opt2 = - absl::make_optional<TrivialCopyable>(42); - static_assert((*c_opt2).x == 42, ""); - } -} - -template <typename T, typename U> -void optionalTest_Comparisons_EXPECT_LESS(T x, U y) { - EXPECT_FALSE(x == y); - EXPECT_TRUE(x != y); - EXPECT_TRUE(x < y); - EXPECT_FALSE(x > y); - EXPECT_TRUE(x <= y); - EXPECT_FALSE(x >= y); -} - -template <typename T, typename U> -void optionalTest_Comparisons_EXPECT_SAME(T x, U y) { - EXPECT_TRUE(x == y); - EXPECT_FALSE(x != y); - EXPECT_FALSE(x < y); - EXPECT_FALSE(x > y); - EXPECT_TRUE(x <= y); - EXPECT_TRUE(x >= y); -} - -template <typename T, typename U> -void optionalTest_Comparisons_EXPECT_GREATER(T x, U y) { - EXPECT_FALSE(x == y); - EXPECT_TRUE(x != y); - EXPECT_FALSE(x < y); - EXPECT_TRUE(x > y); - EXPECT_FALSE(x <= y); - EXPECT_TRUE(x >= y); -} - - -template <typename T, typename U, typename V> -void TestComparisons() { - absl::optional<T> ae, a2{2}, a4{4}; - absl::optional<U> be, b2{2}, b4{4}; - V v3 = 3; - - // LHS: absl::nullopt, ae, a2, v3, a4 - // RHS: absl::nullopt, be, b2, v3, b4 - - // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(absl::nullopt,absl::nullopt); - optionalTest_Comparisons_EXPECT_SAME(absl::nullopt, be); - optionalTest_Comparisons_EXPECT_LESS(absl::nullopt, b2); - // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(absl::nullopt,v3); - optionalTest_Comparisons_EXPECT_LESS(absl::nullopt, b4); - - optionalTest_Comparisons_EXPECT_SAME(ae, absl::nullopt); - optionalTest_Comparisons_EXPECT_SAME(ae, be); - optionalTest_Comparisons_EXPECT_LESS(ae, b2); - optionalTest_Comparisons_EXPECT_LESS(ae, v3); - optionalTest_Comparisons_EXPECT_LESS(ae, b4); - - optionalTest_Comparisons_EXPECT_GREATER(a2, absl::nullopt); - optionalTest_Comparisons_EXPECT_GREATER(a2, be); - optionalTest_Comparisons_EXPECT_SAME(a2, b2); - optionalTest_Comparisons_EXPECT_LESS(a2, v3); - optionalTest_Comparisons_EXPECT_LESS(a2, b4); - - // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(v3,absl::nullopt); - optionalTest_Comparisons_EXPECT_GREATER(v3, be); - optionalTest_Comparisons_EXPECT_GREATER(v3, b2); - optionalTest_Comparisons_EXPECT_SAME(v3, v3); - optionalTest_Comparisons_EXPECT_LESS(v3, b4); - - optionalTest_Comparisons_EXPECT_GREATER(a4, absl::nullopt); - optionalTest_Comparisons_EXPECT_GREATER(a4, be); - optionalTest_Comparisons_EXPECT_GREATER(a4, b2); - optionalTest_Comparisons_EXPECT_GREATER(a4, v3); - optionalTest_Comparisons_EXPECT_SAME(a4, b4); -} - -struct Int1 { - Int1() = default; - Int1(int i) : i(i) {} // NOLINT(runtime/explicit) - int i; -}; - -struct Int2 { - Int2() = default; - Int2(int i) : i(i) {} // NOLINT(runtime/explicit) - int i; -}; - -// comparison between Int1 and Int2 -constexpr bool operator==(const Int1& lhs, const Int2& rhs) { - return lhs.i == rhs.i; -} -constexpr bool operator!=(const Int1& lhs, const Int2& rhs) { - return !(lhs == rhs); -} -constexpr bool operator<(const Int1& lhs, const Int2& rhs) { - return lhs.i < rhs.i; -} -constexpr bool operator<=(const Int1& lhs, const Int2& rhs) { - return lhs < rhs || lhs == rhs; -} -constexpr bool operator>(const Int1& lhs, const Int2& rhs) { - return !(lhs <= rhs); -} -constexpr bool operator>=(const Int1& lhs, const Int2& rhs) { - return !(lhs < rhs); -} - -TEST(optionalTest, Comparisons) { - TestComparisons<int, int, int>(); - TestComparisons<const int, int, int>(); - TestComparisons<Int1, int, int>(); - TestComparisons<int, Int2, int>(); - TestComparisons<Int1, Int2, int>(); - - // compare absl::optional<std::string> with const char* - absl::optional<std::string> opt_str = "abc"; - const char* cstr = "abc"; - EXPECT_TRUE(opt_str == cstr); - // compare absl::optional<std::string> with absl::optional<const char*> - absl::optional<const char*> opt_cstr = cstr; - EXPECT_TRUE(opt_str == opt_cstr); - // compare absl::optional<std::string> with absl::optional<absl::string_view> - absl::optional<absl::string_view> e1; - absl::optional<std::string> e2; - EXPECT_TRUE(e1 == e2); -} - - -TEST(optionalTest, SwapRegression) { - StructorListener listener; - Listenable::listener = &listener; - - { - absl::optional<Listenable> a; - absl::optional<Listenable> b(absl::in_place); - a.swap(b); - } - - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.move); - EXPECT_EQ(2, listener.destruct); - - { - absl::optional<Listenable> a(absl::in_place); - absl::optional<Listenable> b; - a.swap(b); - } - - EXPECT_EQ(2, listener.construct0); - EXPECT_EQ(2, listener.move); - EXPECT_EQ(4, listener.destruct); -} - -TEST(optionalTest, BigStringLeakCheck) { - constexpr size_t n = 1 << 16; - - using OS = absl::optional<std::string>; - - OS a; - OS b = absl::nullopt; - OS c = std::string(n, 'c'); - std::string sd(n, 'd'); - OS d = sd; - OS e(absl::in_place, n, 'e'); - OS f; - f.emplace(n, 'f'); - - OS ca(a); - OS cb(b); - OS cc(c); - OS cd(d); - OS ce(e); - - OS oa; - OS ob = absl::nullopt; - OS oc = std::string(n, 'c'); - std::string sod(n, 'd'); - OS od = sod; - OS oe(absl::in_place, n, 'e'); - OS of; - of.emplace(n, 'f'); - - OS ma(std::move(oa)); - OS mb(std::move(ob)); - OS mc(std::move(oc)); - OS md(std::move(od)); - OS me(std::move(oe)); - OS mf(std::move(of)); - - OS aa1; - OS ab1 = absl::nullopt; - OS ac1 = std::string(n, 'c'); - std::string sad1(n, 'd'); - OS ad1 = sad1; - OS ae1(absl::in_place, n, 'e'); - OS af1; - af1.emplace(n, 'f'); - - OS aa2; - OS ab2 = absl::nullopt; - OS ac2 = std::string(n, 'c'); - std::string sad2(n, 'd'); - OS ad2 = sad2; - OS ae2(absl::in_place, n, 'e'); - OS af2; - af2.emplace(n, 'f'); - - aa1 = af2; - ab1 = ae2; - ac1 = ad2; - ad1 = ac2; - ae1 = ab2; - af1 = aa2; - - OS aa3; - OS ab3 = absl::nullopt; - OS ac3 = std::string(n, 'c'); - std::string sad3(n, 'd'); - OS ad3 = sad3; - OS ae3(absl::in_place, n, 'e'); - OS af3; - af3.emplace(n, 'f'); - - aa3 = absl::nullopt; - ab3 = absl::nullopt; - ac3 = absl::nullopt; - ad3 = absl::nullopt; - ae3 = absl::nullopt; - af3 = absl::nullopt; - - OS aa4; - OS ab4 = absl::nullopt; - OS ac4 = std::string(n, 'c'); - std::string sad4(n, 'd'); - OS ad4 = sad4; - OS ae4(absl::in_place, n, 'e'); - OS af4; - af4.emplace(n, 'f'); - - aa4 = OS(absl::in_place, n, 'a'); - ab4 = OS(absl::in_place, n, 'b'); - ac4 = OS(absl::in_place, n, 'c'); - ad4 = OS(absl::in_place, n, 'd'); - ae4 = OS(absl::in_place, n, 'e'); - af4 = OS(absl::in_place, n, 'f'); - - OS aa5; - OS ab5 = absl::nullopt; - OS ac5 = std::string(n, 'c'); - std::string sad5(n, 'd'); - OS ad5 = sad5; - OS ae5(absl::in_place, n, 'e'); - OS af5; - af5.emplace(n, 'f'); - - std::string saa5(n, 'a'); - std::string sab5(n, 'a'); - std::string sac5(n, 'a'); - std::string sad52(n, 'a'); - std::string sae5(n, 'a'); - std::string saf5(n, 'a'); - - aa5 = saa5; - ab5 = sab5; - ac5 = sac5; - ad5 = sad52; - ae5 = sae5; - af5 = saf5; - - OS aa6; - OS ab6 = absl::nullopt; - OS ac6 = std::string(n, 'c'); - std::string sad6(n, 'd'); - OS ad6 = sad6; - OS ae6(absl::in_place, n, 'e'); - OS af6; - af6.emplace(n, 'f'); - - aa6 = std::string(n, 'a'); - ab6 = std::string(n, 'b'); - ac6 = std::string(n, 'c'); - ad6 = std::string(n, 'd'); - ae6 = std::string(n, 'e'); - af6 = std::string(n, 'f'); - - OS aa7; - OS ab7 = absl::nullopt; - OS ac7 = std::string(n, 'c'); - std::string sad7(n, 'd'); - OS ad7 = sad7; - OS ae7(absl::in_place, n, 'e'); - OS af7; - af7.emplace(n, 'f'); - - aa7.emplace(n, 'A'); - ab7.emplace(n, 'B'); - ac7.emplace(n, 'C'); - ad7.emplace(n, 'D'); - ae7.emplace(n, 'E'); - af7.emplace(n, 'F'); -} - -TEST(optionalTest, MoveAssignRegression) { - StructorListener listener; - Listenable::listener = &listener; - - { - absl::optional<Listenable> a; - Listenable b; - a = std::move(b); - } - - EXPECT_EQ(1, listener.construct0); - EXPECT_EQ(1, listener.move); - EXPECT_EQ(2, listener.destruct); -} - -TEST(optionalTest, ValueType) { - EXPECT_TRUE((std::is_same<absl::optional<int>::value_type, int>::value)); - EXPECT_TRUE((std::is_same<absl::optional<std::string>::value_type, - std::string>::value)); - EXPECT_FALSE( - (std::is_same<absl::optional<int>::value_type, absl::nullopt_t>::value)); -} - -template <typename T> -struct is_hash_enabled_for { - template <typename U, typename = decltype(std::hash<U>()(std::declval<U>()))> - static std::true_type test(int); - - template <typename U> - static std::false_type test(...); - - static constexpr bool value = decltype(test<T>(0))::value; -}; - -TEST(optionalTest, Hash) { - std::hash<absl::optional<int>> hash; - std::set<size_t> hashcodes; - hashcodes.insert(hash(absl::nullopt)); - for (int i = 0; i < 100; ++i) { - hashcodes.insert(hash(i)); - } - EXPECT_GT(hashcodes.size(), 90); - - static_assert(is_hash_enabled_for<absl::optional<int>>::value, ""); - static_assert(is_hash_enabled_for<absl::optional<Hashable>>::value, ""); - static_assert( - absl::type_traits_internal::IsHashable<absl::optional<int>>::value, ""); - static_assert( - absl::type_traits_internal::IsHashable<absl::optional<Hashable>>::value, - ""); - absl::type_traits_internal::AssertHashEnabled<absl::optional<int>>(); - absl::type_traits_internal::AssertHashEnabled<absl::optional<Hashable>>(); - -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - static_assert(!is_hash_enabled_for<absl::optional<NonHashable>>::value, ""); - static_assert(!absl::type_traits_internal::IsHashable< - absl::optional<NonHashable>>::value, - ""); -#endif - - // libstdc++ std::optional is missing remove_const_t, i.e. it's using - // std::hash<T> rather than std::hash<std::remove_const_t<T>>. - // Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82262 -#ifndef __GLIBCXX__ - static_assert(is_hash_enabled_for<absl::optional<const int>>::value, ""); - static_assert(is_hash_enabled_for<absl::optional<const Hashable>>::value, ""); - std::hash<absl::optional<const int>> c_hash; - for (int i = 0; i < 100; ++i) { - EXPECT_EQ(hash(i), c_hash(i)); - } -#endif -} - -struct MoveMeNoThrow { - MoveMeNoThrow() : x(0) {} - [[noreturn]] MoveMeNoThrow(const MoveMeNoThrow& other) : x(other.x) { - ABSL_RAW_LOG(FATAL, "Should not be called."); - abort(); - } - MoveMeNoThrow(MoveMeNoThrow&& other) noexcept : x(other.x) {} - int x; -}; - -struct MoveMeThrow { - MoveMeThrow() : x(0) {} - MoveMeThrow(const MoveMeThrow& other) : x(other.x) {} - MoveMeThrow(MoveMeThrow&& other) : x(other.x) {} - int x; -}; - -TEST(optionalTest, NoExcept) { - static_assert( - std::is_nothrow_move_constructible<absl::optional<MoveMeNoThrow>>::value, - ""); -#ifndef ABSL_USES_STD_OPTIONAL - static_assert(absl::default_allocator_is_nothrow::value == - std::is_nothrow_move_constructible< - absl::optional<MoveMeThrow>>::value, - ""); -#endif - std::vector<absl::optional<MoveMeNoThrow>> v; - for (int i = 0; i < 10; ++i) v.emplace_back(); -} - -struct AnyLike { - AnyLike(AnyLike&&) = default; - AnyLike(const AnyLike&) = default; - - template <typename ValueType, - typename T = typename std::decay<ValueType>::type, - typename std::enable_if< - !absl::disjunction< - std::is_same<AnyLike, T>, - absl::negation<std::is_copy_constructible<T>>>::value, - int>::type = 0> - AnyLike(ValueType&&) {} // NOLINT(runtime/explicit) - - AnyLike& operator=(AnyLike&&) = default; - AnyLike& operator=(const AnyLike&) = default; - - template <typename ValueType, - typename T = typename std::decay<ValueType>::type> - typename std::enable_if< - absl::conjunction<absl::negation<std::is_same<AnyLike, T>>, - std::is_copy_constructible<T>>::value, - AnyLike&>::type - operator=(ValueType&& /* rhs */) { - return *this; - } -}; - -TEST(optionalTest, ConstructionConstraints) { - EXPECT_TRUE((std::is_constructible<AnyLike, absl::optional<AnyLike>>::value)); - - EXPECT_TRUE( - (std::is_constructible<AnyLike, const absl::optional<AnyLike>&>::value)); - - EXPECT_TRUE((std::is_constructible<absl::optional<AnyLike>, AnyLike>::value)); - EXPECT_TRUE( - (std::is_constructible<absl::optional<AnyLike>, const AnyLike&>::value)); - - EXPECT_TRUE((std::is_convertible<absl::optional<AnyLike>, AnyLike>::value)); - - EXPECT_TRUE( - (std::is_convertible<const absl::optional<AnyLike>&, AnyLike>::value)); - - EXPECT_TRUE((std::is_convertible<AnyLike, absl::optional<AnyLike>>::value)); - EXPECT_TRUE( - (std::is_convertible<const AnyLike&, absl::optional<AnyLike>>::value)); - - EXPECT_TRUE(std::is_move_constructible<absl::optional<AnyLike>>::value); - EXPECT_TRUE(std::is_copy_constructible<absl::optional<AnyLike>>::value); -} - -TEST(optionalTest, AssignmentConstraints) { - EXPECT_TRUE((std::is_assignable<AnyLike&, absl::optional<AnyLike>>::value)); - EXPECT_TRUE( - (std::is_assignable<AnyLike&, const absl::optional<AnyLike>&>::value)); - EXPECT_TRUE((std::is_assignable<absl::optional<AnyLike>&, AnyLike>::value)); - EXPECT_TRUE( - (std::is_assignable<absl::optional<AnyLike>&, const AnyLike&>::value)); - EXPECT_TRUE(std::is_move_assignable<absl::optional<AnyLike>>::value); - EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value); -} - -#if !defined(__EMSCRIPTEN__) -struct NestedClassBug { - struct Inner { - bool dummy = false; - }; - absl::optional<Inner> value; -}; - -TEST(optionalTest, InPlaceTSFINAEBug) { - NestedClassBug b; - ((void)b); - using Inner = NestedClassBug::Inner; - - EXPECT_TRUE((std::is_default_constructible<Inner>::value)); - EXPECT_TRUE((std::is_constructible<Inner>::value)); - EXPECT_TRUE( - (std::is_constructible<absl::optional<Inner>, absl::in_place_t>::value)); - - absl::optional<Inner> o(absl::in_place); - EXPECT_TRUE(o.has_value()); - o.emplace(); - EXPECT_TRUE(o.has_value()); -} -#endif // !defined(__EMSCRIPTEN__) - -} // namespace - -#endif // #if !defined(ABSL_USES_STD_OPTIONAL) diff --git a/third_party/abseil_cpp/absl/types/span.h b/third_party/abseil_cpp/absl/types/span.h deleted file mode 100644 index 95fe79262d67..000000000000 --- a/third_party/abseil_cpp/absl/types/span.h +++ /dev/null @@ -1,726 +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. -// -// ----------------------------------------------------------------------------- -// span.h -// ----------------------------------------------------------------------------- -// -// This header file defines a `Span<T>` type for holding a reference to existing -// array data. The `Span` object, much like the `absl::string_view` object, -// does not own such data itself, and the data being referenced by the span must -// outlive the span itself. Unlike `view` type references, a span can hold a -// reference to mutable data (and can mutate it for underlying types of -// non-const T.) A span provides a lightweight way to pass a reference to such -// data. -// -// Additionally, this header file defines `MakeSpan()` and `MakeConstSpan()` -// factory functions, for clearly creating spans of type `Span<T>` or read-only -// `Span<const T>` when such types may be difficult to identify due to issues -// with implicit conversion. -// -// The C++20 draft standard includes a `std::span` type. As of June 2020, the -// differences between `absl::Span` and `std::span` are: -// * `absl::Span` has `operator==` (which is likely a design bug, -// per https://abseil.io/blog/20180531-regular-types) -// * `absl::Span` has the factory functions `MakeSpan()` and -// `MakeConstSpan()` -// * bounds-checked access to `absl::Span` is accomplished with `at()` -// * `absl::Span` has compiler-provided move and copy constructors and -// assignment. This is due to them being specified as `constexpr`, but that -// implies const in C++11. -// * `absl::Span` has no `element_type` typedef -// * A read-only `absl::Span<const T>` can be implicitly constructed from an -// initializer list. -// * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or -// `as_mutable_bytes()` methods -// * `absl::Span` has no static extent template parameter, nor constructors -// which exist only because of the static extent parameter. -// * `absl::Span` has an explicit mutable-reference constructor -// -// For more information, see the class comments below. -#ifndef ABSL_TYPES_SPAN_H_ -#define ABSL_TYPES_SPAN_H_ - -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <initializer_list> -#include <iterator> -#include <type_traits> -#include <utility> - -#include "absl/base/internal/throw_delegate.h" -#include "absl/base/macros.h" -#include "absl/base/optimization.h" -#include "absl/base/port.h" // TODO(strel): remove this include -#include "absl/meta/type_traits.h" -#include "absl/types/internal/span.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -//------------------------------------------------------------------------------ -// Span -//------------------------------------------------------------------------------ -// -// A `Span` is an "array reference" type for holding a reference of contiguous -// array data; the `Span` object does not and cannot own such data itself. A -// span provides an easy way to provide overloads for anything operating on -// contiguous sequences without needing to manage pointers and array lengths -// manually. - -// A span is conceptually a pointer (ptr) and a length (size) into an already -// existing array of contiguous memory; the array it represents references the -// elements "ptr[0] .. ptr[size-1]". Passing a properly-constructed `Span` -// instead of raw pointers avoids many issues related to index out of bounds -// errors. -// -// Spans may also be constructed from containers holding contiguous sequences. -// Such containers must supply `data()` and `size() const` methods (e.g -// `std::vector<T>`, `absl::InlinedVector<T, N>`). All implicit conversions to -// `absl::Span` from such containers will create spans of type `const T`; -// spans which can mutate their values (of type `T`) must use explicit -// constructors. -// -// A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array -// of elements of type `T`, and unlike an `absl::string_view`, a span can hold a -// reference to mutable data. A user of `Span` must ensure that the data being -// pointed to outlives the `Span` itself. -// -// You can construct a `Span<T>` in several ways: -// -// * Explicitly from a reference to a container type -// * Explicitly from a pointer and size -// * Implicitly from a container type (but only for spans of type `const T`) -// * Using the `MakeSpan()` or `MakeConstSpan()` factory functions. -// -// Examples: -// -// // Construct a Span explicitly from a container: -// std::vector<int> v = {1, 2, 3, 4, 5}; -// auto span = absl::Span<const int>(v); -// -// // Construct a Span explicitly from a C-style array: -// int a[5] = {1, 2, 3, 4, 5}; -// auto span = absl::Span<const int>(a); -// -// // Construct a Span implicitly from a container -// void MyRoutine(absl::Span<const int> a) { -// ... -// } -// std::vector v = {1,2,3,4,5}; -// MyRoutine(v) // convert to Span<const T> -// -// Note that `Span` objects, in addition to requiring that the memory they -// point to remains alive, must also ensure that such memory does not get -// reallocated. Therefore, to avoid undefined behavior, containers with -// associated spans should not invoke operations that may reallocate memory -// (such as resizing) or invalidate iterators into the container. -// -// One common use for a `Span` is when passing arguments to a routine that can -// accept a variety of array types (e.g. a `std::vector`, `absl::InlinedVector`, -// a C-style array, etc.). Instead of creating overloads for each case, you -// can simply specify a `Span` as the argument to such a routine. -// -// Example: -// -// void MyRoutine(absl::Span<const int> a) { -// ... -// } -// -// std::vector v = {1,2,3,4,5}; -// MyRoutine(v); -// -// absl::InlinedVector<int, 4> my_inline_vector; -// MyRoutine(my_inline_vector); -// -// // Explicit constructor from pointer,size -// int* my_array = new int[10]; -// MyRoutine(absl::Span<const int>(my_array, 10)); -template <typename T> -class Span { - private: - // Used to determine whether a Span can be constructed from a container of - // type C. - template <typename C> - using EnableIfConvertibleFrom = - typename std::enable_if<span_internal::HasData<T, C>::value && - span_internal::HasSize<C>::value>::type; - - // Used to SFINAE-enable a function when the slice elements are const. - template <typename U> - using EnableIfConstView = - typename std::enable_if<std::is_const<T>::value, U>::type; - - // Used to SFINAE-enable a function when the slice elements are mutable. - template <typename U> - using EnableIfMutableView = - typename std::enable_if<!std::is_const<T>::value, U>::type; - - public: - using value_type = absl::remove_cv_t<T>; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - using size_type = size_t; - using difference_type = ptrdiff_t; - - static const size_type npos = ~(size_type(0)); - - constexpr Span() noexcept : Span(nullptr, 0) {} - constexpr Span(pointer array, size_type length) noexcept - : ptr_(array), len_(length) {} - - // Implicit conversion constructors - template <size_t N> - constexpr Span(T (&a)[N]) noexcept // NOLINT(runtime/explicit) - : Span(a, N) {} - - // Explicit reference constructor for a mutable `Span<T>` type. Can be - // replaced with MakeSpan() to infer the type parameter. - template <typename V, typename = EnableIfConvertibleFrom<V>, - typename = EnableIfMutableView<V>> - explicit Span(V& v) noexcept // NOLINT(runtime/references) - : Span(span_internal::GetData(v), v.size()) {} - - // Implicit reference constructor for a read-only `Span<const T>` type - template <typename V, typename = EnableIfConvertibleFrom<V>, - typename = EnableIfConstView<V>> - constexpr Span(const V& v) noexcept // NOLINT(runtime/explicit) - : Span(span_internal::GetData(v), v.size()) {} - - // Implicit constructor from an initializer list, making it possible to pass a - // brace-enclosed initializer list to a function expecting a `Span`. Such - // spans constructed from an initializer list must be of type `Span<const T>`. - // - // void Process(absl::Span<const int> x); - // Process({1, 2, 3}); - // - // Note that as always the array referenced by the span must outlive the span. - // Since an initializer list constructor acts as if it is fed a temporary - // array (cf. C++ standard [dcl.init.list]/5), it's safe to use this - // constructor only when the `std::initializer_list` itself outlives the span. - // In order to meet this requirement it's sufficient to ensure that neither - // the span nor a copy of it is used outside of the expression in which it's - // created: - // - // // Assume that this function uses the array directly, not retaining any - // // copy of the span or pointer to any of its elements. - // void Process(absl::Span<const int> ints); - // - // // Okay: the std::initializer_list<int> will reference a temporary array - // // that isn't destroyed until after the call to Process returns. - // Process({ 17, 19 }); - // - // // Not okay: the storage used by the std::initializer_list<int> is not - // // allowed to be referenced after the first line. - // absl::Span<const int> ints = { 17, 19 }; - // Process(ints); - // - // // Not okay for the same reason as above: even when the elements of the - // // initializer list expression are not temporaries the underlying array - // // is, so the initializer list must still outlive the span. - // const int foo = 17; - // absl::Span<const int> ints = { foo }; - // Process(ints); - // - template <typename LazyT = T, - typename = EnableIfConstView<LazyT>> - Span( - std::initializer_list<value_type> v) noexcept // NOLINT(runtime/explicit) - : Span(v.begin(), v.size()) {} - - // Accessors - - // Span::data() - // - // Returns a pointer to the span's underlying array of data (which is held - // outside the span). - constexpr pointer data() const noexcept { return ptr_; } - - // Span::size() - // - // Returns the size of this span. - constexpr size_type size() const noexcept { return len_; } - - // Span::length() - // - // Returns the length (size) of this span. - constexpr size_type length() const noexcept { return size(); } - - // Span::empty() - // - // Returns a boolean indicating whether or not this span is considered empty. - constexpr bool empty() const noexcept { return size() == 0; } - - // Span::operator[] - // - // Returns a reference to the i'th element of this span. - constexpr reference operator[](size_type i) const noexcept { - // MSVC 2015 accepts this as constexpr, but not ptr_[i] - return ABSL_HARDENING_ASSERT(i < size()), *(data() + i); - } - - // Span::at() - // - // Returns a reference to the i'th element of this span. - constexpr reference at(size_type i) const { - return ABSL_PREDICT_TRUE(i < size()) // - ? *(data() + i) - : (base_internal::ThrowStdOutOfRange( - "Span::at failed bounds check"), - *(data() + i)); - } - - // Span::front() - // - // Returns a reference to the first element of this span. The span must not - // be empty. - constexpr reference front() const noexcept { - return ABSL_HARDENING_ASSERT(size() > 0), *data(); - } - - // Span::back() - // - // Returns a reference to the last element of this span. The span must not - // be empty. - constexpr reference back() const noexcept { - return ABSL_HARDENING_ASSERT(size() > 0), *(data() + size() - 1); - } - - // Span::begin() - // - // Returns an iterator pointing to the first element of this span, or `end()` - // if the span is empty. - constexpr iterator begin() const noexcept { return data(); } - - // Span::cbegin() - // - // Returns a const iterator pointing to the first element of this span, or - // `end()` if the span is empty. - constexpr const_iterator cbegin() const noexcept { return begin(); } - - // Span::end() - // - // Returns an iterator pointing just beyond the last element at the - // end of this span. This iterator acts as a placeholder; attempting to - // access it results in undefined behavior. - constexpr iterator end() const noexcept { return data() + size(); } - - // Span::cend() - // - // Returns a const iterator pointing just beyond the last element at the - // end of this span. This iterator acts as a placeholder; attempting to - // access it results in undefined behavior. - constexpr const_iterator cend() const noexcept { return end(); } - - // Span::rbegin() - // - // Returns a reverse iterator pointing to the last element at the end of this - // span, or `rend()` if the span is empty. - constexpr reverse_iterator rbegin() const noexcept { - return reverse_iterator(end()); - } - - // Span::crbegin() - // - // Returns a const reverse iterator pointing to the last element at the end of - // this span, or `crend()` if the span is empty. - constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } - - // Span::rend() - // - // Returns a reverse iterator pointing just before the first element - // at the beginning of this span. This pointer acts as a placeholder; - // attempting to access its element results in undefined behavior. - constexpr reverse_iterator rend() const noexcept { - return reverse_iterator(begin()); - } - - // Span::crend() - // - // Returns a reverse const iterator pointing just before the first element - // at the beginning of this span. This pointer acts as a placeholder; - // attempting to access its element results in undefined behavior. - constexpr const_reverse_iterator crend() const noexcept { return rend(); } - - // Span mutations - - // Span::remove_prefix() - // - // Removes the first `n` elements from the span. - void remove_prefix(size_type n) noexcept { - ABSL_HARDENING_ASSERT(size() >= n); - ptr_ += n; - len_ -= n; - } - - // Span::remove_suffix() - // - // Removes the last `n` elements from the span. - void remove_suffix(size_type n) noexcept { - ABSL_HARDENING_ASSERT(size() >= n); - len_ -= n; - } - - // Span::subspan() - // - // Returns a `Span` starting at element `pos` and of length `len`. Both `pos` - // and `len` are of type `size_type` and thus non-negative. Parameter `pos` - // must be <= size(). Any `len` value that points past the end of the span - // will be trimmed to at most size() - `pos`. A default `len` value of `npos` - // ensures the returned subspan continues until the end of the span. - // - // Examples: - // - // std::vector<int> vec = {10, 11, 12, 13}; - // absl::MakeSpan(vec).subspan(1, 2); // {11, 12} - // absl::MakeSpan(vec).subspan(2, 8); // {12, 13} - // absl::MakeSpan(vec).subspan(1); // {11, 12, 13} - // 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 <= size()) - ? Span(data() + pos, span_internal::Min(size() - pos, len)) - : (base_internal::ThrowStdOutOfRange("pos > size()"), Span()); - } - - // Span::first() - // - // Returns a `Span` containing first `len` elements. Parameter `len` is of - // type `size_type` and thus non-negative. `len` value must be <= size(). - // - // Examples: - // - // std::vector<int> vec = {10, 11, 12, 13}; - // absl::MakeSpan(vec).first(1); // {10} - // absl::MakeSpan(vec).first(3); // {10, 11, 12} - // absl::MakeSpan(vec).first(5); // throws std::out_of_range - constexpr Span first(size_type len) const { - return (len <= size()) - ? Span(data(), len) - : (base_internal::ThrowStdOutOfRange("len > size()"), Span()); - } - - // Span::last() - // - // Returns a `Span` containing last `len` elements. Parameter `len` is of - // type `size_type` and thus non-negative. `len` value must be <= size(). - // - // Examples: - // - // std::vector<int> vec = {10, 11, 12, 13}; - // absl::MakeSpan(vec).last(1); // {13} - // absl::MakeSpan(vec).last(3); // {11, 12, 13} - // absl::MakeSpan(vec).last(5); // throws std::out_of_range - constexpr Span last(size_type len) const { - return (len <= size()) - ? Span(size() - len + data(), len) - : (base_internal::ThrowStdOutOfRange("len > 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_; -}; - -template <typename T> -const typename Span<T>::size_type Span<T>::npos; - -// Span relationals - -// Equality is compared element-by-element, while ordering is lexicographical. -// We provide three overloads for each operator to cover any combination on the -// left or right hand side of mutable Span<T>, read-only Span<const T>, and -// convertible-to-read-only Span<T>. -// TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering -// template functions, 5 overloads per operator is needed as a workaround. We -// should update them to 3 overloads per operator using non-deduced context like -// string_view, i.e. -// - (Span<T>, Span<T>) -// - (Span<T>, non_deduced<Span<const T>>) -// - (non_deduced<Span<const T>>, Span<T>) - -// operator== -template <typename T> -bool operator==(Span<T> a, Span<T> b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} -template <typename T> -bool operator==(Span<const T> a, Span<T> b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} -template <typename T> -bool operator==(Span<T> a, Span<const T> b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator==(const U& a, Span<T> b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator==(Span<T> a, const U& b) { - return span_internal::EqualImpl<Span, const T>(a, b); -} - -// operator!= -template <typename T> -bool operator!=(Span<T> a, Span<T> b) { - return !(a == b); -} -template <typename T> -bool operator!=(Span<const T> a, Span<T> b) { - return !(a == b); -} -template <typename T> -bool operator!=(Span<T> a, Span<const T> b) { - return !(a == b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator!=(const U& a, Span<T> b) { - return !(a == b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator!=(Span<T> a, const U& b) { - return !(a == b); -} - -// operator< -template <typename T> -bool operator<(Span<T> a, Span<T> b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} -template <typename T> -bool operator<(Span<const T> a, Span<T> b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} -template <typename T> -bool operator<(Span<T> a, Span<const T> b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<(const U& a, Span<T> b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<(Span<T> a, const U& b) { - return span_internal::LessThanImpl<Span, const T>(a, b); -} - -// operator> -template <typename T> -bool operator>(Span<T> a, Span<T> b) { - return b < a; -} -template <typename T> -bool operator>(Span<const T> a, Span<T> b) { - return b < a; -} -template <typename T> -bool operator>(Span<T> a, Span<const T> b) { - return b < a; -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>(const U& a, Span<T> b) { - return b < a; -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>(Span<T> a, const U& b) { - return b < a; -} - -// operator<= -template <typename T> -bool operator<=(Span<T> a, Span<T> b) { - return !(b < a); -} -template <typename T> -bool operator<=(Span<const T> a, Span<T> b) { - return !(b < a); -} -template <typename T> -bool operator<=(Span<T> a, Span<const T> b) { - return !(b < a); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<=(const U& a, Span<T> b) { - return !(b < a); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<=(Span<T> a, const U& b) { - return !(b < a); -} - -// operator>= -template <typename T> -bool operator>=(Span<T> a, Span<T> b) { - return !(a < b); -} -template <typename T> -bool operator>=(Span<const T> a, Span<T> b) { - return !(a < b); -} -template <typename T> -bool operator>=(Span<T> a, Span<const T> b) { - return !(a < b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>=(const U& a, Span<T> b) { - return !(a < b); -} -template < - typename T, typename U, - typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>=(Span<T> a, const U& b) { - return !(a < b); -} - -// MakeSpan() -// -// Constructs a mutable `Span<T>`, deducing `T` automatically from either a -// container or pointer+size. -// -// Because a read-only `Span<const T>` is implicitly constructed from container -// types regardless of whether the container itself is a const container, -// constructing mutable spans of type `Span<T>` from containers requires -// explicit constructors. The container-accepting version of `MakeSpan()` -// deduces the type of `T` by the constness of the pointer received from the -// container's `data()` member. Similarly, the pointer-accepting version returns -// a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise. -// -// Examples: -// -// void MyRoutine(absl::Span<MyComplicatedType> a) { -// ... -// }; -// // my_vector is a container of non-const types -// std::vector<MyComplicatedType> my_vector; -// -// // Constructing a Span implicitly attempts to create a Span of type -// // `Span<const T>` -// MyRoutine(my_vector); // error, type mismatch -// -// // Explicitly constructing the Span is verbose -// MyRoutine(absl::Span<MyComplicatedType>(my_vector)); -// -// // Use MakeSpan() to make an absl::Span<T> -// MyRoutine(absl::MakeSpan(my_vector)); -// -// // Construct a span from an array ptr+size -// absl::Span<T> my_span() { -// return absl::MakeSpan(&array[0], num_elements_); -// } -// -template <int&... ExplicitArgumentBarrier, typename T> -constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept { - return Span<T>(ptr, size); -} - -template <int&... ExplicitArgumentBarrier, typename T> -Span<T> MakeSpan(T* begin, T* end) noexcept { - return ABSL_HARDENING_ASSERT(begin <= end), Span<T>(begin, end - begin); -} - -template <int&... ExplicitArgumentBarrier, typename C> -constexpr auto MakeSpan(C& c) noexcept // NOLINT(runtime/references) - -> decltype(absl::MakeSpan(span_internal::GetData(c), c.size())) { - return MakeSpan(span_internal::GetData(c), c.size()); -} - -template <int&... ExplicitArgumentBarrier, typename T, size_t N> -constexpr Span<T> MakeSpan(T (&array)[N]) noexcept { - return Span<T>(array, N); -} - -// MakeConstSpan() -// -// Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically, -// but always returning a `Span<const T>`. -// -// Examples: -// -// void ProcessInts(absl::Span<const int> some_ints); -// -// // Call with a pointer and size. -// int array[3] = { 0, 0, 0 }; -// ProcessInts(absl::MakeConstSpan(&array[0], 3)); -// -// // Call with a [begin, end) pair. -// ProcessInts(absl::MakeConstSpan(&array[0], &array[3])); -// -// // Call directly with an array. -// ProcessInts(absl::MakeConstSpan(array)); -// -// // Call with a contiguous container. -// std::vector<int> some_ints = ...; -// ProcessInts(absl::MakeConstSpan(some_ints)); -// ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 })); -// -template <int&... ExplicitArgumentBarrier, typename T> -constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept { - return Span<const T>(ptr, size); -} - -template <int&... ExplicitArgumentBarrier, typename T> -Span<const T> MakeConstSpan(T* begin, T* end) noexcept { - return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin); -} - -template <int&... ExplicitArgumentBarrier, typename C> -constexpr auto MakeConstSpan(const C& c) noexcept -> decltype(MakeSpan(c)) { - return MakeSpan(c); -} - -template <int&... ExplicitArgumentBarrier, typename T, size_t N> -constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept { - return Span<const T>(array, N); -} -ABSL_NAMESPACE_END -} // namespace absl -#endif // ABSL_TYPES_SPAN_H_ diff --git a/third_party/abseil_cpp/absl/types/span_test.cc b/third_party/abseil_cpp/absl/types/span_test.cc deleted file mode 100644 index 2584339bd309..000000000000 --- a/third_party/abseil_cpp/absl/types/span_test.cc +++ /dev/null @@ -1,846 +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/span.h" - -#include <array> -#include <initializer_list> -#include <numeric> -#include <stdexcept> -#include <string> -#include <type_traits> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/attributes.h" -#include "absl/base/config.h" -#include "absl/base/internal/exception_testing.h" -#include "absl/base/options.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 { - -MATCHER_P(DataIs, data, - absl::StrCat("data() ", negation ? "isn't " : "is ", - testing::PrintToString(data))) { - return arg.data() == data; -} - -template <typename T> -auto SpanIs(T data, size_t size) - -> decltype(testing::AllOf(DataIs(data), testing::SizeIs(size))) { - return testing::AllOf(DataIs(data), testing::SizeIs(size)); -} - -template <typename Container> -auto SpanIs(const Container& c) -> decltype(SpanIs(c.data(), c.size())) { - return SpanIs(c.data(), c.size()); -} - -std::vector<int> MakeRamp(int len, int offset = 0) { - std::vector<int> v(len); - std::iota(v.begin(), v.end(), offset); - return v; -} - -TEST(IntSpan, EmptyCtors) { - absl::Span<int> s; - EXPECT_THAT(s, SpanIs(nullptr, 0)); -} - -TEST(IntSpan, PtrLenCtor) { - int a[] = {1, 2, 3}; - absl::Span<int> s(&a[0], 2); - EXPECT_THAT(s, SpanIs(a, 2)); -} - -TEST(IntSpan, ArrayCtor) { - int a[] = {1, 2, 3}; - absl::Span<int> s(a); - EXPECT_THAT(s, SpanIs(a, 3)); - - EXPECT_TRUE((std::is_constructible<absl::Span<const int>, int[3]>::value)); - EXPECT_TRUE( - (std::is_constructible<absl::Span<const int>, const int[3]>::value)); - EXPECT_FALSE((std::is_constructible<absl::Span<int>, const int[3]>::value)); - EXPECT_TRUE((std::is_convertible<int[3], absl::Span<const int>>::value)); - EXPECT_TRUE( - (std::is_convertible<const int[3], absl::Span<const int>>::value)); -} - -template <typename T> -void TakesGenericSpan(absl::Span<T>) {} - -TEST(IntSpan, ContainerCtor) { - std::vector<int> empty; - absl::Span<int> s_empty(empty); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::vector<int> filled{1, 2, 3}; - absl::Span<int> s_filled(filled); - EXPECT_THAT(s_filled, SpanIs(filled)); - - absl::Span<int> s_from_span(filled); - EXPECT_THAT(s_from_span, SpanIs(s_filled)); - - absl::Span<const int> const_filled = filled; - EXPECT_THAT(const_filled, SpanIs(filled)); - - absl::Span<const int> const_from_span = s_filled; - EXPECT_THAT(const_from_span, SpanIs(s_filled)); - - EXPECT_TRUE( - (std::is_convertible<std::vector<int>&, absl::Span<const int>>::value)); - EXPECT_TRUE( - (std::is_convertible<absl::Span<int>&, absl::Span<const int>>::value)); - - TakesGenericSpan(absl::Span<int>(filled)); -} - -// A struct supplying shallow data() const. -struct ContainerWithShallowConstData { - std::vector<int> storage; - int* data() const { return const_cast<int*>(storage.data()); } - int size() const { return storage.size(); } -}; - -TEST(IntSpan, ShallowConstness) { - const ContainerWithShallowConstData c{MakeRamp(20)}; - absl::Span<int> s( - c); // We should be able to do this even though data() is const. - s[0] = -1; - EXPECT_EQ(c.storage[0], -1); -} - -TEST(CharSpan, StringCtor) { - std::string empty = ""; - absl::Span<char> s_empty(empty); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::string abc = "abc"; - absl::Span<char> s_abc(abc); - EXPECT_THAT(s_abc, SpanIs(abc)); - - absl::Span<const char> s_const_abc = abc; - EXPECT_THAT(s_const_abc, SpanIs(abc)); - - EXPECT_FALSE((std::is_constructible<absl::Span<int>, std::string>::value)); - EXPECT_FALSE( - (std::is_constructible<absl::Span<const int>, std::string>::value)); - EXPECT_TRUE( - (std::is_convertible<std::string, absl::Span<const char>>::value)); -} - -TEST(IntSpan, FromConstPointer) { - EXPECT_TRUE((std::is_constructible<absl::Span<const int* const>, - std::vector<int*>>::value)); - EXPECT_TRUE((std::is_constructible<absl::Span<const int* const>, - std::vector<const int*>>::value)); - EXPECT_FALSE(( - std::is_constructible<absl::Span<const int*>, std::vector<int*>>::value)); - EXPECT_FALSE(( - std::is_constructible<absl::Span<int*>, std::vector<const int*>>::value)); -} - -struct TypeWithMisleadingData { - int& data() { return i; } - int size() { return 1; } - int i; -}; - -struct TypeWithMisleadingSize { - int* data() { return &i; } - const char* size() { return "1"; } - int i; -}; - -TEST(IntSpan, EvilTypes) { - EXPECT_FALSE( - (std::is_constructible<absl::Span<int>, TypeWithMisleadingData&>::value)); - EXPECT_FALSE( - (std::is_constructible<absl::Span<int>, TypeWithMisleadingSize&>::value)); -} - -struct Base { - int* data() { return &i; } - int size() { return 1; } - int i; -}; -struct Derived : Base {}; - -TEST(IntSpan, SpanOfDerived) { - EXPECT_TRUE((std::is_constructible<absl::Span<int>, Base&>::value)); - EXPECT_TRUE((std::is_constructible<absl::Span<int>, Derived&>::value)); - EXPECT_FALSE( - (std::is_constructible<absl::Span<Base>, std::vector<Derived>>::value)); -} - -void TestInitializerList(absl::Span<const int> s, const std::vector<int>& v) { - EXPECT_TRUE(absl::equal(s.begin(), s.end(), v.begin(), v.end())); -} - -TEST(ConstIntSpan, InitializerListConversion) { - TestInitializerList({}, {}); - TestInitializerList({1}, {1}); - TestInitializerList({1, 2, 3}, {1, 2, 3}); - - EXPECT_FALSE((std::is_constructible<absl::Span<int>, - std::initializer_list<int>>::value)); - EXPECT_FALSE(( - std::is_convertible<absl::Span<int>, std::initializer_list<int>>::value)); -} - -TEST(IntSpan, Data) { - int i; - absl::Span<int> s(&i, 1); - EXPECT_EQ(&i, s.data()); -} - -TEST(IntSpan, SizeLengthEmpty) { - absl::Span<int> empty; - EXPECT_EQ(empty.size(), 0); - EXPECT_TRUE(empty.empty()); - EXPECT_EQ(empty.size(), empty.length()); - - auto v = MakeRamp(10); - absl::Span<int> s(v); - EXPECT_EQ(s.size(), 10); - EXPECT_FALSE(s.empty()); - EXPECT_EQ(s.size(), s.length()); -} - -TEST(IntSpan, ElementAccess) { - auto v = MakeRamp(10); - absl::Span<int> s(v); - for (int i = 0; i < s.size(); ++i) { - EXPECT_EQ(s[i], s.at(i)); - } - - EXPECT_EQ(s.front(), s[0]); - EXPECT_EQ(s.back(), s[9]); - -#if !defined(NDEBUG) || ABSL_OPTION_HARDENED - EXPECT_DEATH_IF_SUPPORTED(s[-1], ""); - EXPECT_DEATH_IF_SUPPORTED(s[10], ""); -#endif -} - -TEST(IntSpan, AtThrows) { - auto v = MakeRamp(10); - absl::Span<int> s(v); - - EXPECT_EQ(s.at(9), 9); - ABSL_BASE_INTERNAL_EXPECT_FAIL(s.at(10), std::out_of_range, - "failed bounds check"); -} - -TEST(IntSpan, RemovePrefixAndSuffix) { - auto v = MakeRamp(20, 1); - absl::Span<int> s(v); - EXPECT_EQ(s.size(), 20); - - s.remove_suffix(0); - s.remove_prefix(0); - EXPECT_EQ(s.size(), 20); - - s.remove_prefix(1); - EXPECT_EQ(s.size(), 19); - EXPECT_EQ(s[0], 2); - - s.remove_suffix(1); - EXPECT_EQ(s.size(), 18); - EXPECT_EQ(s.back(), 19); - - s.remove_prefix(7); - EXPECT_EQ(s.size(), 11); - EXPECT_EQ(s[0], 9); - - s.remove_suffix(11); - EXPECT_EQ(s.size(), 0); - - EXPECT_EQ(v, MakeRamp(20, 1)); - -#if !defined(NDEBUG) || ABSL_OPTION_HARDENED - absl::Span<int> prefix_death(v); - EXPECT_DEATH_IF_SUPPORTED(prefix_death.remove_prefix(21), ""); - absl::Span<int> suffix_death(v); - EXPECT_DEATH_IF_SUPPORTED(suffix_death.remove_suffix(21), ""); -#endif -} - -TEST(IntSpan, Subspan) { - std::vector<int> empty; - EXPECT_EQ(absl::MakeSpan(empty).subspan(), empty); - EXPECT_THAT(absl::MakeSpan(empty).subspan(0, 0), SpanIs(empty)); - EXPECT_THAT(absl::MakeSpan(empty).subspan(0, absl::Span<const int>::npos), - SpanIs(empty)); - - auto ramp = MakeRamp(10); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(), SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, 10), SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, absl::Span<const int>::npos), - SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, 3), SpanIs(ramp.data(), 3)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(5, absl::Span<const int>::npos), - SpanIs(ramp.data() + 5, 5)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(3, 3), SpanIs(ramp.data() + 3, 3)); - EXPECT_THAT(absl::MakeSpan(ramp).subspan(10, 5), SpanIs(ramp.data() + 10, 0)); - -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(absl::MakeSpan(ramp).subspan(11, 5), std::out_of_range); -#else - EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).subspan(11, 5), ""); -#endif -} - -TEST(IntSpan, First) { - std::vector<int> empty; - EXPECT_THAT(absl::MakeSpan(empty).first(0), SpanIs(empty)); - - auto ramp = MakeRamp(10); - EXPECT_THAT(absl::MakeSpan(ramp).first(0), SpanIs(ramp.data(), 0)); - EXPECT_THAT(absl::MakeSpan(ramp).first(10), SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).first(3), SpanIs(ramp.data(), 3)); - -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(absl::MakeSpan(ramp).first(11), std::out_of_range); -#else - EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).first(11), ""); -#endif -} - -TEST(IntSpan, Last) { - std::vector<int> empty; - EXPECT_THAT(absl::MakeSpan(empty).last(0), SpanIs(empty)); - - auto ramp = MakeRamp(10); - EXPECT_THAT(absl::MakeSpan(ramp).last(0), SpanIs(ramp.data() + 10, 0)); - EXPECT_THAT(absl::MakeSpan(ramp).last(10), SpanIs(ramp)); - EXPECT_THAT(absl::MakeSpan(ramp).last(3), SpanIs(ramp.data() + 7, 3)); - -#ifdef ABSL_HAVE_EXCEPTIONS - EXPECT_THROW(absl::MakeSpan(ramp).last(11), std::out_of_range); -#else - EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).last(11), ""); -#endif -} - -TEST(IntSpan, MakeSpanPtrLength) { - std::vector<int> empty; - auto s_empty = absl::MakeSpan(empty.data(), empty.size()); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::array<int, 3> a{{1, 2, 3}}; - auto s = absl::MakeSpan(a.data(), a.size()); - EXPECT_THAT(s, SpanIs(a)); - - EXPECT_THAT(absl::MakeConstSpan(empty.data(), empty.size()), SpanIs(s_empty)); - EXPECT_THAT(absl::MakeConstSpan(a.data(), a.size()), SpanIs(s)); -} - -TEST(IntSpan, MakeSpanTwoPtrs) { - std::vector<int> empty; - auto s_empty = absl::MakeSpan(empty.data(), empty.data()); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::vector<int> v{1, 2, 3}; - auto s = absl::MakeSpan(v.data(), v.data() + 1); - EXPECT_THAT(s, SpanIs(v.data(), 1)); - - EXPECT_THAT(absl::MakeConstSpan(empty.data(), empty.data()), SpanIs(s_empty)); - EXPECT_THAT(absl::MakeConstSpan(v.data(), v.data() + 1), SpanIs(s)); -} - -TEST(IntSpan, MakeSpanContainer) { - std::vector<int> empty; - auto s_empty = absl::MakeSpan(empty); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::vector<int> v{1, 2, 3}; - auto s = absl::MakeSpan(v); - EXPECT_THAT(s, SpanIs(v)); - - EXPECT_THAT(absl::MakeConstSpan(empty), SpanIs(s_empty)); - EXPECT_THAT(absl::MakeConstSpan(v), SpanIs(s)); - - EXPECT_THAT(absl::MakeSpan(s), SpanIs(s)); - EXPECT_THAT(absl::MakeConstSpan(s), SpanIs(s)); -} - -TEST(CharSpan, MakeSpanString) { - std::string empty = ""; - auto s_empty = absl::MakeSpan(empty); - EXPECT_THAT(s_empty, SpanIs(empty)); - - std::string str = "abc"; - auto s_str = absl::MakeSpan(str); - EXPECT_THAT(s_str, SpanIs(str)); - - EXPECT_THAT(absl::MakeConstSpan(empty), SpanIs(s_empty)); - EXPECT_THAT(absl::MakeConstSpan(str), SpanIs(s_str)); -} - -TEST(IntSpan, MakeSpanArray) { - int a[] = {1, 2, 3}; - auto s = absl::MakeSpan(a); - EXPECT_THAT(s, SpanIs(a, 3)); - - const int ca[] = {1, 2, 3}; - auto s_ca = absl::MakeSpan(ca); - EXPECT_THAT(s_ca, SpanIs(ca, 3)); - - EXPECT_THAT(absl::MakeConstSpan(a), SpanIs(s)); - EXPECT_THAT(absl::MakeConstSpan(ca), SpanIs(s_ca)); -} - -// Compile-asserts that the argument has the expected decayed type. -template <typename Expected, typename T> -void CheckType(const T& /* value */) { - testing::StaticAssertTypeEq<Expected, T>(); -} - -TEST(IntSpan, MakeSpanTypes) { - std::vector<int> vec; - const std::vector<int> cvec; - int a[1]; - const int ca[] = {1}; - int* ip = a; - const int* cip = ca; - std::string s = ""; - const std::string cs = ""; - CheckType<absl::Span<int>>(absl::MakeSpan(vec)); - CheckType<absl::Span<const int>>(absl::MakeSpan(cvec)); - CheckType<absl::Span<int>>(absl::MakeSpan(ip, ip + 1)); - CheckType<absl::Span<int>>(absl::MakeSpan(ip, 1)); - CheckType<absl::Span<const int>>(absl::MakeSpan(cip, cip + 1)); - CheckType<absl::Span<const int>>(absl::MakeSpan(cip, 1)); - CheckType<absl::Span<int>>(absl::MakeSpan(a)); - CheckType<absl::Span<int>>(absl::MakeSpan(a, a + 1)); - CheckType<absl::Span<int>>(absl::MakeSpan(a, 1)); - CheckType<absl::Span<const int>>(absl::MakeSpan(ca)); - CheckType<absl::Span<const int>>(absl::MakeSpan(ca, ca + 1)); - CheckType<absl::Span<const int>>(absl::MakeSpan(ca, 1)); - CheckType<absl::Span<char>>(absl::MakeSpan(s)); - CheckType<absl::Span<const char>>(absl::MakeSpan(cs)); -} - -TEST(ConstIntSpan, MakeConstSpanTypes) { - std::vector<int> vec; - const std::vector<int> cvec; - int array[1]; - const int carray[] = {0}; - int* ptr = array; - const int* cptr = carray; - std::string s = ""; - std::string cs = ""; - CheckType<absl::Span<const int>>(absl::MakeConstSpan(vec)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(cvec)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(ptr, ptr + 1)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(ptr, 1)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(cptr, cptr + 1)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(cptr, 1)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(array)); - CheckType<absl::Span<const int>>(absl::MakeConstSpan(carray)); - CheckType<absl::Span<const char>>(absl::MakeConstSpan(s)); - CheckType<absl::Span<const char>>(absl::MakeConstSpan(cs)); -} - -TEST(IntSpan, Equality) { - const int arr1[] = {1, 2, 3, 4, 5}; - int arr2[] = {1, 2, 3, 4, 5}; - std::vector<int> vec1(std::begin(arr1), std::end(arr1)); - std::vector<int> vec2 = vec1; - std::vector<int> other_vec = {2, 4, 6, 8, 10}; - // These two slices are from different vectors, but have the same size and - // have the same elements (right now). They should compare equal. Test both - // == and !=. - const absl::Span<const int> from1 = vec1; - const absl::Span<const int> from2 = vec2; - EXPECT_EQ(from1, from1); - EXPECT_FALSE(from1 != from1); - EXPECT_EQ(from1, from2); - EXPECT_FALSE(from1 != from2); - - // These two slices have different underlying vector values. They should be - // considered not equal. Test both == and !=. - const absl::Span<const int> from_other = other_vec; - EXPECT_NE(from1, from_other); - EXPECT_FALSE(from1 == from_other); - - // Comparison between a vector and its slice should be equal. And vice-versa. - // This ensures implicit conversion to Span works on both sides of ==. - EXPECT_EQ(vec1, from1); - EXPECT_FALSE(vec1 != from1); - EXPECT_EQ(from1, vec1); - EXPECT_FALSE(from1 != vec1); - - // This verifies that absl::Span<T> can be compared freely with - // absl::Span<const T>. - const absl::Span<int> mutable_from1(vec1); - const absl::Span<int> mutable_from2(vec2); - EXPECT_EQ(from1, mutable_from1); - EXPECT_EQ(mutable_from1, from1); - EXPECT_EQ(mutable_from1, mutable_from2); - EXPECT_EQ(mutable_from2, mutable_from1); - - // Comparison between a vector and its slice should be equal for mutable - // Spans as well. - EXPECT_EQ(vec1, mutable_from1); - EXPECT_FALSE(vec1 != mutable_from1); - EXPECT_EQ(mutable_from1, vec1); - EXPECT_FALSE(mutable_from1 != vec1); - - // Comparison between convertible-to-Span-of-const and Span-of-mutable. Arrays - // are used because they're the only value type which converts to a - // Span-of-mutable. EXPECT_TRUE is used instead of EXPECT_EQ to avoid - // array-to-pointer decay. - EXPECT_TRUE(arr1 == mutable_from1); - EXPECT_FALSE(arr1 != mutable_from1); - EXPECT_TRUE(mutable_from1 == arr1); - EXPECT_FALSE(mutable_from1 != arr1); - - // Comparison between convertible-to-Span-of-mutable and Span-of-const - EXPECT_TRUE(arr2 == from1); - EXPECT_FALSE(arr2 != from1); - EXPECT_TRUE(from1 == arr2); - EXPECT_FALSE(from1 != arr2); - - // With a different size, the array slices should not be equal. - EXPECT_NE(from1, absl::Span<const int>(from1).subspan(0, from1.size() - 1)); - - // With different contents, the array slices should not be equal. - ++vec2.back(); - EXPECT_NE(from1, from2); -} - -class IntSpanOrderComparisonTest : public testing::Test { - public: - IntSpanOrderComparisonTest() - : arr_before_{1, 2, 3}, - arr_after_{1, 2, 4}, - carr_after_{1, 2, 4}, - vec_before_(std::begin(arr_before_), std::end(arr_before_)), - vec_after_(std::begin(arr_after_), std::end(arr_after_)), - before_(vec_before_), - after_(vec_after_), - cbefore_(vec_before_), - cafter_(vec_after_) {} - - protected: - int arr_before_[3], arr_after_[3]; - const int carr_after_[3]; - std::vector<int> vec_before_, vec_after_; - absl::Span<int> before_, after_; - absl::Span<const int> cbefore_, cafter_; -}; - -TEST_F(IntSpanOrderComparisonTest, CompareSpans) { - EXPECT_TRUE(cbefore_ < cafter_); - EXPECT_TRUE(cbefore_ <= cafter_); - EXPECT_TRUE(cafter_ > cbefore_); - EXPECT_TRUE(cafter_ >= cbefore_); - - EXPECT_FALSE(cbefore_ > cafter_); - EXPECT_FALSE(cafter_ < cbefore_); - - EXPECT_TRUE(before_ < after_); - EXPECT_TRUE(before_ <= after_); - EXPECT_TRUE(after_ > before_); - EXPECT_TRUE(after_ >= before_); - - EXPECT_FALSE(before_ > after_); - EXPECT_FALSE(after_ < before_); - - EXPECT_TRUE(cbefore_ < after_); - EXPECT_TRUE(cbefore_ <= after_); - EXPECT_TRUE(after_ > cbefore_); - EXPECT_TRUE(after_ >= cbefore_); - - EXPECT_FALSE(cbefore_ > after_); - EXPECT_FALSE(after_ < cbefore_); -} - -TEST_F(IntSpanOrderComparisonTest, SpanOfConstAndContainer) { - EXPECT_TRUE(cbefore_ < vec_after_); - EXPECT_TRUE(cbefore_ <= vec_after_); - EXPECT_TRUE(vec_after_ > cbefore_); - EXPECT_TRUE(vec_after_ >= cbefore_); - - EXPECT_FALSE(cbefore_ > vec_after_); - EXPECT_FALSE(vec_after_ < cbefore_); - - EXPECT_TRUE(arr_before_ < cafter_); - EXPECT_TRUE(arr_before_ <= cafter_); - EXPECT_TRUE(cafter_ > arr_before_); - EXPECT_TRUE(cafter_ >= arr_before_); - - EXPECT_FALSE(arr_before_ > cafter_); - EXPECT_FALSE(cafter_ < arr_before_); -} - -TEST_F(IntSpanOrderComparisonTest, SpanOfMutableAndContainer) { - EXPECT_TRUE(vec_before_ < after_); - EXPECT_TRUE(vec_before_ <= after_); - EXPECT_TRUE(after_ > vec_before_); - EXPECT_TRUE(after_ >= vec_before_); - - EXPECT_FALSE(vec_before_ > after_); - EXPECT_FALSE(after_ < vec_before_); - - EXPECT_TRUE(before_ < carr_after_); - EXPECT_TRUE(before_ <= carr_after_); - EXPECT_TRUE(carr_after_ > before_); - EXPECT_TRUE(carr_after_ >= before_); - - EXPECT_FALSE(before_ > carr_after_); - EXPECT_FALSE(carr_after_ < before_); -} - -TEST_F(IntSpanOrderComparisonTest, EqualSpans) { - EXPECT_FALSE(before_ < before_); - EXPECT_TRUE(before_ <= before_); - EXPECT_FALSE(before_ > before_); - EXPECT_TRUE(before_ >= before_); -} - -TEST_F(IntSpanOrderComparisonTest, Subspans) { - auto subspan = before_.subspan(0, 1); - EXPECT_TRUE(subspan < before_); - EXPECT_TRUE(subspan <= before_); - EXPECT_TRUE(before_ > subspan); - EXPECT_TRUE(before_ >= subspan); - - EXPECT_FALSE(subspan > before_); - EXPECT_FALSE(before_ < subspan); -} - -TEST_F(IntSpanOrderComparisonTest, EmptySpans) { - absl::Span<int> empty; - EXPECT_FALSE(empty < empty); - EXPECT_TRUE(empty <= empty); - EXPECT_FALSE(empty > empty); - EXPECT_TRUE(empty >= empty); - - EXPECT_TRUE(empty < before_); - EXPECT_TRUE(empty <= before_); - EXPECT_TRUE(before_ > empty); - EXPECT_TRUE(before_ >= empty); - - EXPECT_FALSE(empty > before_); - EXPECT_FALSE(before_ < empty); -} - -TEST(IntSpan, ExposesContainerTypesAndConsts) { - absl::Span<int> slice; - CheckType<absl::Span<int>::iterator>(slice.begin()); - EXPECT_TRUE((std::is_convertible<decltype(slice.begin()), - absl::Span<int>::const_iterator>::value)); - CheckType<absl::Span<int>::const_iterator>(slice.cbegin()); - EXPECT_TRUE((std::is_convertible<decltype(slice.end()), - absl::Span<int>::const_iterator>::value)); - CheckType<absl::Span<int>::const_iterator>(slice.cend()); - CheckType<absl::Span<int>::reverse_iterator>(slice.rend()); - EXPECT_TRUE( - (std::is_convertible<decltype(slice.rend()), - absl::Span<int>::const_reverse_iterator>::value)); - CheckType<absl::Span<int>::const_reverse_iterator>(slice.crend()); - testing::StaticAssertTypeEq<int, absl::Span<int>::value_type>(); - testing::StaticAssertTypeEq<int, absl::Span<const int>::value_type>(); - testing::StaticAssertTypeEq<int*, absl::Span<int>::pointer>(); - testing::StaticAssertTypeEq<const int*, absl::Span<const int>::pointer>(); - testing::StaticAssertTypeEq<int&, absl::Span<int>::reference>(); - testing::StaticAssertTypeEq<const int&, absl::Span<const int>::reference>(); - testing::StaticAssertTypeEq<const int&, absl::Span<int>::const_reference>(); - testing::StaticAssertTypeEq<const int&, - absl::Span<const int>::const_reference>(); - EXPECT_EQ(static_cast<absl::Span<int>::size_type>(-1), absl::Span<int>::npos); -} - -TEST(IntSpan, IteratorsAndReferences) { - auto accept_pointer = [](int*) {}; - auto accept_reference = [](int&) {}; - auto accept_iterator = [](absl::Span<int>::iterator) {}; - auto accept_const_iterator = [](absl::Span<int>::const_iterator) {}; - auto accept_reverse_iterator = [](absl::Span<int>::reverse_iterator) {}; - auto accept_const_reverse_iterator = - [](absl::Span<int>::const_reverse_iterator) {}; - - int a[1]; - absl::Span<int> s = a; - - accept_pointer(s.data()); - accept_iterator(s.begin()); - accept_const_iterator(s.begin()); - accept_const_iterator(s.cbegin()); - accept_iterator(s.end()); - accept_const_iterator(s.end()); - accept_const_iterator(s.cend()); - accept_reverse_iterator(s.rbegin()); - accept_const_reverse_iterator(s.rbegin()); - accept_const_reverse_iterator(s.crbegin()); - accept_reverse_iterator(s.rend()); - accept_const_reverse_iterator(s.rend()); - accept_const_reverse_iterator(s.crend()); - - accept_reference(s[0]); - accept_reference(s.at(0)); - accept_reference(s.front()); - accept_reference(s.back()); -} - -TEST(IntSpan, IteratorsAndReferences_Const) { - auto accept_pointer = [](int*) {}; - auto accept_reference = [](int&) {}; - auto accept_iterator = [](absl::Span<int>::iterator) {}; - auto accept_const_iterator = [](absl::Span<int>::const_iterator) {}; - auto accept_reverse_iterator = [](absl::Span<int>::reverse_iterator) {}; - auto accept_const_reverse_iterator = - [](absl::Span<int>::const_reverse_iterator) {}; - - int a[1]; - const absl::Span<int> s = a; - - accept_pointer(s.data()); - accept_iterator(s.begin()); - accept_const_iterator(s.begin()); - accept_const_iterator(s.cbegin()); - accept_iterator(s.end()); - accept_const_iterator(s.end()); - accept_const_iterator(s.cend()); - accept_reverse_iterator(s.rbegin()); - accept_const_reverse_iterator(s.rbegin()); - accept_const_reverse_iterator(s.crbegin()); - accept_reverse_iterator(s.rend()); - accept_const_reverse_iterator(s.rend()); - accept_const_reverse_iterator(s.crend()); - - accept_reference(s[0]); - accept_reference(s.at(0)); - accept_reference(s.front()); - accept_reference(s.back()); -} - -TEST(IntSpan, NoexceptTest) { - int a[] = {1, 2, 3}; - std::vector<int> v; - EXPECT_TRUE(noexcept(absl::Span<const int>())); - EXPECT_TRUE(noexcept(absl::Span<const int>(a, 2))); - EXPECT_TRUE(noexcept(absl::Span<const int>(a))); - EXPECT_TRUE(noexcept(absl::Span<const int>(v))); - EXPECT_TRUE(noexcept(absl::Span<int>(v))); - EXPECT_TRUE(noexcept(absl::Span<const int>({1, 2, 3}))); - EXPECT_TRUE(noexcept(absl::MakeSpan(v))); - EXPECT_TRUE(noexcept(absl::MakeSpan(a))); - EXPECT_TRUE(noexcept(absl::MakeSpan(a, 2))); - EXPECT_TRUE(noexcept(absl::MakeSpan(a, a + 1))); - EXPECT_TRUE(noexcept(absl::MakeConstSpan(v))); - EXPECT_TRUE(noexcept(absl::MakeConstSpan(a))); - EXPECT_TRUE(noexcept(absl::MakeConstSpan(a, 2))); - EXPECT_TRUE(noexcept(absl::MakeConstSpan(a, a + 1))); - - absl::Span<int> s(v); - EXPECT_TRUE(noexcept(s.data())); - EXPECT_TRUE(noexcept(s.size())); - EXPECT_TRUE(noexcept(s.length())); - EXPECT_TRUE(noexcept(s.empty())); - EXPECT_TRUE(noexcept(s[0])); - EXPECT_TRUE(noexcept(s.front())); - EXPECT_TRUE(noexcept(s.back())); - EXPECT_TRUE(noexcept(s.begin())); - EXPECT_TRUE(noexcept(s.cbegin())); - EXPECT_TRUE(noexcept(s.end())); - EXPECT_TRUE(noexcept(s.cend())); - EXPECT_TRUE(noexcept(s.rbegin())); - EXPECT_TRUE(noexcept(s.crbegin())); - EXPECT_TRUE(noexcept(s.rend())); - EXPECT_TRUE(noexcept(s.crend())); - EXPECT_TRUE(noexcept(s.remove_prefix(0))); - EXPECT_TRUE(noexcept(s.remove_suffix(0))); -} - -// ConstexprTester exercises expressions in a constexpr context. Simply placing -// the expression in a constexpr function is not enough, as some compilers will -// simply compile the constexpr function as runtime code. Using template -// parameters forces compile-time execution. -template <int i> -struct ConstexprTester {}; - -#define ABSL_TEST_CONSTEXPR(expr) \ - do { \ - ABSL_ATTRIBUTE_UNUSED ConstexprTester<(expr, 1)> t; \ - } while (0) - -struct ContainerWithConstexprMethods { - constexpr int size() const { return 1; } - constexpr const int* data() const { return &i; } - const int i; -}; - -TEST(ConstIntSpan, ConstexprTest) { - static constexpr int a[] = {1, 2, 3}; - static constexpr int sized_arr[2] = {1, 2}; - static constexpr ContainerWithConstexprMethods c{1}; - ABSL_TEST_CONSTEXPR(absl::Span<const int>()); - ABSL_TEST_CONSTEXPR(absl::Span<const int>(a, 2)); - ABSL_TEST_CONSTEXPR(absl::Span<const int>(sized_arr)); - ABSL_TEST_CONSTEXPR(absl::Span<const int>(c)); - ABSL_TEST_CONSTEXPR(absl::MakeSpan(&a[0], 1)); - ABSL_TEST_CONSTEXPR(absl::MakeSpan(c)); - ABSL_TEST_CONSTEXPR(absl::MakeSpan(a)); - ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(&a[0], 1)); - ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(c)); - ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(a)); - - constexpr absl::Span<const int> span = c; - ABSL_TEST_CONSTEXPR(span.data()); - ABSL_TEST_CONSTEXPR(span.size()); - ABSL_TEST_CONSTEXPR(span.length()); - ABSL_TEST_CONSTEXPR(span.empty()); - ABSL_TEST_CONSTEXPR(span.begin()); - ABSL_TEST_CONSTEXPR(span.cbegin()); - ABSL_TEST_CONSTEXPR(span.subspan(0, 0)); - ABSL_TEST_CONSTEXPR(span.first(1)); - ABSL_TEST_CONSTEXPR(span.last(1)); - ABSL_TEST_CONSTEXPR(span[0]); -} - -struct BigStruct { - char bytes[10000]; -}; - -TEST(Span, SpanSize) { - EXPECT_LE(sizeof(absl::Span<int>), 2 * sizeof(void*)); - EXPECT_LE(sizeof(absl::Span<BigStruct>), 2 * sizeof(void*)); -} - -TEST(Span, Hash) { - int array[] = {1, 2, 3, 4}; - int array2[] = {1, 2, 3}; - using T = absl::Span<const int>; - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - {// Empties - T(), T(nullptr, 0), T(array, 0), T(array2, 0), - // Different array with same value - T(array, 3), T(array2), T({1, 2, 3}), - // Same array, but different length - T(array, 1), T(array, 2), - // Same length, but different array - T(array + 1, 2), T(array + 2, 2)})); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/types/variant.h b/third_party/abseil_cpp/absl/types/variant.h deleted file mode 100644 index ac93464bf8d0..000000000000 --- a/third_party/abseil_cpp/absl/types/variant.h +++ /dev/null @@ -1,866 +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. -// -// ----------------------------------------------------------------------------- -// variant.h -// ----------------------------------------------------------------------------- -// -// This header file defines an `absl::variant` type for holding a type-safe -// value of some prescribed set of types (noted as alternative types), and -// associated functions for managing variants. -// -// The `absl::variant` type is a form of type-safe union. An `absl::variant` -// should always hold a value of one of its alternative types (except in the -// "valueless by exception state" -- see below). A default-constructed -// `absl::variant` will hold the value of its first alternative type, provided -// it is default-constructible. -// -// In exceptional cases due to error, an `absl::variant` can hold no -// value (known as a "valueless by exception" state), though this is not the -// norm. -// -// As with `absl::optional`, an `absl::variant` -- when it holds a value -- -// allocates a value of that type directly within the `variant` itself; it -// cannot hold a reference, array, or the type `void`; it can, however, hold a -// pointer to externally managed memory. -// -// `absl::variant` is a C++11 compatible version of the C++17 `std::variant` -// abstraction and is designed to be a drop-in replacement for code compliant -// with C++17. - -#ifndef ABSL_TYPES_VARIANT_H_ -#define ABSL_TYPES_VARIANT_H_ - -#include "absl/base/config.h" -#include "absl/utility/utility.h" - -#ifdef ABSL_USES_STD_VARIANT - -#include <variant> // IWYU pragma: export - -namespace absl { -ABSL_NAMESPACE_BEGIN -using std::bad_variant_access; -using std::get; -using std::get_if; -using std::holds_alternative; -using std::monostate; -using std::variant; -using std::variant_alternative; -using std::variant_alternative_t; -using std::variant_npos; -using std::variant_size; -using std::variant_size_v; -using std::visit; -ABSL_NAMESPACE_END -} // namespace absl - -#else // ABSL_USES_STD_VARIANT - -#include <functional> -#include <new> -#include <type_traits> -#include <utility> - -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/meta/type_traits.h" -#include "absl/types/internal/variant.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// ----------------------------------------------------------------------------- -// 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. -// -// Example: -// -// // Construct a variant that holds either an integer or a std::string and -// // assign it to a std::string. -// absl::variant<int, std::string> v = std::string("abc"); -// -// // A default-constructed variant will hold a value-initialized value of -// // the first alternative type. -// auto a = absl::variant<int, std::string>(); // Holds an int of value '0'. -// -// // variants are assignable. -// -// // copy assignment -// auto v1 = absl::variant<int, std::string>("abc"); -// auto v2 = absl::variant<int, std::string>(10); -// v2 = v1; // copy assign -// -// // move assignment -// auto v1 = absl::variant<int, std::string>("abc"); -// v1 = absl::variant<int, std::string>(10); -// -// // assignment through type conversion -// a = 128; // variant contains int -// a = "128"; // variant contains std::string -// -// An `absl::variant` holding a value of one of its alternative types `T` holds -// an allocation of `T` directly within the variant itself. An `absl::variant` -// is not allowed to allocate additional storage, such as dynamic memory, to -// allocate the contained value. The contained value shall be allocated in a -// region of the variant storage suitably aligned for all alternative types. -template <typename... Ts> -class variant; - -// swap() -// -// Swaps two `absl::variant` values. This function is equivalent to `v.swap(w)` -// where `v` and `w` are `absl::variant` types. -// -// Note that this function requires all alternative types to be both swappable -// and move-constructible, because any two variants may refer to either the same -// type (in which case, they will be swapped) or to two different types (in -// which case the values will need to be moved). -// -template < - typename... Ts, - absl::enable_if_t< - absl::conjunction<std::is_move_constructible<Ts>..., - type_traits_internal::IsSwappable<Ts>...>::value, - int> = 0> -void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) { - v.swap(w); -} - -// variant_size -// -// 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. -// -// Example: -// -// auto a = absl::variant<int, std::string>; -// constexpr int num_types = -// absl::variant_size<absl::variant<int, std::string>>(); -// -// // You can also use the member constant `value`. -// constexpr int num_types = -// absl::variant_size<absl::variant<int, std::string>>::value; -// -// // `absl::variant_size` is more valuable for use in generic code: -// template <typename Variant> -// constexpr bool IsVariantMultivalue() { -// return absl::variant_size<Variant>() > 1; -// } -// -// Note that the set of cv-qualified specializations of `variant_size` are -// provided to ensure that those specializations compile (especially when passed -// within template logic). -template <class T> -struct variant_size; - -template <class... Ts> -struct variant_size<variant<Ts...>> - : std::integral_constant<std::size_t, sizeof...(Ts)> {}; - -// Specialization of `variant_size` for const qualified variants. -template <class T> -struct variant_size<const T> : variant_size<T>::type {}; - -// Specialization of `variant_size` for volatile qualified variants. -template <class T> -struct variant_size<volatile T> : variant_size<T>::type {}; - -// Specialization of `variant_size` for const volatile qualified variants. -template <class T> -struct variant_size<const volatile T> : variant_size<T>::type {}; - -// variant_alternative -// -// Returns the alternative type for a given `absl::variant` at the passed -// index value as a compile-time constant expression. As this is a class -// template resulting in a type, it is not useful for access of the run-time -// value of any given `absl::variant` variable. -// -// Example: -// -// // The type of the 0th alternative is "int". -// using alternative_type_0 -// = absl::variant_alternative<0, absl::variant<int, std::string>>::type; -// -// static_assert(std::is_same<alternative_type_0, int>::value, ""); -// -// // `absl::variant_alternative` is more valuable for use in generic code: -// template <typename Variant> -// constexpr bool IsFirstElementTrivial() { -// return std::is_trivial_v<variant_alternative<0, Variant>::type>; -// } -// -// Note that the set of cv-qualified specializations of `variant_alternative` -// are provided to ensure that those specializations compile (especially when -// passed within template logic). -template <std::size_t I, class T> -struct variant_alternative; - -template <std::size_t I, class... Types> -struct variant_alternative<I, variant<Types...>> { - using type = - variant_internal::VariantAlternativeSfinaeT<I, variant<Types...>>; -}; - -// Specialization of `variant_alternative` for const qualified variants. -template <std::size_t I, class T> -struct variant_alternative<I, const T> { - using type = const typename variant_alternative<I, T>::type; -}; - -// Specialization of `variant_alternative` for volatile qualified variants. -template <std::size_t I, class T> -struct variant_alternative<I, volatile T> { - using type = volatile typename variant_alternative<I, T>::type; -}; - -// Specialization of `variant_alternative` for const volatile qualified -// variants. -template <std::size_t I, class T> -struct variant_alternative<I, const volatile T> { - using type = const volatile typename variant_alternative<I, T>::type; -}; - -// Template type alias for variant_alternative<I, T>::type. -// -// Example: -// -// using alternative_type_0 -// = absl::variant_alternative_t<0, absl::variant<int, std::string>>; -// static_assert(std::is_same<alternative_type_0, int>::value, ""); -template <std::size_t I, class T> -using variant_alternative_t = typename variant_alternative<I, T>::type; - -// holds_alternative() -// -// Checks whether the given variant currently holds a given alternative type, -// returning `true` if so. -// -// Example: -// -// absl::variant<int, std::string> foo = 42; -// if (absl::holds_alternative<int>(foo)) { -// std::cout << "The variant holds an integer"; -// } -template <class T, class... Types> -constexpr bool holds_alternative(const variant<Types...>& v) noexcept { - static_assert( - variant_internal::UnambiguousIndexOfImpl<variant<Types...>, T, - 0>::value != sizeof...(Types), - "The type T must occur exactly once in Types..."); - return v.index() == - variant_internal::UnambiguousIndexOf<variant<Types...>, T>::value; -} - -// get() -// -// Returns a reference to the value currently within a given variant, using -// either a unique alternative type amongst the variant's set of alternative -// types, or the variant's index value. Attempting to get a variant's value -// using a type that is not unique within the variant's set of alternative types -// is a compile-time error. If the index of the alternative being specified is -// different from the index of the alternative that is currently stored, throws -// `absl::bad_variant_access`. -// -// Example: -// -// auto a = absl::variant<int, std::string>; -// -// // Get the value by type (if unique). -// int i = absl::get<int>(a); -// -// auto b = absl::variant<int, int>; -// -// // Getting the value by a type that is not unique is ill-formed. -// int j = absl::get<int>(b); // Compile Error! -// -// // Getting value by index not ambiguous and allowed. -// int k = absl::get<1>(b); - -// 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::CheckedAccess< - variant_internal::IndexOf<T, Types...>::value>(v); -} - -// Overload for getting a variant's rvalue by type. -// 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::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::CheckedAccess< - variant_internal::IndexOf<T, Types...>::value>(v); -} - -// Overload for getting a variant's const rvalue by type. -// 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::CheckedAccess< - variant_internal::IndexOf<T, Types...>::value>(absl::move(v)); -} - -// Overload for getting a variant's lvalue by index. -template <std::size_t I, class... Types> -constexpr variant_alternative_t<I, variant<Types...>>& get( - variant<Types...>& v) { // NOLINT - return variant_internal::VariantCoreAccess::CheckedAccess<I>(v); -} - -// Overload for getting a variant's rvalue by index. -// Note: `absl::move()` is required to allow use of constexpr in C++11. -template <std::size_t I, class... Types> -constexpr variant_alternative_t<I, variant<Types...>>&& get( - variant<Types...>&& 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::CheckedAccess<I>(v); -} - -// Overload for getting a variant's const rvalue by index. -// Note: `absl::move()` is required to allow use of constexpr in C++11. -template <std::size_t I, class... Types> -constexpr const variant_alternative_t<I, variant<Types...>>&& get( - const variant<Types...>&& v) { - return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::move(v)); -} - -// get_if() -// -// Returns a pointer to the value currently stored within a given variant, if -// present, using either a unique alternative type amongst the variant's set of -// alternative types, or the variant's index value. If such a value does not -// exist, returns `nullptr`. -// -// As with `get`, attempting to get a variant's value using a type that is not -// unique within the variant's set of alternative types is a compile-time error. - -// Overload for getting a pointer to the value stored in the given variant by -// index. -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( - variant_internal::VariantCoreAccess::Access<I>(*v)) - : nullptr; -} - -// Overload for getting a pointer to the const value stored in the given -// variant by index. -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( - variant_internal::VariantCoreAccess::Access<I>(*v)) - : nullptr; -} - -// Overload for getting a pointer to the value stored in the given variant by -// type. -template <class T, class... Types> -constexpr absl::add_pointer_t<T> get_if(variant<Types...>* v) noexcept { - return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v); -} - -// Overload for getting a pointer to the const value stored in the given variant -// by type. -template <class T, class... Types> -constexpr absl::add_pointer_t<const T> get_if( - const variant<Types...>* v) noexcept { - return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v); -} - -// visit() -// -// 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). -// -// The functor must return the same type when called with any of the variants' -// alternatives. -// -// Example: -// -// // Define a visitor functor -// struct GetVariant { -// template<typename T> -// void operator()(const T& i) const { -// std::cout << "The variant's value is: " << i; -// } -// }; -// -// // Declare our variant, and call `absl::visit()` on it. -// // Note that `GetVariant()` returns void in either case. -// absl::variant<int, std::string> foo = std::string("foo"); -// GetVariant visitor; -// 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) { - return variant_internal:: - VisitIndices<variant_size<absl::decay_t<Variants> >::value...>::Run( - variant_internal::PerformVisitation<Visitor, Variants...>{ - std::forward_as_tuple(absl::forward<Variants>(vars)...), - absl::forward<Visitor>(vis)}, - vars.index()...); -} - -// monostate -// -// The monostate class serves as a first alternative type for a variant for -// which the first variant type is otherwise not default-constructible. -struct monostate {}; - -// `absl::monostate` Relational Operators - -constexpr bool operator<(monostate, monostate) noexcept { return false; } -constexpr bool operator>(monostate, monostate) noexcept { return false; } -constexpr bool operator<=(monostate, monostate) noexcept { return true; } -constexpr bool operator>=(monostate, monostate) noexcept { return true; } -constexpr bool operator==(monostate, monostate) noexcept { return true; } -constexpr bool operator!=(monostate, monostate) noexcept { return false; } - - -//------------------------------------------------------------------------------ -// `absl::variant` Template Definition -//------------------------------------------------------------------------------ -template <typename T0, typename... Tn> -class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> { - 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<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 containing a non-nothrow " - "destructible type."); - - friend struct variant_internal::VariantCoreAccess; - - private: - using Base = variant_internal::VariantBase<T0, Tn...>; - - public: - // Constructors - - // Constructs a variant holding a default-initialized value of the first - // alternative type. - constexpr variant() /*noexcept(see 111above)*/ = default; - - // Copy constructor, standard semantics - variant(const variant& other) = default; - - // Move constructor, standard semantics - variant(variant&& other) /*noexcept(see above)*/ = default; - - // Constructs a variant of an alternative type specified by overload - // resolution of the provided forwarding arguments through - // direct-initialization. - // - // Note: If the selected constructor is a constexpr constructor, this - // constructor shall be a constexpr constructor. - // - // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html - // has been voted passed the design phase in the C++ standard meeting in Mar - // 2018. It will be implemented and integrated into `absl::variant`. - template < - class T, - std::size_t I = std::enable_if< - variant_internal::IsNeitherSelfNorInPlace<variant, - absl::decay_t<T>>::value, - variant_internal::IndexOfConstructedType<variant, T>>::type::value, - class Tj = absl::variant_alternative_t<I, variant>, - absl::enable_if_t<std::is_constructible<Tj, T>::value>* = - nullptr> - constexpr variant(T&& t) noexcept(std::is_nothrow_constructible<Tj, T>::value) - : Base(variant_internal::EmplaceTag<I>(), absl::forward<T>(t)) {} - - // Constructs a variant of an alternative type from the arguments through - // direct-initialization. - // - // Note: If the selected constructor is a constexpr constructor, this - // constructor shall be a constexpr constructor. - template <class T, class... Args, - typename std::enable_if<std::is_constructible< - variant_internal::UnambiguousTypeOfT<variant, T>, - Args...>::value>::type* = nullptr> - constexpr explicit variant(in_place_type_t<T>, Args&&... args) - : Base(variant_internal::EmplaceTag< - variant_internal::UnambiguousIndexOf<variant, T>::value>(), - absl::forward<Args>(args)...) {} - - // Constructs a variant of an alternative type from an initializer list - // and other arguments through direct-initialization. - // - // Note: If the selected constructor is a constexpr constructor, this - // constructor shall be a constexpr constructor. - template <class T, class U, class... Args, - typename std::enable_if<std::is_constructible< - variant_internal::UnambiguousTypeOfT<variant, T>, - std::initializer_list<U>&, Args...>::value>::type* = nullptr> - constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il, - Args&&... args) - : Base(variant_internal::EmplaceTag< - variant_internal::UnambiguousIndexOf<variant, T>::value>(), - il, absl::forward<Args>(args)...) {} - - // Constructs a variant of an alternative type from a provided index, - // through value-initialization using the provided forwarded arguments. - template <std::size_t I, class... Args, - typename std::enable_if<std::is_constructible< - variant_internal::VariantAlternativeSfinaeT<I, variant>, - Args...>::value>::type* = nullptr> - constexpr explicit variant(in_place_index_t<I>, Args&&... args) - : Base(variant_internal::EmplaceTag<I>(), absl::forward<Args>(args)...) {} - - // Constructs a variant of an alternative type from a provided index, - // through value-initialization of an initializer list and the provided - // forwarded arguments. - template <std::size_t I, class U, class... Args, - typename std::enable_if<std::is_constructible< - variant_internal::VariantAlternativeSfinaeT<I, variant>, - std::initializer_list<U>&, Args...>::value>::type* = nullptr> - constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il, - Args&&... args) - : Base(variant_internal::EmplaceTag<I>(), il, - absl::forward<Args>(args)...) {} - - // Destructors - - // Destroys the variant's currently contained value, provided that - // `absl::valueless_by_exception()` is false. - ~variant() = default; - - // Assignment Operators - - // Copy assignment operator - variant& operator=(const variant& other) = default; - - // Move assignment operator - variant& operator=(variant&& other) /*noexcept(see above)*/ = default; - - // Converting assignment operator - // - // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html - // has been voted passed the design phase in the C++ standard meeting in Mar - // 2018. It will be implemented and integrated into `absl::variant`. - template < - class T, - std::size_t I = std::enable_if< - !std::is_same<absl::decay_t<T>, variant>::value, - variant_internal::IndexOfConstructedType<variant, T>>::type::value, - class Tj = absl::variant_alternative_t<I, variant>, - typename std::enable_if<std::is_assignable<Tj&, T>::value && - std::is_constructible<Tj, T>::value>::type* = - nullptr> - variant& operator=(T&& t) noexcept( - std::is_nothrow_assignable<Tj&, T>::value&& - std::is_nothrow_constructible<Tj, T>::value) { - variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run( - variant_internal::VariantCoreAccess::MakeConversionAssignVisitor( - this, absl::forward<T>(t)), - index()); - - return *this; - } - - - // emplace() Functions - - // Constructs a value of the given alternative type T within the variant. The - // existing value of the variant is destroyed first (provided that - // `absl::valueless_by_exception()` is false). Requires that T is unambiguous - // in the variant. - // - // Example: - // - // absl::variant<std::vector<int>, int, std::string> v; - // v.emplace<int>(99); - // v.emplace<std::string>("abc"); - template < - class T, class... Args, - typename std::enable_if<std::is_constructible< - absl::variant_alternative_t< - variant_internal::UnambiguousIndexOf<variant, T>::value, variant>, - Args...>::value>::type* = nullptr> - T& emplace(Args&&... args) { - return variant_internal::VariantCoreAccess::Replace< - variant_internal::UnambiguousIndexOf<variant, T>::value>( - this, absl::forward<Args>(args)...); - } - - // Constructs a value of the given alternative type T within the variant using - // an initializer list. The existing value of the variant is destroyed first - // (provided that `absl::valueless_by_exception()` is false). Requires that T - // is unambiguous in the variant. - // - // Example: - // - // absl::variant<std::vector<int>, int, std::string> v; - // v.emplace<std::vector<int>>({0, 1, 2}); - template < - class T, class U, class... Args, - typename std::enable_if<std::is_constructible< - absl::variant_alternative_t< - variant_internal::UnambiguousIndexOf<variant, T>::value, variant>, - std::initializer_list<U>&, Args...>::value>::type* = nullptr> - T& emplace(std::initializer_list<U> il, Args&&... args) { - return variant_internal::VariantCoreAccess::Replace< - variant_internal::UnambiguousIndexOf<variant, T>::value>( - this, il, absl::forward<Args>(args)...); - } - - // Destroys the current value of the variant (provided that - // `absl::valueless_by_exception()` is false) and constructs a new value at - // the given index. - // - // Example: - // - // absl::variant<std::vector<int>, int, int> v; - // v.emplace<1>(99); - // v.emplace<2>(98); - // v.emplace<int>(99); // Won't compile. 'int' isn't a unique type. - template <std::size_t I, class... Args, - typename std::enable_if< - std::is_constructible<absl::variant_alternative_t<I, variant>, - Args...>::value>::type* = nullptr> - absl::variant_alternative_t<I, variant>& emplace(Args&&... args) { - return variant_internal::VariantCoreAccess::Replace<I>( - this, absl::forward<Args>(args)...); - } - - // Destroys the current value of the variant (provided that - // `absl::valueless_by_exception()` is false) and constructs a new value at - // the given index using an initializer list and the provided arguments. - // - // Example: - // - // absl::variant<std::vector<int>, int, int> v; - // v.emplace<0>({0, 1, 2}); - template <std::size_t I, class U, class... Args, - typename std::enable_if<std::is_constructible< - absl::variant_alternative_t<I, variant>, - std::initializer_list<U>&, Args...>::value>::type* = nullptr> - absl::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il, - Args&&... args) { - return variant_internal::VariantCoreAccess::Replace<I>( - this, il, absl::forward<Args>(args)...); - } - - // variant::valueless_by_exception() - // - // Returns false if and only if the variant currently holds a valid value. - constexpr bool valueless_by_exception() const noexcept { - return this->index_ == absl::variant_npos; - } - - // variant::index() - // - // Returns the index value of the variant's currently selected alternative - // type. - constexpr std::size_t index() const noexcept { return this->index_; } - - // variant::swap() - // - // Swaps the values of two variant objects. - // - void swap(variant& rhs) noexcept( - absl::conjunction< - std::is_nothrow_move_constructible<T0>, - std::is_nothrow_move_constructible<Tn>..., - type_traits_internal::IsNothrowSwappable<T0>, - type_traits_internal::IsNothrowSwappable<Tn>...>::value) { - return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run( - variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index()); - } -}; - -// We need a valid declaration of variant<> for SFINAE and overload resolution -// to work properly above, but we don't need a full declaration since this type -// will never be constructed. This declaration, though incomplete, suffices. -template <> -class variant<>; - -//------------------------------------------------------------------------------ -// Relational Operators -//------------------------------------------------------------------------------ -// -// If neither operand is in the `variant::valueless_by_exception` state: -// -// * If the index of both variants is the same, the relational operator -// returns the result of the corresponding relational operator for the -// corresponding alternative type. -// * If the index of both variants is not the same, the relational operator -// returns the result of that operation applied to the value of the left -// operand's index and the value of the right operand's index. -// * If at least one operand is in the valueless_by_exception state: -// - A variant in the valueless_by_exception state is only considered equal -// to another variant in the valueless_by_exception state. -// - If exactly one operand is in the valueless_by_exception state, the -// variant in the valueless_by_exception state is less than the variant -// that is not in the valueless_by_exception state. -// -// Note: The value 1 is added to each index in the relational comparisons such -// that the index corresponding to the valueless_by_exception state wraps around -// to 0 (the lowest value for the index type), and the remaining indices stay in -// the same relative order. - -// Equal-to operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() == b.index()) && - variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::EqualsOp<Types...>{&a, &b}, a.index()); -} - -// Not equal operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) || - variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index()); -} - -// Less-than operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) - ? (a.index() + 1) < (b.index() + 1) - : variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::LessThanOp<Types...>{&a, &b}, a.index()); -} - -// Greater-than operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) - ? (a.index() + 1) > (b.index() + 1) - : variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::GreaterThanOp<Types...>{&a, &b}, - a.index()); -} - -// Less-than or equal-to operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=( - const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) - ? (a.index() + 1) < (b.index() + 1) - : variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::LessThanOrEqualsOp<Types...>{&a, &b}, - a.index()); -} - -// Greater-than or equal-to operator -template <typename... Types> -constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...> -operator>=(const variant<Types...>& a, const variant<Types...>& b) { - return (a.index() != b.index()) - ? (a.index() + 1) > (b.index() + 1) - : variant_internal::VisitIndices<sizeof...(Types)>::Run( - variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b}, - a.index()); -} - -ABSL_NAMESPACE_END -} // namespace absl - -namespace std { - -// hash() -template <> // NOLINT -struct hash<absl::monostate> { - std::size_t operator()(absl::monostate) const { return 0; } -}; - -template <class... T> // NOLINT -struct hash<absl::variant<T...>> - : absl::variant_internal::VariantHashBase<absl::variant<T...>, void, - absl::remove_const_t<T>...> {}; - -} // namespace std - -#endif // ABSL_USES_STD_VARIANT - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace variant_internal { - -// Helper visitor for converting a variant<Ts...>` into another type (mostly -// variant) that can be constructed from any type. -template <typename To> -struct ConversionVisitor { - template <typename T> - To operator()(T&& v) const { - return To(std::forward<T>(v)); - } -}; - -} // namespace variant_internal - -// ConvertVariantTo() -// -// Helper functions to convert an `absl::variant` to a variant of another set of -// types, provided that the alternative type of the new variant type can be -// converted from any type in the source variant. -// -// Example: -// -// absl::variant<name1, name2, float> InternalReq(const Req&); -// -// // name1 and name2 are convertible to name -// absl::variant<name, float> ExternalReq(const Req& req) { -// return absl::ConvertVariantTo<absl::variant<name, float>>( -// InternalReq(req)); -// } -template <typename To, typename Variant> -To ConvertVariantTo(Variant&& variant) { - return absl::visit(variant_internal::ConversionVisitor<To>{}, - std::forward<Variant>(variant)); -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_TYPES_VARIANT_H_ diff --git a/third_party/abseil_cpp/absl/types/variant_benchmark.cc b/third_party/abseil_cpp/absl/types/variant_benchmark.cc deleted file mode 100644 index 350b17536413..000000000000 --- a/third_party/abseil_cpp/absl/types/variant_benchmark.cc +++ /dev/null @@ -1,222 +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. - -// Unit tests for the variant template. The 'is' and 'IsEmpty' methods -// of variant are not explicitly tested because they are used repeatedly -// in building other tests. All other public variant methods should have -// explicit tests. - -#include "absl/types/variant.h" - -#include <cstddef> -#include <cstdlib> -#include <string> -#include <tuple> - -#include "benchmark/benchmark.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -template <std::size_t I> -struct VariantAlternative { - char member; -}; - -template <class Indices> -struct VariantOfAlternativesImpl; - -template <std::size_t... Indices> -struct VariantOfAlternativesImpl<absl::index_sequence<Indices...>> { - using type = absl::variant<VariantAlternative<Indices>...>; -}; - -template <std::size_t NumAlternatives> -using VariantOfAlternatives = typename VariantOfAlternativesImpl< - absl::make_index_sequence<NumAlternatives>>::type; - -struct Empty {}; - -template <class... T> -void Ignore(T...) noexcept {} - -template <class T> -Empty DoNotOptimizeAndReturnEmpty(T&& arg) noexcept { - benchmark::DoNotOptimize(arg); - return {}; -} - -struct VisitorApplier { - struct Visitor { - template <class... T> - void operator()(T&&... args) const noexcept { - Ignore(DoNotOptimizeAndReturnEmpty(args)...); - } - }; - - template <class... Vars> - void operator()(const Vars&... vars) const noexcept { - absl::visit(Visitor(), vars...); - } -}; - -template <std::size_t NumIndices, std::size_t CurrIndex = NumIndices - 1> -struct MakeWithIndex { - using Variant = VariantOfAlternatives<NumIndices>; - - static Variant Run(std::size_t index) { - return index == CurrIndex - ? Variant(absl::in_place_index_t<CurrIndex>()) - : MakeWithIndex<NumIndices, CurrIndex - 1>::Run(index); - } -}; - -template <std::size_t NumIndices> -struct MakeWithIndex<NumIndices, 0> { - using Variant = VariantOfAlternatives<NumIndices>; - - static Variant Run(std::size_t /*index*/) { return Variant(); } -}; - -template <std::size_t NumIndices, class Dimensions> -struct MakeVariantTuple; - -template <class T, std::size_t /*I*/> -using always_t = T; - -template <std::size_t NumIndices> -VariantOfAlternatives<NumIndices> MakeVariant(std::size_t dimension, - std::size_t index) { - return dimension == 0 - ? MakeWithIndex<NumIndices>::Run(index % NumIndices) - : MakeVariant<NumIndices>(dimension - 1, index / NumIndices); -} - -template <std::size_t NumIndices, std::size_t... Dimensions> -struct MakeVariantTuple<NumIndices, absl::index_sequence<Dimensions...>> { - using VariantTuple = - std::tuple<always_t<VariantOfAlternatives<NumIndices>, Dimensions>...>; - - static VariantTuple Run(int index) { - return std::make_tuple(MakeVariant<NumIndices>(Dimensions, index)...); - } -}; - -constexpr std::size_t integral_pow(std::size_t base, std::size_t power) { - return power == 0 ? 1 : base * integral_pow(base, power - 1); -} - -template <std::size_t End, std::size_t I = 0> -struct VisitTestBody { - template <class Vars, class State> - static bool Run(Vars& vars, State& state) { - if (state.KeepRunning()) { - absl::apply(VisitorApplier(), vars[I]); - return VisitTestBody<End, I + 1>::Run(vars, state); - } - return false; - } -}; - -template <std::size_t End> -struct VisitTestBody<End, End> { - template <class Vars, class State> - static bool Run(Vars& /*vars*/, State& /*state*/) { - return true; - } -}; - -// Visit operations where branch prediction is likely to give a boost. -template <std::size_t NumIndices, std::size_t NumDimensions = 1> -void BM_RedundantVisit(benchmark::State& state) { - auto vars = - MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>:: - Run(static_cast<std::size_t>(state.range(0))); - - for (auto _ : state) { // NOLINT - benchmark::DoNotOptimize(vars); - absl::apply(VisitorApplier(), vars); - } -} - -// Visit operations where branch prediction is unlikely to give a boost. -template <std::size_t NumIndices, std::size_t NumDimensions = 1> -void BM_Visit(benchmark::State& state) { - constexpr std::size_t num_possibilities = - integral_pow(NumIndices, NumDimensions); - - using VariantTupleMaker = - MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>; - using Tuple = typename VariantTupleMaker::VariantTuple; - - Tuple vars[num_possibilities]; - for (std::size_t i = 0; i < num_possibilities; ++i) - vars[i] = VariantTupleMaker::Run(i); - - while (VisitTestBody<num_possibilities>::Run(vars, state)) { - } -} - -// Visitation -// Each visit is on a different variant with a different active alternative) - -// Unary visit -BENCHMARK_TEMPLATE(BM_Visit, 1); -BENCHMARK_TEMPLATE(BM_Visit, 2); -BENCHMARK_TEMPLATE(BM_Visit, 3); -BENCHMARK_TEMPLATE(BM_Visit, 4); -BENCHMARK_TEMPLATE(BM_Visit, 5); -BENCHMARK_TEMPLATE(BM_Visit, 6); -BENCHMARK_TEMPLATE(BM_Visit, 7); -BENCHMARK_TEMPLATE(BM_Visit, 8); -BENCHMARK_TEMPLATE(BM_Visit, 16); -BENCHMARK_TEMPLATE(BM_Visit, 32); -BENCHMARK_TEMPLATE(BM_Visit, 64); - -// Binary visit -BENCHMARK_TEMPLATE(BM_Visit, 1, 2); -BENCHMARK_TEMPLATE(BM_Visit, 2, 2); -BENCHMARK_TEMPLATE(BM_Visit, 3, 2); -BENCHMARK_TEMPLATE(BM_Visit, 4, 2); -BENCHMARK_TEMPLATE(BM_Visit, 5, 2); - -// Ternary visit -BENCHMARK_TEMPLATE(BM_Visit, 1, 3); -BENCHMARK_TEMPLATE(BM_Visit, 2, 3); -BENCHMARK_TEMPLATE(BM_Visit, 3, 3); - -// Quaternary visit -BENCHMARK_TEMPLATE(BM_Visit, 1, 4); -BENCHMARK_TEMPLATE(BM_Visit, 2, 4); - -// Redundant Visitation -// Each visit consistently has the same alternative active - -// Unary visit -BENCHMARK_TEMPLATE(BM_RedundantVisit, 1)->Arg(0); -BENCHMARK_TEMPLATE(BM_RedundantVisit, 2)->DenseRange(0, 1); -BENCHMARK_TEMPLATE(BM_RedundantVisit, 8)->DenseRange(0, 7); - -// Binary visit -BENCHMARK_TEMPLATE(BM_RedundantVisit, 1, 2)->Arg(0); -BENCHMARK_TEMPLATE(BM_RedundantVisit, 2, 2) - ->DenseRange(0, integral_pow(2, 2) - 1); -BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2) - ->DenseRange(0, integral_pow(4, 2) - 1); - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/types/variant_exception_safety_test.cc b/third_party/abseil_cpp/absl/types/variant_exception_safety_test.cc deleted file mode 100644 index 439c6e1df367..000000000000 --- a/third_party/abseil_cpp/absl/types/variant_exception_safety_test.cc +++ /dev/null @@ -1,532 +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/variant.h" - -#include "absl/base/config.h" - -// This test is a no-op when absl::variant is an alias for std::variant and when -// exceptions are not enabled. -#if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS) - -#include <iostream> -#include <memory> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.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 { -ABSL_NAMESPACE_BEGIN -namespace { - -using ::testing::MakeExceptionSafetyTester; -using ::testing::strong_guarantee; -using ::testing::TestNothrowOp; -using ::testing::TestThrowingCtor; - -using Thrower = testing::ThrowingValue<>; -using CopyNothrow = testing::ThrowingValue<testing::TypeSpec::kNoThrowCopy>; -using MoveNothrow = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>; -using ThrowingAlloc = testing::ThrowingAllocator<Thrower>; -using ThrowerVec = std::vector<Thrower, ThrowingAlloc>; -using ThrowingVariant = - absl::variant<Thrower, CopyNothrow, MoveNothrow, ThrowerVec>; - -struct ConversionException {}; - -template <class T> -struct ExceptionOnConversion { - operator T() const { // NOLINT - throw ConversionException(); - } -}; - -// Forces a variant into the valueless by exception state. -void ToValuelessByException(ThrowingVariant& v) { // NOLINT - try { - v.emplace<Thrower>(); - v.emplace<Thrower>(ExceptionOnConversion<Thrower>()); - } catch (const ConversionException&) { - // This space intentionally left blank. - } -} - -// Check that variant is still in a usable state after an exception is thrown. -testing::AssertionResult VariantInvariants(ThrowingVariant* v) { - using testing::AssertionFailure; - using testing::AssertionSuccess; - - // Try using the active alternative - if (absl::holds_alternative<Thrower>(*v)) { - auto& t = absl::get<Thrower>(*v); - t = Thrower{-100}; - if (t.Get() != -100) { - return AssertionFailure() << "Thrower should be assigned -100"; - } - } else if (absl::holds_alternative<ThrowerVec>(*v)) { - auto& tv = absl::get<ThrowerVec>(*v); - tv.clear(); - tv.emplace_back(-100); - if (tv.size() != 1 || tv[0].Get() != -100) { - return AssertionFailure() << "ThrowerVec should be {Thrower{-100}}"; - } - } else if (absl::holds_alternative<CopyNothrow>(*v)) { - auto& t = absl::get<CopyNothrow>(*v); - t = CopyNothrow{-100}; - if (t.Get() != -100) { - return AssertionFailure() << "CopyNothrow should be assigned -100"; - } - } else if (absl::holds_alternative<MoveNothrow>(*v)) { - auto& t = absl::get<MoveNothrow>(*v); - t = MoveNothrow{-100}; - if (t.Get() != -100) { - return AssertionFailure() << "MoveNothrow should be assigned -100"; - } - } - - // Try making variant valueless_by_exception - if (!v->valueless_by_exception()) ToValuelessByException(*v); - if (!v->valueless_by_exception()) { - return AssertionFailure() << "Variant should be valueless_by_exception"; - } - try { - auto unused = absl::get<Thrower>(*v); - static_cast<void>(unused); - return AssertionFailure() << "Variant should not contain Thrower"; - } catch (const absl::bad_variant_access&) { - } catch (...) { - return AssertionFailure() << "Unexpected exception throw from absl::get"; - } - - // Try using the variant - v->emplace<Thrower>(100); - if (!absl::holds_alternative<Thrower>(*v) || - absl::get<Thrower>(*v) != Thrower(100)) { - return AssertionFailure() << "Variant should contain Thrower(100)"; - } - v->emplace<ThrowerVec>({Thrower(100)}); - if (!absl::holds_alternative<ThrowerVec>(*v) || - absl::get<ThrowerVec>(*v)[0] != Thrower(100)) { - return AssertionFailure() - << "Variant should contain ThrowerVec{Thrower(100)}"; - } - return AssertionSuccess(); -} - -template <typename... Args> -Thrower ExpectedThrower(Args&&... args) { - return Thrower(42, args...); -} - -ThrowerVec ExpectedThrowerVec() { return {Thrower(100), Thrower(200)}; } -ThrowingVariant ValuelessByException() { - ThrowingVariant v; - ToValuelessByException(v); - return v; -} -ThrowingVariant WithThrower() { return Thrower(39); } -ThrowingVariant WithThrowerVec() { - return ThrowerVec{Thrower(1), Thrower(2), Thrower(3)}; -} -ThrowingVariant WithCopyNoThrow() { return CopyNothrow(39); } -ThrowingVariant WithMoveNoThrow() { return MoveNothrow(39); } - -TEST(VariantExceptionSafetyTest, DefaultConstructor) { - TestThrowingCtor<ThrowingVariant>(); -} - -TEST(VariantExceptionSafetyTest, CopyConstructor) { - { - ThrowingVariant v(ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(v); - } - { - ThrowingVariant v(ExpectedThrowerVec()); - TestThrowingCtor<ThrowingVariant>(v); - } - { - ThrowingVariant v(ValuelessByException()); - TestThrowingCtor<ThrowingVariant>(v); - } -} - -TEST(VariantExceptionSafetyTest, MoveConstructor) { - { - ThrowingVariant v(ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(std::move(v)); - } - { - ThrowingVariant v(ExpectedThrowerVec()); - TestThrowingCtor<ThrowingVariant>(std::move(v)); - } - { - ThrowingVariant v(ValuelessByException()); - TestThrowingCtor<ThrowingVariant>(std::move(v)); - } -} - -TEST(VariantExceptionSafetyTest, ValueConstructor) { - TestThrowingCtor<ThrowingVariant>(ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(ExpectedThrowerVec()); -} - -TEST(VariantExceptionSafetyTest, InPlaceTypeConstructor) { - TestThrowingCtor<ThrowingVariant>(absl::in_place_type_t<Thrower>{}, - ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(absl::in_place_type_t<ThrowerVec>{}, - ExpectedThrowerVec()); -} - -TEST(VariantExceptionSafetyTest, InPlaceIndexConstructor) { - TestThrowingCtor<ThrowingVariant>(absl::in_place_index_t<0>{}, - ExpectedThrower()); - TestThrowingCtor<ThrowingVariant>(absl::in_place_index_t<3>{}, - ExpectedThrowerVec()); -} - -TEST(VariantExceptionSafetyTest, CopyAssign) { - // variant& operator=(const variant& rhs); - // Let j be rhs.index() - { - // - neither *this nor rhs holds a value - const ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = ValuelessByException(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; })); - } - { - // - *this holds a value but rhs does not - const ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; })); - } - // - index() == j - { - const ThrowingVariant rhs(ExpectedThrower()); - auto tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } - { - const ThrowingVariant rhs(ExpectedThrowerVec()); - auto tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithThrowerVec()) - .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } - // libstdc++ std::variant has bugs on copy assignment regarding exception - // safety. -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - // index() != j - // if is_nothrow_copy_constructible_v<Tj> or - // !is_nothrow_move_constructible<Tj> is true, equivalent to - // emplace<j>(get<j>(rhs)) - { - // is_nothrow_copy_constructible_v<Tj> == true - // should not throw because emplace() invokes Tj's copy ctor - // which should not throw. - const ThrowingVariant rhs(CopyNothrow{}); - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; })); - } - { - // is_nothrow_copy_constructible<Tj> == false && - // is_nothrow_move_constructible<Tj> == false - // should provide basic guarantee because emplace() invokes Tj's copy ctor - // which may throw. - const ThrowingVariant rhs(ExpectedThrower()); - auto tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } -#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - { - // is_nothrow_copy_constructible_v<Tj> == false && - // is_nothrow_move_constructible_v<Tj> == true - // should provide strong guarantee because it is equivalent to - // operator=(variant(rhs)) which creates a temporary then invoke the move - // ctor which shouldn't throw. - const ThrowingVariant rhs(MoveNothrow{}); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithContracts(VariantInvariants, strong_guarantee) - .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; })); - } -} - -TEST(VariantExceptionSafetyTest, MoveAssign) { - // variant& operator=(variant&& rhs); - // Let j be rhs.index() - { - // - neither *this nor rhs holds a value - ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = ValuelessByException(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); })); - } - { - // - *this holds a value but rhs does not - ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); })); - } - { - // - index() == j - // assign get<j>(std::move(rhs)) to the value contained in *this. - // If an exception is thrown during call to Tj's move assignment, the state - // of the contained value is as defined by the exception safety guarantee of - // Tj's move assignment; index() will be j. - ThrowingVariant rhs(ExpectedThrower()); - size_t j = rhs.index(); - // Since Thrower's move assignment has basic guarantee, so should variant's. - auto tester = MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([&](ThrowingVariant* lhs) { - auto copy = rhs; - *lhs = std::move(copy); - }); - EXPECT_TRUE(tester - .WithContracts( - VariantInvariants, - [&](ThrowingVariant* lhs) { return lhs->index() == j; }) - .Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } - { - // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06. - // The fix is targeted for gcc-9. - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 - // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614 -#if !(defined(ABSL_USES_STD_VARIANT) && \ - defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) - // - otherwise (index() != j), equivalent to - // emplace<j>(get<j>(std::move(rhs))) - // - If an exception is thrown during the call to Tj's move construction - // (with j being rhs.index()), the variant will hold no value. - ThrowingVariant rhs(CopyNothrow{}); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) - .Test([&](ThrowingVariant* lhs) { - auto copy = rhs; - *lhs = std::move(copy); - })); -#endif // !(defined(ABSL_USES_STD_VARIANT) && - // defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) - } -} - -TEST(VariantExceptionSafetyTest, ValueAssign) { - // template<class T> variant& operator=(T&& t); - // Let Tj be the type that is selected by overload resolution to be assigned. - { - // If *this holds a Tj, assigns std::forward<T>(t) to the value contained in - // *this. If an exception is thrown during the assignment of - // std::forward<T>(t) to the value contained in *this, the state of the - // contained value and t are as defined by the exception safety guarantee of - // the assignment expression; valueless_by_exception() will be false. - // Since Thrower's copy/move assignment has basic guarantee, so should - // variant's. - Thrower rhs = ExpectedThrower(); - // copy assign - auto copy_tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(copy_tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return !lhs->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(copy_tester.WithContracts(strong_guarantee).Test()); - // move assign - auto move_tester = MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([&](ThrowingVariant* lhs) { - auto copy = rhs; - *lhs = std::move(copy); - }); - EXPECT_TRUE(move_tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return !lhs->valueless_by_exception(); - }) - .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 - // emplace<j>(std::forward<T>(t)). - // We simplify the test by letting T = `const Tj&` or `Tj&&`, so we can reuse - // the CopyNothrow and MoveNothrow types. - - // if is_nothrow_constructible_v<Tj, T> - // (i.e. is_nothrow_copy/move_constructible_v<Tj>) is true, emplace() just - // invokes the copy/move constructor and it should not throw. - { - const CopyNothrow rhs; - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; })); - } - { - MoveNothrow rhs; - ThrowingVariant lhs = WithThrower(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); })); - } - // if is_nothrow_constructible_v<Tj, T> == false && - // is_nothrow_move_constructible<Tj> == false - // emplace() invokes the copy/move constructor which may throw so it should - // provide basic guarantee and variant object might not hold a value. - { - Thrower rhs = ExpectedThrower(); - // copy - auto copy_tester = - MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }); - EXPECT_TRUE(copy_tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(copy_tester.WithContracts(strong_guarantee).Test()); - // move - auto move_tester = MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithOperation([](ThrowingVariant* lhs) { - *lhs = ExpectedThrower(testing::nothrow_ctor); - }); - EXPECT_TRUE(move_tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* lhs) { - return lhs->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(move_tester.WithContracts(strong_guarantee).Test()); - } - // Otherwise (if is_nothrow_constructible_v<Tj, T> == false && - // is_nothrow_move_constructible<Tj> == true), - // equivalent to operator=(variant(std::forward<T>(t))) - // This should have strong guarantee because it creates a temporary variant - // and operator=(variant&&) invokes Tj's move ctor which doesn't throw. - // libstdc++ std::variant has bugs on conversion assignment regarding - // exception safety. -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - { - MoveNothrow rhs; - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithContracts(VariantInvariants, strong_guarantee) - .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; })); - } -#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) -} - -TEST(VariantExceptionSafetyTest, Emplace) { - // If an exception during the initialization of the contained value, the - // variant might not hold a value. The standard requires emplace() to provide - // only basic guarantee. - { - Thrower args = ExpectedThrower(); - auto tester = MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithOperation([&args](ThrowingVariant* v) { - v->emplace<Thrower>(args); - }); - EXPECT_TRUE(tester - .WithContracts(VariantInvariants, - [](ThrowingVariant* v) { - return v->valueless_by_exception(); - }) - .Test()); - EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); - } -} - -TEST(VariantExceptionSafetyTest, Swap) { - // if both are valueless_by_exception(), no effect - { - ThrowingVariant rhs = ValuelessByException(); - ThrowingVariant lhs = ValuelessByException(); - EXPECT_TRUE(TestNothrowOp([&]() { lhs.swap(rhs); })); - } - // if index() == rhs.index(), calls swap(get<i>(*this), get<i>(rhs)) - // where i is index(). - { - ThrowingVariant rhs = ExpectedThrower(); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithThrower()) - .WithContracts(VariantInvariants) - .Test([&](ThrowingVariant* lhs) { - auto copy = rhs; - lhs->swap(copy); - })); - } - // Otherwise, exchanges the value of rhs and *this. The exception safety - // involves variant in moved-from state which is not specified in the - // standard, and since swap is 3-step it's impossible for it to provide a - // overall strong guarantee. So, we are only checking basic guarantee here. - { - ThrowingVariant rhs = ExpectedThrower(); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithContracts(VariantInvariants) - .Test([&](ThrowingVariant* lhs) { - auto copy = rhs; - lhs->swap(copy); - })); - } - { - ThrowingVariant rhs = ExpectedThrower(); - EXPECT_TRUE(MakeExceptionSafetyTester() - .WithInitialValue(WithCopyNoThrow()) - .WithContracts(VariantInvariants) - .Test([&](ThrowingVariant* lhs) { - auto copy = rhs; - copy.swap(*lhs); - })); - } -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl - -#endif // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) - -#endif // #if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS) diff --git a/third_party/abseil_cpp/absl/types/variant_test.cc b/third_party/abseil_cpp/absl/types/variant_test.cc deleted file mode 100644 index cf237334da02..000000000000 --- a/third_party/abseil_cpp/absl/types/variant_test.cc +++ /dev/null @@ -1,2718 +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. - -// Unit tests for the variant template. The 'is' and 'IsEmpty' methods -// of variant are not explicitly tested because they are used repeatedly -// in building other tests. All other public variant methods should have -// explicit tests. - -#include "absl/types/variant.h" - -// This test is a no-op when absl::variant is an alias for std::variant. -#if !defined(ABSL_USES_STD_VARIANT) - -#include <algorithm> -#include <cstddef> -#include <functional> -#include <initializer_list> -#include <memory> -#include <ostream> -#include <queue> -#include <type_traits> -#include <unordered_set> -#include <utility> -#include <vector> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/config.h" -#include "absl/base/port.h" -#include "absl/memory/memory.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/string_view.h" - -#ifdef ABSL_HAVE_EXCEPTIONS - -#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \ - EXPECT_THROW(expr, exception_t) - -#else - -#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \ - EXPECT_DEATH_IF_SUPPORTED(expr, text) - -#endif // ABSL_HAVE_EXCEPTIONS - -#define ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(...) \ - ABSL_VARIANT_TEST_EXPECT_FAIL((void)(__VA_ARGS__), absl::bad_variant_access, \ - "Bad variant access") - -struct Hashable {}; - -namespace std { -template <> -struct hash<Hashable> { - size_t operator()(const Hashable&); -}; -} // namespace std - -struct NonHashable {}; - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -using ::testing::DoubleEq; -using ::testing::Pointee; -using ::testing::VariantWith; - -struct MoveCanThrow { - MoveCanThrow() : v(0) {} - MoveCanThrow(int v) : v(v) {} // NOLINT(runtime/explicit) - MoveCanThrow(const MoveCanThrow& other) : v(other.v) {} - MoveCanThrow& operator=(const MoveCanThrow& /*other*/) { return *this; } - int v; -}; - -bool operator==(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v == rhs.v; } -bool operator!=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v != rhs.v; } -bool operator<(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v < rhs.v; } -bool operator<=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v <= rhs.v; } -bool operator>=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v >= rhs.v; } -bool operator>(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v > rhs.v; } - -// This helper class allows us to determine if it was swapped with std::swap() -// or with its friend swap() function. -struct SpecialSwap { - explicit SpecialSwap(int i) : i(i) {} - friend void swap(SpecialSwap& a, SpecialSwap& b) { - a.special_swap = b.special_swap = true; - std::swap(a.i, b.i); - } - bool operator==(SpecialSwap other) const { return i == other.i; } - int i; - bool special_swap = false; -}; - -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; -}; - -#ifdef ABSL_HAVE_EXCEPTIONS - -struct ConversionException {}; - -template <class T> -struct ExceptionOnConversion { - operator T() const { // NOLINT(runtime/explicit) - throw ConversionException(); - } -}; - -// Forces a variant into the valueless by exception state. -template <class H, class... T> -void ToValuelessByException(absl::variant<H, T...>& v) { // NOLINT - try { - v.template emplace<0>(ExceptionOnConversion<H>()); - } catch (ConversionException& /*e*/) { - // This space intentionally left blank. - } -} - -#endif // ABSL_HAVE_EXCEPTIONS - -// An indexed sequence of distinct structures holding a single -// value of type T -template<typename T, size_t N> -struct ValueHolder { - explicit ValueHolder(const T& x) : value(x) {} - typedef T value_type; - value_type value; - static const size_t kIndex = N; -}; -template<typename T, size_t N> -const size_t ValueHolder<T, N>::kIndex; - -// The following three functions make ValueHolder compatible with -// EXPECT_EQ and EXPECT_NE -template<typename T, size_t N> -inline bool operator==(const ValueHolder<T, N>& left, - const ValueHolder<T, N>& right) { - return left.value == right.value; -} - -template<typename T, size_t N> -inline bool operator!=(const ValueHolder<T, N>& left, - const ValueHolder<T, N>& right) { - return left.value != right.value; -} - -template<typename T, size_t N> -inline std::ostream& operator<<( - std::ostream& stream, const ValueHolder<T, N>& object) { - return stream << object.value; -} - -// Makes a variant holding twelve uniquely typed T wrappers. -template<typename T> -struct VariantFactory { - typedef variant<ValueHolder<T, 1>, ValueHolder<T, 2>, ValueHolder<T, 3>, - ValueHolder<T, 4>> - Type; -}; - -// A typelist in 1:1 with VariantFactory, to use type driven unit tests. -typedef ::testing::Types<ValueHolder<size_t, 1>, ValueHolder<size_t, 2>, - ValueHolder<size_t, 3>, - ValueHolder<size_t, 4>> VariantTypes; - -// Increments the provided counter pointer in the destructor -struct IncrementInDtor { - explicit IncrementInDtor(int* counter) : counter(counter) {} - ~IncrementInDtor() { *counter += 1; } - int* counter; -}; - -struct IncrementInDtorCopyCanThrow { - explicit IncrementInDtorCopyCanThrow(int* counter) : counter(counter) {} - IncrementInDtorCopyCanThrow(IncrementInDtorCopyCanThrow&& other) noexcept = - default; - IncrementInDtorCopyCanThrow(const IncrementInDtorCopyCanThrow& other) - : counter(other.counter) {} - IncrementInDtorCopyCanThrow& operator=( - IncrementInDtorCopyCanThrow&&) noexcept = default; - IncrementInDtorCopyCanThrow& operator=( - IncrementInDtorCopyCanThrow const& other) { - counter = other.counter; - return *this; - } - ~IncrementInDtorCopyCanThrow() { *counter += 1; } - int* counter; -}; - -// This is defined so operator== for ValueHolder<IncrementInDtor> will -// return true if two IncrementInDtor objects increment the same -// counter -inline bool operator==(const IncrementInDtor& left, - const IncrementInDtor& right) { - return left.counter == right.counter; -} - -// This is defined so EXPECT_EQ can work with IncrementInDtor -inline std::ostream& operator<<( - std::ostream& stream, const IncrementInDtor& object) { - return stream << object.counter; -} - -// A class that can be copied, but not assigned. -class CopyNoAssign { - public: - explicit CopyNoAssign(int value) : foo(value) {} - CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {} - int foo; - private: - const CopyNoAssign& operator=(const CopyNoAssign&); -}; - -// A class that can neither be copied nor assigned. We provide -// overloads for the constructor with up to four parameters so we can -// test the overloads of variant::emplace. -class NonCopyable { - public: - NonCopyable() - : value(0) {} - explicit NonCopyable(int value1) - : value(value1) {} - - NonCopyable(int value1, int value2) - : value(value1 + value2) {} - - NonCopyable(int value1, int value2, int value3) - : value(value1 + value2 + value3) {} - - NonCopyable(int value1, int value2, int value3, int value4) - : value(value1 + value2 + value3 + value4) {} - NonCopyable(const NonCopyable&) = delete; - NonCopyable& operator=(const NonCopyable&) = delete; - int value; -}; - -// A typed test and typed test case over the VariantTypes typelist, -// from which we derive a number of tests that will execute for one of -// each type. -template <typename T> -class VariantTypesTest : public ::testing::Test {}; -TYPED_TEST_SUITE(VariantTypesTest, VariantTypes); - -//////////////////// -// [variant.ctor] // -//////////////////// - -struct NonNoexceptDefaultConstructible { - NonNoexceptDefaultConstructible() {} - int value = 5; -}; - -struct NonDefaultConstructible { - NonDefaultConstructible() = delete; -}; - -TEST(VariantTest, TestDefaultConstructor) { - { - using X = variant<int>; - constexpr variant<int> x{}; - ASSERT_FALSE(x.valueless_by_exception()); - ASSERT_EQ(0, x.index()); - EXPECT_EQ(0, absl::get<0>(x)); - EXPECT_TRUE(std::is_nothrow_default_constructible<X>::value); - } - - { - using X = variant<NonNoexceptDefaultConstructible>; - X x{}; - ASSERT_FALSE(x.valueless_by_exception()); - ASSERT_EQ(0, x.index()); - EXPECT_EQ(5, absl::get<0>(x).value); - EXPECT_FALSE(std::is_nothrow_default_constructible<X>::value); - } - - { - using X = variant<int, NonNoexceptDefaultConstructible>; - X x{}; - ASSERT_FALSE(x.valueless_by_exception()); - ASSERT_EQ(0, x.index()); - EXPECT_EQ(0, absl::get<0>(x)); - EXPECT_TRUE(std::is_nothrow_default_constructible<X>::value); - } - - { - using X = variant<NonNoexceptDefaultConstructible, int>; - X x{}; - ASSERT_FALSE(x.valueless_by_exception()); - ASSERT_EQ(0, x.index()); - EXPECT_EQ(5, absl::get<0>(x).value); - EXPECT_FALSE(std::is_nothrow_default_constructible<X>::value); - } - EXPECT_FALSE( - std::is_default_constructible<variant<NonDefaultConstructible>>::value); - EXPECT_FALSE((std::is_default_constructible< - variant<NonDefaultConstructible, int>>::value)); - EXPECT_TRUE((std::is_default_constructible< - variant<int, NonDefaultConstructible>>::value)); -} - -// Test that for each slot, copy constructing a variant with that type -// produces a sensible object that correctly reports its type, and -// that copies the provided value. -TYPED_TEST(VariantTypesTest, TestCopyCtor) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - const TypeParam value(TypeParam::kIndex); - Variant original(value); - Variant copied(original); - EXPECT_TRUE(absl::holds_alternative<value_type1>(copied) || - TypeParam::kIndex != 1); - EXPECT_TRUE(absl::holds_alternative<value_type2>(copied) || - TypeParam::kIndex != 2); - EXPECT_TRUE(absl::holds_alternative<value_type3>(copied) || - TypeParam::kIndex != 3); - EXPECT_TRUE(absl::holds_alternative<value_type4>(copied) || - TypeParam::kIndex != 4); - EXPECT_TRUE((absl::get_if<value_type1>(&original) == - absl::get_if<value_type1>(&copied)) || - TypeParam::kIndex == 1); - EXPECT_TRUE((absl::get_if<value_type2>(&original) == - absl::get_if<value_type2>(&copied)) || - TypeParam::kIndex == 2); - EXPECT_TRUE((absl::get_if<value_type3>(&original) == - absl::get_if<value_type3>(&copied)) || - TypeParam::kIndex == 3); - EXPECT_TRUE((absl::get_if<value_type4>(&original) == - absl::get_if<value_type4>(&copied)) || - TypeParam::kIndex == 4); - EXPECT_TRUE((absl::get_if<value_type1>(&original) == - absl::get_if<value_type1>(&copied)) || - TypeParam::kIndex == 1); - EXPECT_TRUE((absl::get_if<value_type2>(&original) == - absl::get_if<value_type2>(&copied)) || - TypeParam::kIndex == 2); - EXPECT_TRUE((absl::get_if<value_type3>(&original) == - absl::get_if<value_type3>(&copied)) || - TypeParam::kIndex == 3); - EXPECT_TRUE((absl::get_if<value_type4>(&original) == - absl::get_if<value_type4>(&copied)) || - TypeParam::kIndex == 4); - const TypeParam* ovalptr = absl::get_if<TypeParam>(&original); - const TypeParam* cvalptr = absl::get_if<TypeParam>(&copied); - ASSERT_TRUE(ovalptr != nullptr); - ASSERT_TRUE(cvalptr != nullptr); - EXPECT_EQ(*ovalptr, *cvalptr); - TypeParam* mutable_ovalptr = absl::get_if<TypeParam>(&original); - TypeParam* mutable_cvalptr = absl::get_if<TypeParam>(&copied); - ASSERT_TRUE(mutable_ovalptr != nullptr); - ASSERT_TRUE(mutable_cvalptr != nullptr); - EXPECT_EQ(*mutable_ovalptr, *mutable_cvalptr); -} - -template <class> -struct MoveOnly { - MoveOnly() = default; - explicit MoveOnly(int value) : value(value) {} - MoveOnly(MoveOnly&&) = default; - MoveOnly& operator=(MoveOnly&&) = default; - int value = 5; -}; - -TEST(VariantTest, TestMoveConstruct) { - using V = variant<MoveOnly<class A>, MoveOnly<class B>, MoveOnly<class C>>; - - V v(in_place_index<1>, 10); - V v2 = absl::move(v); - EXPECT_EQ(10, absl::get<1>(v2).value); -} - -// Used internally to emulate missing triviality traits for tests. -template <class T> -union SingleUnion { - T member; -}; - -// NOTE: These don't work with types that can't be union members. -// They are just for testing. -template <class T> -struct is_trivially_move_constructible - : std::is_move_constructible<SingleUnion<T>>::type {}; - -template <class T> -struct is_trivially_move_assignable - : absl::is_move_assignable<SingleUnion<T>>::type {}; - -TEST(VariantTest, NothrowMoveConstructible) { - // Verify that variant is nothrow move constructible iff its template - // arguments are. - using U = std::unique_ptr<int>; - struct E { - E(E&&) {} - }; - static_assert(std::is_nothrow_move_constructible<variant<U>>::value, ""); - static_assert(std::is_nothrow_move_constructible<variant<U, int>>::value, ""); - static_assert(!std::is_nothrow_move_constructible<variant<U, E>>::value, ""); -} - -// Test that for each slot, constructing a variant with that type -// produces a sensible object that correctly reports its type, and -// that copies the provided value. -TYPED_TEST(VariantTypesTest, TestValueCtor) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - const TypeParam value(TypeParam::kIndex); - Variant v(value); - EXPECT_TRUE(absl::holds_alternative<value_type1>(v) || - TypeParam::kIndex != 1); - EXPECT_TRUE(absl::holds_alternative<value_type2>(v) || - TypeParam::kIndex != 2); - EXPECT_TRUE(absl::holds_alternative<value_type3>(v) || - TypeParam::kIndex != 3); - EXPECT_TRUE(absl::holds_alternative<value_type4>(v) || - TypeParam::kIndex != 4); - EXPECT_TRUE(nullptr != absl::get_if<value_type1>(&v) || - TypeParam::kIndex != 1); - EXPECT_TRUE(nullptr != absl::get_if<value_type2>(&v) || - TypeParam::kIndex != 2); - EXPECT_TRUE(nullptr != absl::get_if<value_type3>(&v) || - TypeParam::kIndex != 3); - EXPECT_TRUE(nullptr != absl::get_if<value_type4>(&v) || - TypeParam::kIndex != 4); - EXPECT_TRUE(nullptr != absl::get_if<value_type1>(&v) || - TypeParam::kIndex != 1); - EXPECT_TRUE(nullptr != absl::get_if<value_type2>(&v) || - TypeParam::kIndex != 2); - EXPECT_TRUE(nullptr != absl::get_if<value_type3>(&v) || - TypeParam::kIndex != 3); - EXPECT_TRUE(nullptr != absl::get_if<value_type4>(&v) || - TypeParam::kIndex != 4); - const TypeParam* valptr = absl::get_if<TypeParam>(&v); - ASSERT_TRUE(nullptr != valptr); - EXPECT_EQ(value.value, valptr->value); - const TypeParam* mutable_valptr = absl::get_if<TypeParam>(&v); - ASSERT_TRUE(nullptr != mutable_valptr); - EXPECT_EQ(value.value, mutable_valptr->value); -} - -TEST(VariantTest, AmbiguousValueConstructor) { - EXPECT_FALSE((std::is_convertible<int, absl::variant<int, int>>::value)); - EXPECT_FALSE((std::is_constructible<absl::variant<int, int>, int>::value)); -} - -TEST(VariantTest, InPlaceType) { - using Var = variant<int, std::string, NonCopyable, std::vector<int>>; - - Var v1(in_place_type_t<int>(), 7); - ASSERT_TRUE(absl::holds_alternative<int>(v1)); - EXPECT_EQ(7, absl::get<int>(v1)); - - Var v2(in_place_type_t<std::string>(), "ABC"); - ASSERT_TRUE(absl::holds_alternative<std::string>(v2)); - EXPECT_EQ("ABC", absl::get<std::string>(v2)); - - Var v3(in_place_type_t<std::string>(), "ABC", 2); - ASSERT_TRUE(absl::holds_alternative<std::string>(v3)); - EXPECT_EQ("AB", absl::get<std::string>(v3)); - - Var v4(in_place_type_t<NonCopyable>{}); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4)); - - Var v5(in_place_type_t<std::vector<int>>(), {1, 2, 3}); - ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5)); - EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3)); -} - -TEST(VariantTest, InPlaceTypeVariableTemplate) { - using Var = variant<int, std::string, NonCopyable, std::vector<int>>; - - Var v1(in_place_type<int>, 7); - ASSERT_TRUE(absl::holds_alternative<int>(v1)); - EXPECT_EQ(7, absl::get<int>(v1)); - - Var v2(in_place_type<std::string>, "ABC"); - ASSERT_TRUE(absl::holds_alternative<std::string>(v2)); - EXPECT_EQ("ABC", absl::get<std::string>(v2)); - - Var v3(in_place_type<std::string>, "ABC", 2); - ASSERT_TRUE(absl::holds_alternative<std::string>(v3)); - EXPECT_EQ("AB", absl::get<std::string>(v3)); - - Var v4(in_place_type<NonCopyable>); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4)); - - Var v5(in_place_type<std::vector<int>>, {1, 2, 3}); - ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5)); - EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3)); -} - -TEST(VariantTest, InPlaceTypeInitializerList) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(in_place_type_t<MoveOnlyWithListConstructor>(), {1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); -} - -TEST(VariantTest, InPlaceTypeInitializerListVariabletemplate) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(in_place_type<MoveOnlyWithListConstructor>, {1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); -} - -TEST(VariantTest, InPlaceIndex) { - using Var = variant<int, std::string, NonCopyable, std::vector<int>>; - - Var v1(in_place_index_t<0>(), 7); - ASSERT_TRUE(absl::holds_alternative<int>(v1)); - EXPECT_EQ(7, absl::get<int>(v1)); - - Var v2(in_place_index_t<1>(), "ABC"); - ASSERT_TRUE(absl::holds_alternative<std::string>(v2)); - EXPECT_EQ("ABC", absl::get<std::string>(v2)); - - Var v3(in_place_index_t<1>(), "ABC", 2); - ASSERT_TRUE(absl::holds_alternative<std::string>(v3)); - EXPECT_EQ("AB", absl::get<std::string>(v3)); - - Var v4(in_place_index_t<2>{}); - EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4)); - - // Verify that a variant with only non-copyables can still be constructed. - EXPECT_TRUE(absl::holds_alternative<NonCopyable>( - variant<NonCopyable>(in_place_index_t<0>{}))); - - Var v5(in_place_index_t<3>(), {1, 2, 3}); - ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5)); - EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3)); -} - -TEST(VariantTest, InPlaceIndexVariableTemplate) { - using Var = variant<int, std::string, NonCopyable, std::vector<int>>; - - Var v1(in_place_index<0>, 7); - ASSERT_TRUE(absl::holds_alternative<int>(v1)); - EXPECT_EQ(7, absl::get<int>(v1)); - - Var v2(in_place_index<1>, "ABC"); - ASSERT_TRUE(absl::holds_alternative<std::string>(v2)); - EXPECT_EQ("ABC", absl::get<std::string>(v2)); - - Var v3(in_place_index<1>, "ABC", 2); - ASSERT_TRUE(absl::holds_alternative<std::string>(v3)); - EXPECT_EQ("AB", absl::get<std::string>(v3)); - - Var v4(in_place_index<2>); - EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4)); - - // Verify that a variant with only non-copyables can still be constructed. - EXPECT_TRUE(absl::holds_alternative<NonCopyable>( - variant<NonCopyable>(in_place_index<0>))); - - Var v5(in_place_index<3>, {1, 2, 3}); - ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5)); - EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3)); -} - -TEST(VariantTest, InPlaceIndexInitializerList) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(in_place_index_t<3>(), {1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); -} - -TEST(VariantTest, InPlaceIndexInitializerListVariableTemplate) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(in_place_index<3>, {1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); -} - -//////////////////// -// [variant.dtor] // -//////////////////// - -// Make sure that the destructor destroys the contained value -TEST(VariantTest, TestDtor) { - typedef VariantFactory<IncrementInDtor>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - int counter = 0; - IncrementInDtor counter_adjuster(&counter); - EXPECT_EQ(0, counter); - - value_type1 value1(counter_adjuster); - { Variant object(value1); } - EXPECT_EQ(1, counter); - - value_type2 value2(counter_adjuster); - { Variant object(value2); } - EXPECT_EQ(2, counter); - - value_type3 value3(counter_adjuster); - { Variant object(value3); } - EXPECT_EQ(3, counter); - - value_type4 value4(counter_adjuster); - { Variant object(value4); } - EXPECT_EQ(4, counter); -} - -#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) -#endif -{ - int counter = 0; - IncrementInDtor counter_adjuster(&counter); - - { - using Variant = VariantFactory<IncrementInDtor>::Type; - - Variant v(in_place_index<0>, counter_adjuster); - EXPECT_EQ(0, counter); - - ToValuelessByException(v); - ASSERT_TRUE(v.valueless_by_exception()); - EXPECT_EQ(1, counter); - } - EXPECT_EQ(1, counter); -} - -#endif // ABSL_HAVE_EXCEPTIONS - -////////////////////// -// [variant.assign] // -////////////////////// - -// Test that self-assignment doesn't destroy the current value -TEST(VariantTest, TestSelfAssignment) { - typedef VariantFactory<IncrementInDtor>::Type Variant; - int counter = 0; - IncrementInDtor counter_adjuster(&counter); - absl::variant_alternative_t<0, Variant> value(counter_adjuster); - Variant object(value); - object.operator=(object); - EXPECT_EQ(0, counter); - - // A string long enough that it's likely to defeat any inline representation - // optimization. - const std::string long_str(128, 'a'); - - std::string foo = long_str; - foo = *&foo; - EXPECT_EQ(long_str, foo); - - variant<int, std::string> so = long_str; - ASSERT_EQ(1, so.index()); - EXPECT_EQ(long_str, absl::get<1>(so)); - so = *&so; - - ASSERT_EQ(1, so.index()); - EXPECT_EQ(long_str, absl::get<1>(so)); -} - -// Test that assigning a variant<..., T, ...> to a variant<..., T, ...> produces -// a variant<..., T, ...> with the correct value. -TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValueSameTypes) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - const TypeParam value(TypeParam::kIndex); - const Variant source(value); - Variant target(TypeParam(value.value + 1)); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(source)); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(target)); - ASSERT_NE(absl::get<TypeParam>(source), absl::get<TypeParam>(target)); - target = source; - ASSERT_TRUE(absl::holds_alternative<TypeParam>(source)); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(target)); - EXPECT_EQ(absl::get<TypeParam>(source), absl::get<TypeParam>(target)); -} - -// Test that assisnging a variant<..., T, ...> to a variant<1, ...> -// produces a variant<..., T, ...> with the correct value. -TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValuesVaryingSourceType) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - const TypeParam value(TypeParam::kIndex); - const Variant source(value); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(source)); - Variant target(value_type1(1)); - ASSERT_TRUE(absl::holds_alternative<value_type1>(target)); - target = source; - EXPECT_TRUE(absl::holds_alternative<TypeParam>(source)); - EXPECT_TRUE(absl::holds_alternative<TypeParam>(target)); - EXPECT_EQ(absl::get<TypeParam>(source), absl::get<TypeParam>(target)); -} - -// Test that assigning a variant<1, ...> to a variant<..., T, ...> -// produces a variant<1, ...> with the correct value. -TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValuesVaryingTargetType) { - typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - const Variant source(value_type1(1)); - ASSERT_TRUE(absl::holds_alternative<value_type1>(source)); - const TypeParam value(TypeParam::kIndex); - Variant target(value); - ASSERT_TRUE(absl::holds_alternative<TypeParam>(target)); - target = source; - EXPECT_TRUE(absl::holds_alternative<value_type1>(target)); - EXPECT_TRUE(absl::holds_alternative<value_type1>(source)); - EXPECT_EQ(absl::get<value_type1>(source), absl::get<value_type1>(target)); -} - -// Test that operator=<T> works, that assigning a new value destroys -// the old and that assigning the new value again does not redestroy -// the old -TEST(VariantTest, TestAssign) { - typedef VariantFactory<IncrementInDtor>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - - const int kSize = 4; - int counter[kSize]; - std::unique_ptr<IncrementInDtor> counter_adjustor[kSize]; - for (int i = 0; i != kSize; i++) { - counter[i] = 0; - counter_adjustor[i] = absl::make_unique<IncrementInDtor>(&counter[i]); - } - - value_type1 v1(*counter_adjustor[0]); - value_type2 v2(*counter_adjustor[1]); - value_type3 v3(*counter_adjustor[2]); - value_type4 v4(*counter_adjustor[3]); - - // Test that reassignment causes destruction of old value - { - Variant object(v1); - object = v2; - object = v3; - object = v4; - object = v1; - } - - EXPECT_EQ(2, counter[0]); - EXPECT_EQ(1, counter[1]); - EXPECT_EQ(1, counter[2]); - EXPECT_EQ(1, counter[3]); - - std::fill(std::begin(counter), std::end(counter), 0); - - // Test that self-assignment does not cause destruction of old value - { - Variant object(v1); - object.operator=(object); - EXPECT_EQ(0, counter[0]); - } - { - Variant object(v2); - object.operator=(object); - EXPECT_EQ(0, counter[1]); - } - { - Variant object(v3); - object.operator=(object); - EXPECT_EQ(0, counter[2]); - } - { - Variant object(v4); - object.operator=(object); - EXPECT_EQ(0, counter[3]); - } - - EXPECT_EQ(1, counter[0]); - EXPECT_EQ(1, counter[1]); - EXPECT_EQ(1, counter[2]); - EXPECT_EQ(1, counter[3]); -} - -// This tests that we perform a backup if the copy-assign can throw but the move -// cannot throw. -TEST(VariantTest, TestBackupAssign) { - typedef VariantFactory<IncrementInDtorCopyCanThrow>::Type Variant; - using value_type1 = absl::variant_alternative_t<0, Variant>; - using value_type2 = absl::variant_alternative_t<1, Variant>; - using value_type3 = absl::variant_alternative_t<2, Variant>; - using value_type4 = absl::variant_alternative_t<3, Variant>; - - const int kSize = 4; - int counter[kSize]; - std::unique_ptr<IncrementInDtorCopyCanThrow> counter_adjustor[kSize]; - for (int i = 0; i != kSize; i++) { - counter[i] = 0; - counter_adjustor[i].reset(new IncrementInDtorCopyCanThrow(&counter[i])); - } - - value_type1 v1(*counter_adjustor[0]); - value_type2 v2(*counter_adjustor[1]); - value_type3 v3(*counter_adjustor[2]); - value_type4 v4(*counter_adjustor[3]); - - // Test that reassignment causes destruction of old value - { - Variant object(v1); - object = v2; - object = v3; - object = v4; - object = v1; - } - - // libstdc++ doesn't pass this test -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - EXPECT_EQ(3, counter[0]); - EXPECT_EQ(2, counter[1]); - EXPECT_EQ(2, counter[2]); - EXPECT_EQ(2, counter[3]); -#endif - - std::fill(std::begin(counter), std::end(counter), 0); - - // Test that self-assignment does not cause destruction of old value - { - Variant object(v1); - object.operator=(object); - EXPECT_EQ(0, counter[0]); - } - { - Variant object(v2); - object.operator=(object); - EXPECT_EQ(0, counter[1]); - } - { - Variant object(v3); - object.operator=(object); - EXPECT_EQ(0, counter[2]); - } - { - Variant object(v4); - object.operator=(object); - EXPECT_EQ(0, counter[3]); - } - - EXPECT_EQ(1, counter[0]); - EXPECT_EQ(1, counter[1]); - EXPECT_EQ(1, counter[2]); - EXPECT_EQ(1, counter[3]); -} - -/////////////////// -// [variant.mod] // -/////////////////// - -TEST(VariantTest, TestEmplaceBasic) { - using Variant = variant<int, char>; - - Variant v(absl::in_place_index<0>, 0); - - { - char& emplace_result = v.emplace<char>(); - ASSERT_TRUE(absl::holds_alternative<char>(v)); - EXPECT_EQ(absl::get<char>(v), 0); - EXPECT_EQ(&emplace_result, &absl::get<char>(v)); - } - - // Make sure that another emplace does zero-initialization - absl::get<char>(v) = 'a'; - v.emplace<char>('b'); - ASSERT_TRUE(absl::holds_alternative<char>(v)); - EXPECT_EQ(absl::get<char>(v), 'b'); - - { - int& emplace_result = v.emplace<int>(); - EXPECT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_EQ(absl::get<int>(v), 0); - EXPECT_EQ(&emplace_result, &absl::get<int>(v)); - } -} - -TEST(VariantTest, TestEmplaceInitializerList) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(absl::in_place_index<0>, 555); - MoveOnlyWithListConstructor& emplace_result = - v1.emplace<MoveOnlyWithListConstructor>({1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); - EXPECT_EQ(&emplace_result, &absl::get<MoveOnlyWithListConstructor>(v1)); -} - -TEST(VariantTest, TestEmplaceIndex) { - using Variant = variant<int, char>; - - Variant v(absl::in_place_index<0>, 555); - - { - char& emplace_result = v.emplace<1>(); - ASSERT_TRUE(absl::holds_alternative<char>(v)); - EXPECT_EQ(absl::get<char>(v), 0); - EXPECT_EQ(&emplace_result, &absl::get<char>(v)); - } - - // Make sure that another emplace does zero-initialization - absl::get<char>(v) = 'a'; - v.emplace<1>('b'); - ASSERT_TRUE(absl::holds_alternative<char>(v)); - EXPECT_EQ(absl::get<char>(v), 'b'); - - { - int& emplace_result = v.emplace<0>(); - EXPECT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_EQ(absl::get<int>(v), 0); - EXPECT_EQ(&emplace_result, &absl::get<int>(v)); - } -} - -TEST(VariantTest, TestEmplaceIndexInitializerList) { - using Var = - variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>; - - Var v1(absl::in_place_index<0>, 555); - MoveOnlyWithListConstructor& emplace_result = - v1.emplace<3>({1, 2, 3, 4, 5}, 6); - ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1)); - EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value); - EXPECT_EQ(&emplace_result, &absl::get<MoveOnlyWithListConstructor>(v1)); -} - -////////////////////// -// [variant.status] // -////////////////////// - -TEST(VariantTest, Index) { - using Var = variant<int, std::string, double>; - - Var v = 1; - EXPECT_EQ(0, v.index()); - v = "str"; - EXPECT_EQ(1, v.index()); - v = 0.; - EXPECT_EQ(2, v.index()); - - Var v2 = v; - EXPECT_EQ(2, v2.index()); - v2.emplace<int>(3); - EXPECT_EQ(0, v2.index()); -} - -TEST(VariantTest, NotValuelessByException) { - using Var = variant<int, std::string, double>; - - Var v = 1; - EXPECT_FALSE(v.valueless_by_exception()); - v = "str"; - EXPECT_FALSE(v.valueless_by_exception()); - v = 0.; - EXPECT_FALSE(v.valueless_by_exception()); - - Var v2 = v; - EXPECT_FALSE(v.valueless_by_exception()); - v2.emplace<int>(3); - EXPECT_FALSE(v.valueless_by_exception()); -} - -#ifdef ABSL_HAVE_EXCEPTIONS - -TEST(VariantTest, IndexValuelessByException) { - using Var = variant<MoveCanThrow, std::string, double>; - - Var v(absl::in_place_index<0>); - EXPECT_EQ(0, v.index()); - ToValuelessByException(v); - EXPECT_EQ(absl::variant_npos, v.index()); - v = "str"; - EXPECT_EQ(1, v.index()); -} - -TEST(VariantTest, ValuelessByException) { - using Var = variant<MoveCanThrow, std::string, double>; - - Var v(absl::in_place_index<0>); - EXPECT_FALSE(v.valueless_by_exception()); - ToValuelessByException(v); - EXPECT_TRUE(v.valueless_by_exception()); - v = "str"; - EXPECT_FALSE(v.valueless_by_exception()); -} - -#endif // ABSL_HAVE_EXCEPTIONS - -//////////////////// -// [variant.swap] // -//////////////////// - -TEST(VariantTest, MemberSwap) { - SpecialSwap v1(3); - SpecialSwap v2(7); - - variant<SpecialSwap> a = v1, b = v2; - - EXPECT_THAT(a, VariantWith<SpecialSwap>(v1)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v2)); - - a.swap(b); - EXPECT_THAT(a, VariantWith<SpecialSwap>(v2)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v1)); - EXPECT_TRUE(absl::get<SpecialSwap>(a).special_swap); - - using V = variant<MoveCanThrow, std::string, int>; - int i = 33; - std::string s = "abc"; - { - // lhs and rhs holds different alternative - V lhs(i), rhs(s); - lhs.swap(rhs); - EXPECT_THAT(lhs, VariantWith<std::string>(s)); - EXPECT_THAT(rhs, VariantWith<int>(i)); - } -#ifdef ABSL_HAVE_EXCEPTIONS - V valueless(in_place_index<0>); - ToValuelessByException(valueless); - { - // lhs is valueless - V lhs(valueless), rhs(i); - lhs.swap(rhs); - EXPECT_THAT(lhs, VariantWith<int>(i)); - EXPECT_TRUE(rhs.valueless_by_exception()); - } - { - // rhs is valueless - V lhs(s), rhs(valueless); - lhs.swap(rhs); - EXPECT_THAT(rhs, VariantWith<std::string>(s)); - EXPECT_TRUE(lhs.valueless_by_exception()); - } - { - // both are valueless - V lhs(valueless), rhs(valueless); - lhs.swap(rhs); - EXPECT_TRUE(lhs.valueless_by_exception()); - EXPECT_TRUE(rhs.valueless_by_exception()); - } -#endif // ABSL_HAVE_EXCEPTIONS -} - -////////////////////// -// [variant.helper] // -////////////////////// - -TEST(VariantTest, VariantSize) { - { - using Size1Variant = absl::variant<int>; - EXPECT_EQ(1, absl::variant_size<Size1Variant>::value); - EXPECT_EQ(1, absl::variant_size<const Size1Variant>::value); - EXPECT_EQ(1, absl::variant_size<volatile Size1Variant>::value); - EXPECT_EQ(1, absl::variant_size<const volatile Size1Variant>::value); - } - - { - using Size3Variant = absl::variant<int, float, int>; - EXPECT_EQ(3, absl::variant_size<Size3Variant>::value); - EXPECT_EQ(3, absl::variant_size<const Size3Variant>::value); - EXPECT_EQ(3, absl::variant_size<volatile Size3Variant>::value); - EXPECT_EQ(3, absl::variant_size<const volatile Size3Variant>::value); - } -} - -TEST(VariantTest, VariantAlternative) { - { - using V = absl::variant<float, int, const char*>; - EXPECT_TRUE( - (std::is_same<float, absl::variant_alternative_t<0, V>>::value)); - EXPECT_TRUE((std::is_same<const float, - absl::variant_alternative_t<0, const V>>::value)); - EXPECT_TRUE( - (std::is_same<volatile float, - absl::variant_alternative_t<0, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const volatile float, - absl::variant_alternative_t<0, const volatile V>>::value)); - - EXPECT_TRUE((std::is_same<int, absl::variant_alternative_t<1, V>>::value)); - EXPECT_TRUE((std::is_same<const int, - absl::variant_alternative_t<1, const V>>::value)); - EXPECT_TRUE( - (std::is_same<volatile int, - absl::variant_alternative_t<1, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const volatile int, - absl::variant_alternative_t<1, const volatile V>>::value)); - - EXPECT_TRUE( - (std::is_same<const char*, absl::variant_alternative_t<2, V>>::value)); - EXPECT_TRUE((std::is_same<const char* const, - absl::variant_alternative_t<2, const V>>::value)); - EXPECT_TRUE( - (std::is_same<const char* volatile, - absl::variant_alternative_t<2, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const char* const volatile, - absl::variant_alternative_t<2, const volatile V>>::value)); - } - - { - using V = absl::variant<float, volatile int, const char*>; - EXPECT_TRUE( - (std::is_same<float, absl::variant_alternative_t<0, V>>::value)); - EXPECT_TRUE((std::is_same<const float, - absl::variant_alternative_t<0, const V>>::value)); - EXPECT_TRUE( - (std::is_same<volatile float, - absl::variant_alternative_t<0, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const volatile float, - absl::variant_alternative_t<0, const volatile V>>::value)); - - EXPECT_TRUE( - (std::is_same<volatile int, absl::variant_alternative_t<1, V>>::value)); - EXPECT_TRUE((std::is_same<const volatile int, - absl::variant_alternative_t<1, const V>>::value)); - EXPECT_TRUE( - (std::is_same<volatile int, - absl::variant_alternative_t<1, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const volatile int, - absl::variant_alternative_t<1, const volatile V>>::value)); - - EXPECT_TRUE( - (std::is_same<const char*, absl::variant_alternative_t<2, V>>::value)); - EXPECT_TRUE((std::is_same<const char* const, - absl::variant_alternative_t<2, const V>>::value)); - EXPECT_TRUE( - (std::is_same<const char* volatile, - absl::variant_alternative_t<2, volatile V>>::value)); - EXPECT_TRUE(( - std::is_same<const char* const volatile, - absl::variant_alternative_t<2, const volatile V>>::value)); - } -} - -/////////////////// -// [variant.get] // -/////////////////// - -TEST(VariantTest, HoldsAlternative) { - using Var = variant<int, std::string, double>; - - Var v = 1; - EXPECT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_FALSE(absl::holds_alternative<std::string>(v)); - EXPECT_FALSE(absl::holds_alternative<double>(v)); - v = "str"; - EXPECT_FALSE(absl::holds_alternative<int>(v)); - EXPECT_TRUE(absl::holds_alternative<std::string>(v)); - EXPECT_FALSE(absl::holds_alternative<double>(v)); - v = 0.; - EXPECT_FALSE(absl::holds_alternative<int>(v)); - EXPECT_FALSE(absl::holds_alternative<std::string>(v)); - EXPECT_TRUE(absl::holds_alternative<double>(v)); - - Var v2 = v; - EXPECT_FALSE(absl::holds_alternative<int>(v2)); - EXPECT_FALSE(absl::holds_alternative<std::string>(v2)); - EXPECT_TRUE(absl::holds_alternative<double>(v2)); - v2.emplace<int>(3); - EXPECT_TRUE(absl::holds_alternative<int>(v2)); - EXPECT_FALSE(absl::holds_alternative<std::string>(v2)); - EXPECT_FALSE(absl::holds_alternative<double>(v2)); -} - -TEST(VariantTest, GetIndex) { - using Var = variant<int, std::string, double, int>; - - { - Var v(absl::in_place_index<0>, 0); - - using LValueGetType = decltype(absl::get<0>(v)); - using RValueGetType = decltype(absl::get<0>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, int&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value)); - EXPECT_EQ(absl::get<0>(v), 0); - EXPECT_EQ(absl::get<0>(absl::move(v)), 0); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<0>(const_v)); - using ConstRValueGetType = decltype(absl::get<0>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value)); - EXPECT_EQ(absl::get<0>(const_v), 0); - EXPECT_EQ(absl::get<0>(absl::move(const_v)), 0); - } - - { - Var v = std::string("Hello"); - - using LValueGetType = decltype(absl::get<1>(v)); - using RValueGetType = decltype(absl::get<1>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, std::string&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, std::string&&>::value)); - EXPECT_EQ(absl::get<1>(v), "Hello"); - EXPECT_EQ(absl::get<1>(absl::move(v)), "Hello"); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<1>(const_v)); - using ConstRValueGetType = decltype(absl::get<1>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const std::string&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const std::string&&>::value)); - EXPECT_EQ(absl::get<1>(const_v), "Hello"); - EXPECT_EQ(absl::get<1>(absl::move(const_v)), "Hello"); - } - - { - Var v = 2.0; - - using LValueGetType = decltype(absl::get<2>(v)); - using RValueGetType = decltype(absl::get<2>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, double&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, double&&>::value)); - EXPECT_EQ(absl::get<2>(v), 2.); - EXPECT_EQ(absl::get<2>(absl::move(v)), 2.); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<2>(const_v)); - using ConstRValueGetType = decltype(absl::get<2>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const double&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const double&&>::value)); - EXPECT_EQ(absl::get<2>(const_v), 2.); - EXPECT_EQ(absl::get<2>(absl::move(const_v)), 2.); - } - - { - Var v(absl::in_place_index<0>, 0); - v.emplace<3>(1); - - using LValueGetType = decltype(absl::get<3>(v)); - using RValueGetType = decltype(absl::get<3>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, int&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value)); - EXPECT_EQ(absl::get<3>(v), 1); - EXPECT_EQ(absl::get<3>(absl::move(v)), 1); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<3>(const_v)); - using ConstRValueGetType = decltype(absl::get<3>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value)); - EXPECT_EQ(absl::get<3>(const_v), 1); - EXPECT_EQ(absl::get<3>(absl::move(const_v)), 1); // NOLINT - } -} - -TEST(VariantTest, BadGetIndex) { - using Var = variant<int, std::string, double>; - - { - Var v = 1; - - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(std::move(v))); - - const Var& const_v = v; - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(const_v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<1>(std::move(const_v))); // NOLINT - } - - { - Var v = std::string("Hello"); - - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(std::move(v))); - - const Var& const_v = v; - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(const_v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<0>(std::move(const_v))); // NOLINT - } -} - -TEST(VariantTest, GetType) { - using Var = variant<int, std::string, double>; - - { - Var v = 1; - - using LValueGetType = decltype(absl::get<int>(v)); - using RValueGetType = decltype(absl::get<int>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, int&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value)); - EXPECT_EQ(absl::get<int>(v), 1); - EXPECT_EQ(absl::get<int>(absl::move(v)), 1); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<int>(const_v)); - using ConstRValueGetType = decltype(absl::get<int>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value)); - EXPECT_EQ(absl::get<int>(const_v), 1); - EXPECT_EQ(absl::get<int>(absl::move(const_v)), 1); - } - - { - Var v = std::string("Hello"); - - using LValueGetType = decltype(absl::get<1>(v)); - using RValueGetType = decltype(absl::get<1>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, std::string&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, std::string&&>::value)); - EXPECT_EQ(absl::get<std::string>(v), "Hello"); - EXPECT_EQ(absl::get<std::string>(absl::move(v)), "Hello"); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<1>(const_v)); - using ConstRValueGetType = decltype(absl::get<1>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const std::string&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const std::string&&>::value)); - EXPECT_EQ(absl::get<std::string>(const_v), "Hello"); - EXPECT_EQ(absl::get<std::string>(absl::move(const_v)), "Hello"); - } - - { - Var v = 2.0; - - using LValueGetType = decltype(absl::get<2>(v)); - using RValueGetType = decltype(absl::get<2>(absl::move(v))); - - EXPECT_TRUE((std::is_same<LValueGetType, double&>::value)); - EXPECT_TRUE((std::is_same<RValueGetType, double&&>::value)); - EXPECT_EQ(absl::get<double>(v), 2.); - EXPECT_EQ(absl::get<double>(absl::move(v)), 2.); - - const Var& const_v = v; - using ConstLValueGetType = decltype(absl::get<2>(const_v)); - using ConstRValueGetType = decltype(absl::get<2>(absl::move(const_v))); - EXPECT_TRUE((std::is_same<ConstLValueGetType, const double&>::value)); - EXPECT_TRUE((std::is_same<ConstRValueGetType, const double&&>::value)); - EXPECT_EQ(absl::get<double>(const_v), 2.); - EXPECT_EQ(absl::get<double>(absl::move(const_v)), 2.); - } -} - -TEST(VariantTest, BadGetType) { - using Var = variant<int, std::string, double>; - - { - Var v = 1; - - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<std::string>(std::move(v))); - - const Var& const_v = v; - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<std::string>(const_v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<std::string>(std::move(const_v))); // NOLINT - } - - { - Var v = std::string("Hello"); - - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(std::move(v))); - - const Var& const_v = v; - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(const_v)); - ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS( - absl::get<int>(std::move(const_v))); // NOLINT - } -} - -TEST(VariantTest, GetIfIndex) { - using Var = variant<int, std::string, double, int>; - - { - Var v(absl::in_place_index<0>, 0); - EXPECT_TRUE(noexcept(absl::get_if<0>(&v))); - - { - auto* elem = absl::get_if<0>(&v); - EXPECT_TRUE((std::is_same<decltype(elem), int*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 0); - { - auto* bad_elem = absl::get_if<1>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - } - - const Var& const_v = v; - EXPECT_TRUE(noexcept(absl::get_if<0>(&const_v))); - - { - auto* elem = absl::get_if<0>(&const_v); - EXPECT_TRUE((std::is_same<decltype(elem), const int*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 0); - { - auto* bad_elem = absl::get_if<1>(&const_v); - EXPECT_TRUE( - (std::is_same<decltype(bad_elem), const std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&const_v); - EXPECT_EQ(bad_elem, nullptr); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - } - } - } - - { - Var v = std::string("Hello"); - EXPECT_TRUE(noexcept(absl::get_if<1>(&v))); - - { - auto* elem = absl::get_if<1>(&v); - EXPECT_TRUE((std::is_same<decltype(elem), std::string*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, "Hello"); - { - auto* bad_elem = absl::get_if<0>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - } - - const Var& const_v = v; - EXPECT_TRUE(noexcept(absl::get_if<1>(&const_v))); - - { - auto* elem = absl::get_if<1>(&const_v); - EXPECT_TRUE((std::is_same<decltype(elem), const std::string*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, "Hello"); - { - auto* bad_elem = absl::get_if<0>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&const_v); - EXPECT_EQ(bad_elem, nullptr); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - } - } - } - - { - Var v = 2.0; - EXPECT_TRUE(noexcept(absl::get_if<2>(&v))); - - { - auto* elem = absl::get_if<2>(&v); - EXPECT_TRUE((std::is_same<decltype(elem), double*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 2.0); - { - auto* bad_elem = absl::get_if<0>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<1>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - } - - const Var& const_v = v; - EXPECT_TRUE(noexcept(absl::get_if<2>(&const_v))); - - { - auto* elem = absl::get_if<2>(&const_v); - EXPECT_TRUE((std::is_same<decltype(elem), const double*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 2.0); - { - auto* bad_elem = absl::get_if<0>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<1>(&const_v); - EXPECT_TRUE( - (std::is_same<decltype(bad_elem), const std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<3>(&const_v); - EXPECT_EQ(bad_elem, nullptr); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - } - } - } - - { - Var v(absl::in_place_index<0>, 0); - v.emplace<3>(1); - EXPECT_TRUE(noexcept(absl::get_if<3>(&v))); - - { - auto* elem = absl::get_if<3>(&v); - EXPECT_TRUE((std::is_same<decltype(elem), int*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 1); - { - auto* bad_elem = absl::get_if<0>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<1>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - } - - const Var& const_v = v; - EXPECT_TRUE(noexcept(absl::get_if<3>(&const_v))); - - { - auto* elem = absl::get_if<3>(&const_v); - EXPECT_TRUE((std::is_same<decltype(elem), const int*>::value)); - ASSERT_NE(elem, nullptr); - EXPECT_EQ(*elem, 1); - { - auto* bad_elem = absl::get_if<0>(&const_v); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<1>(&const_v); - EXPECT_TRUE( - (std::is_same<decltype(bad_elem), const std::string*>::value)); - EXPECT_EQ(bad_elem, nullptr); - } - { - auto* bad_elem = absl::get_if<2>(&const_v); - EXPECT_EQ(bad_elem, nullptr); - EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value)); - } - } - } -} - -////////////////////// -// [variant.relops] // -////////////////////// - -TEST(VariantTest, OperatorEquals) { - variant<int, std::string> a(1), b(1); - EXPECT_TRUE(a == b); - EXPECT_TRUE(b == a); - EXPECT_FALSE(a != b); - EXPECT_FALSE(b != a); - - b = "str"; - EXPECT_FALSE(a == b); - EXPECT_FALSE(b == a); - EXPECT_TRUE(a != b); - EXPECT_TRUE(b != a); - - b = 0; - EXPECT_FALSE(a == b); - EXPECT_FALSE(b == a); - EXPECT_TRUE(a != b); - EXPECT_TRUE(b != a); - - a = b = "foo"; - EXPECT_TRUE(a == b); - EXPECT_TRUE(b == a); - EXPECT_FALSE(a != b); - EXPECT_FALSE(b != a); - - a = "bar"; - EXPECT_FALSE(a == b); - EXPECT_FALSE(b == a); - EXPECT_TRUE(a != b); - EXPECT_TRUE(b != a); -} - -TEST(VariantTest, OperatorRelational) { - variant<int, std::string> a(1), b(1); - EXPECT_FALSE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_FALSE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_TRUE(b <= a); - EXPECT_TRUE(a >= b); - EXPECT_TRUE(b >= a); - - b = "str"; - EXPECT_TRUE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_TRUE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_FALSE(b <= a); - EXPECT_FALSE(a >= b); - EXPECT_TRUE(b >= a); - - b = 0; - EXPECT_FALSE(a < b); - EXPECT_TRUE(b < a); - EXPECT_TRUE(a > b); - EXPECT_FALSE(b > a); - EXPECT_FALSE(a <= b); - EXPECT_TRUE(b <= a); - EXPECT_TRUE(a >= b); - EXPECT_FALSE(b >= a); - - a = b = "foo"; - EXPECT_FALSE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_FALSE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_TRUE(b <= a); - EXPECT_TRUE(a >= b); - EXPECT_TRUE(b >= a); - - a = "bar"; - EXPECT_TRUE(a < b); - EXPECT_FALSE(b < a); - EXPECT_FALSE(a > b); - EXPECT_TRUE(b > a); - EXPECT_TRUE(a <= b); - EXPECT_FALSE(b <= a); - EXPECT_FALSE(a >= b); - EXPECT_TRUE(b >= a); -} - -#ifdef ABSL_HAVE_EXCEPTIONS - -TEST(VariantTest, ValuelessOperatorEquals) { - variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"), - valueless(absl::in_place_index<0>), - other_valueless(absl::in_place_index<0>); - ToValuelessByException(valueless); - ToValuelessByException(other_valueless); - - EXPECT_TRUE(valueless == other_valueless); - EXPECT_TRUE(other_valueless == valueless); - EXPECT_FALSE(valueless == int_v); - EXPECT_FALSE(valueless == string_v); - EXPECT_FALSE(int_v == valueless); - EXPECT_FALSE(string_v == valueless); - - EXPECT_FALSE(valueless != other_valueless); - EXPECT_FALSE(other_valueless != valueless); - EXPECT_TRUE(valueless != int_v); - EXPECT_TRUE(valueless != string_v); - EXPECT_TRUE(int_v != valueless); - EXPECT_TRUE(string_v != valueless); -} - -TEST(VariantTest, ValuelessOperatorRelational) { - variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"), - valueless(absl::in_place_index<0>), - other_valueless(absl::in_place_index<0>); - ToValuelessByException(valueless); - ToValuelessByException(other_valueless); - - EXPECT_FALSE(valueless < other_valueless); - EXPECT_FALSE(other_valueless < valueless); - EXPECT_TRUE(valueless < int_v); - EXPECT_TRUE(valueless < string_v); - EXPECT_FALSE(int_v < valueless); - EXPECT_FALSE(string_v < valueless); - - EXPECT_TRUE(valueless <= other_valueless); - EXPECT_TRUE(other_valueless <= valueless); - EXPECT_TRUE(valueless <= int_v); - EXPECT_TRUE(valueless <= string_v); - EXPECT_FALSE(int_v <= valueless); - EXPECT_FALSE(string_v <= valueless); - - EXPECT_TRUE(valueless >= other_valueless); - EXPECT_TRUE(other_valueless >= valueless); - EXPECT_FALSE(valueless >= int_v); - EXPECT_FALSE(valueless >= string_v); - EXPECT_TRUE(int_v >= valueless); - EXPECT_TRUE(string_v >= valueless); - - EXPECT_FALSE(valueless > other_valueless); - EXPECT_FALSE(other_valueless > valueless); - EXPECT_FALSE(valueless > int_v); - EXPECT_FALSE(valueless > string_v); - EXPECT_TRUE(int_v > valueless); - EXPECT_TRUE(string_v > valueless); -} - -#endif - -///////////////////// -// [variant.visit] // -///////////////////// - -template <typename T> -struct ConvertTo { - template <typename U> - T operator()(const U& u) const { - return u; - } -}; - -TEST(VariantTest, VisitSimple) { - variant<std::string, const char*> v = "A"; - - std::string str = absl::visit(ConvertTo<std::string>{}, v); - EXPECT_EQ("A", str); - - v = std::string("B"); - - absl::string_view piece = absl::visit(ConvertTo<absl::string_view>{}, v); - EXPECT_EQ("B", piece); - - struct StrLen { - int operator()(const char* s) const { return strlen(s); } - int operator()(const std::string& s) const { return s.size(); } - }; - - v = "SomeStr"; - EXPECT_EQ(7, absl::visit(StrLen{}, v)); - v = std::string("VeryLargeThisTime"); - EXPECT_EQ(17, absl::visit(StrLen{}, v)); -} - -TEST(VariantTest, VisitRValue) { - variant<std::string> v = std::string("X"); - struct Visitor { - bool operator()(const std::string&) const { return false; } - bool operator()(std::string&&) const { return true; } // NOLINT - - int operator()(const std::string&, const std::string&) const { return 0; } - int operator()(const std::string&, std::string&&) const { - return 1; - } // NOLINT - int operator()(std::string&&, const std::string&) const { - return 2; - } // NOLINT - int operator()(std::string&&, std::string&&) const { return 3; } // NOLINT - }; - EXPECT_FALSE(absl::visit(Visitor{}, v)); - EXPECT_TRUE(absl::visit(Visitor{}, absl::move(v))); - - // Also test the variadic overload. - EXPECT_EQ(0, absl::visit(Visitor{}, v, v)); - EXPECT_EQ(1, absl::visit(Visitor{}, v, absl::move(v))); - EXPECT_EQ(2, absl::visit(Visitor{}, absl::move(v), v)); - EXPECT_EQ(3, absl::visit(Visitor{}, absl::move(v), absl::move(v))); -} - -TEST(VariantTest, VisitRValueVisitor) { - variant<std::string> v = std::string("X"); - struct Visitor { - bool operator()(const std::string&) const& { return false; } - bool operator()(const std::string&) && { return true; } - }; - Visitor visitor; - EXPECT_FALSE(absl::visit(visitor, v)); - EXPECT_TRUE(absl::visit(Visitor{}, v)); -} - -TEST(VariantTest, VisitResultTypeDifferent) { - variant<std::string> v = std::string("X"); - struct LValue_LValue {}; - struct RValue_LValue {}; - struct LValue_RValue {}; - struct RValue_RValue {}; - struct Visitor { - LValue_LValue operator()(const std::string&) const& { return {}; } - RValue_LValue operator()(std::string&&) const& { return {}; } // NOLINT - LValue_RValue operator()(const std::string&) && { return {}; } - RValue_RValue operator()(std::string&&) && { return {}; } // NOLINT - } visitor; - - EXPECT_TRUE( - (std::is_same<LValue_LValue, decltype(absl::visit(visitor, v))>::value)); - EXPECT_TRUE( - (std::is_same<RValue_LValue, - decltype(absl::visit(visitor, absl::move(v)))>::value)); - EXPECT_TRUE(( - std::is_same<LValue_RValue, decltype(absl::visit(Visitor{}, v))>::value)); - EXPECT_TRUE( - (std::is_same<RValue_RValue, - decltype(absl::visit(Visitor{}, absl::move(v)))>::value)); -} - -TEST(VariantTest, VisitVariadic) { - using A = variant<int, std::string>; - using B = variant<std::unique_ptr<int>, absl::string_view>; - - struct Visitor { - std::pair<int, int> operator()(int a, std::unique_ptr<int> b) const { - return {a, *b}; - } - std::pair<int, int> operator()(absl::string_view a, - std::unique_ptr<int> b) const { - return {static_cast<int>(a.size()), static_cast<int>(*b)}; - } - std::pair<int, int> operator()(int a, absl::string_view b) const { - return {a, static_cast<int>(b.size())}; - } - std::pair<int, int> operator()(absl::string_view a, - absl::string_view b) const { - return {static_cast<int>(a.size()), static_cast<int>(b.size())}; - } - }; - - EXPECT_THAT(absl::visit(Visitor(), A(1), B(std::unique_ptr<int>(new int(7)))), - ::testing::Pair(1, 7)); - EXPECT_THAT(absl::visit(Visitor(), A(1), B(absl::string_view("ABC"))), - ::testing::Pair(1, 3)); - EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")), - B(std::unique_ptr<int>(new int(7)))), - ::testing::Pair(5, 7)); - EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")), - B(absl::string_view("ABC"))), - ::testing::Pair(5, 3)); -} - -TEST(VariantTest, VisitNoArgs) { - EXPECT_EQ(5, absl::visit([] { return 5; })); -} - -struct ConstFunctor { - int operator()(int a, int b) const { return a - b; } -}; - -struct MutableFunctor { - int operator()(int a, int b) { return a - b; } -}; - -struct Class { - int Method(int a, int b) { return a - b; } - int ConstMethod(int a, int b) const { return a - b; } - - int member; -}; - -TEST(VariantTest, VisitReferenceWrapper) { - ConstFunctor cf; - MutableFunctor mf; - absl::variant<int> three = 3; - absl::variant<int> two = 2; - - EXPECT_EQ(1, absl::visit(std::cref(cf), three, two)); - EXPECT_EQ(1, absl::visit(std::ref(cf), three, two)); - EXPECT_EQ(1, absl::visit(std::ref(mf), three, two)); -} - -// libstdc++ std::variant doesn't support the INVOKE semantics. -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) -TEST(VariantTest, VisitMemberFunction) { - absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>()); - absl::variant<std::unique_ptr<const Class>> cp( - absl::make_unique<const Class>()); - absl::variant<int> three = 3; - absl::variant<int> two = 2; - - EXPECT_EQ(1, absl::visit(&Class::Method, p, three, two)); - EXPECT_EQ(1, absl::visit(&Class::ConstMethod, p, three, two)); - EXPECT_EQ(1, absl::visit(&Class::ConstMethod, cp, three, two)); -} - -TEST(VariantTest, VisitDataMember) { - absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>(Class{42})); - absl::variant<std::unique_ptr<const Class>> cp( - absl::make_unique<const Class>(Class{42})); - EXPECT_EQ(42, absl::visit(&Class::member, p)); - - absl::visit(&Class::member, p) = 5; - EXPECT_EQ(5, absl::visit(&Class::member, p)); - - EXPECT_EQ(42, absl::visit(&Class::member, cp)); -} -#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) - -///////////////////////// -// [variant.monostate] // -///////////////////////// - -TEST(VariantTest, MonostateBasic) { - absl::monostate mono; - (void)mono; - - // TODO(mattcalabrese) Expose move triviality metafunctions in absl. - EXPECT_TRUE(absl::is_trivially_default_constructible<absl::monostate>::value); - EXPECT_TRUE(is_trivially_move_constructible<absl::monostate>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<absl::monostate>::value); - EXPECT_TRUE(is_trivially_move_assignable<absl::monostate>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<absl::monostate>::value); - EXPECT_TRUE(absl::is_trivially_destructible<absl::monostate>::value); -} - -TEST(VariantTest, VariantMonostateDefaultConstruction) { - absl::variant<absl::monostate, NonDefaultConstructible> var; - EXPECT_EQ(var.index(), 0); -} - -//////////////////////////////// -// [variant.monostate.relops] // -//////////////////////////////// - -TEST(VariantTest, MonostateComparisons) { - absl::monostate lhs, rhs; - - EXPECT_EQ(lhs, lhs); - EXPECT_EQ(lhs, rhs); - - EXPECT_FALSE(lhs != lhs); - EXPECT_FALSE(lhs != rhs); - EXPECT_FALSE(lhs < lhs); - EXPECT_FALSE(lhs < rhs); - EXPECT_FALSE(lhs > lhs); - EXPECT_FALSE(lhs > rhs); - - EXPECT_LE(lhs, lhs); - EXPECT_LE(lhs, rhs); - EXPECT_GE(lhs, lhs); - EXPECT_GE(lhs, rhs); - - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() == - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() != - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() < - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() > - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() <= - std::declval<absl::monostate>())); - EXPECT_TRUE(noexcept(std::declval<absl::monostate>() >= - std::declval<absl::monostate>())); -} - -/////////////////////// -// [variant.specalg] // -/////////////////////// - -TEST(VariantTest, NonmemberSwap) { - using std::swap; - - SpecialSwap v1(3); - SpecialSwap v2(7); - - variant<SpecialSwap> a = v1, b = v2; - - EXPECT_THAT(a, VariantWith<SpecialSwap>(v1)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v2)); - - std::swap(a, b); - EXPECT_THAT(a, VariantWith<SpecialSwap>(v2)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v1)); -#ifndef ABSL_USES_STD_VARIANT - EXPECT_FALSE(absl::get<SpecialSwap>(a).special_swap); -#endif - - swap(a, b); - EXPECT_THAT(a, VariantWith<SpecialSwap>(v1)); - EXPECT_THAT(b, VariantWith<SpecialSwap>(v2)); - EXPECT_TRUE(absl::get<SpecialSwap>(b).special_swap); -} - -////////////////////////// -// [variant.bad.access] // -////////////////////////// - -TEST(VariantTest, BadAccess) { - EXPECT_TRUE(noexcept(absl::bad_variant_access())); - absl::bad_variant_access exception_obj; - std::exception* base = &exception_obj; - (void)base; -} - -//////////////////// -// [variant.hash] // -//////////////////// - -TEST(VariantTest, MonostateHash) { - absl::monostate mono, other_mono; - std::hash<absl::monostate> const hasher{}; - static_assert(std::is_same<decltype(hasher(mono)), std::size_t>::value, ""); - EXPECT_EQ(hasher(mono), hasher(other_mono)); -} - -TEST(VariantTest, Hash) { - static_assert(type_traits_internal::IsHashable<variant<int>>::value, ""); - static_assert(type_traits_internal::IsHashable<variant<Hashable>>::value, ""); - static_assert(type_traits_internal::IsHashable<variant<int, Hashable>>::value, - ""); - -#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ - static_assert(!type_traits_internal::IsHashable<variant<NonHashable>>::value, - ""); - static_assert( - !type_traits_internal::IsHashable<variant<Hashable, NonHashable>>::value, - ""); -#endif - -// MSVC std::hash<std::variant> does not use the index, thus produce the same -// result on the same value as different alternative. -#if !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT)) - { - // same value as different alternative - variant<int, int> v0(in_place_index<0>, 42); - variant<int, int> v1(in_place_index<1>, 42); - std::hash<variant<int, int>> hash; - EXPECT_NE(hash(v0), hash(v1)); - } -#endif // !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT)) - - { - std::hash<variant<int>> hash; - std::set<size_t> hashcodes; - for (int i = 0; i < 100; ++i) { - hashcodes.insert(hash(i)); - } - EXPECT_GT(hashcodes.size(), 90); - - // test const-qualified - static_assert(type_traits_internal::IsHashable<variant<const int>>::value, - ""); - static_assert( - type_traits_internal::IsHashable<variant<const Hashable>>::value, ""); - std::hash<absl::variant<const int>> c_hash; - for (int i = 0; i < 100; ++i) { - EXPECT_EQ(hash(i), c_hash(i)); - } - } -} - -//////////////////////////////////////// -// Miscellaneous and deprecated tests // -//////////////////////////////////////// - -// Test that a set requiring a basic type conversion works correctly -#if !defined(ABSL_USES_STD_VARIANT) -TEST(VariantTest, TestConvertingSet) { - typedef variant<double> Variant; - Variant v(1.0); - const int two = 2; - v = two; - EXPECT_TRUE(absl::holds_alternative<double>(v)); - ASSERT_TRUE(nullptr != absl::get_if<double>(&v)); - EXPECT_DOUBLE_EQ(2, absl::get<double>(v)); -} -#endif // ABSL_USES_STD_VARIANT - -// Test that a vector of variants behaves reasonably. -TEST(VariantTest, Container) { - typedef variant<int, float> Variant; - - // Creation of vector should work - std::vector<Variant> vec; - vec.push_back(Variant(10)); - vec.push_back(Variant(20.0f)); - - // Vector resizing should work if we supply a value for new slots - vec.resize(10, Variant(0)); -} - -// Test that a variant with a non-copyable type can be constructed and -// manipulated to some degree. -TEST(VariantTest, TestVariantWithNonCopyableType) { - typedef variant<int, NonCopyable> Variant; - const int kValue = 1; - Variant v(kValue); - ASSERT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_EQ(kValue, absl::get<int>(v)); -} - -// Test that a variant with a non-copyable type can be transformed to -// the non-copyable type with a call to `emplace` for different numbers -// of arguments. We do not need to test this for each of T1 ... T8 -// because `emplace` does not overload on T1 ... to T8, so if this -// works for any one of T1 ... T8, then it works for all of them. We -// do need to test that it works with varying numbers of parameters -// though. -TEST(VariantTest, TestEmplace) { - typedef variant<int, NonCopyable> Variant; - const int kValue = 1; - Variant v(kValue); - ASSERT_TRUE(absl::holds_alternative<int>(v)); - EXPECT_EQ(kValue, absl::get<int>(v)); - - // emplace with zero arguments, then back to 'int' - v.emplace<NonCopyable>(); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(0, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); - - // emplace with one argument: - v.emplace<NonCopyable>(1); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(1, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); - - // emplace with two arguments: - v.emplace<NonCopyable>(1, 2); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(3, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); - - // emplace with three arguments - v.emplace<NonCopyable>(1, 2, 3); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(6, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); - - // emplace with four arguments - v.emplace<NonCopyable>(1, 2, 3, 4); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(10, absl::get<NonCopyable>(v).value); - v = kValue; - ASSERT_TRUE(absl::holds_alternative<int>(v)); -} - -TEST(VariantTest, TestEmplaceDestroysCurrentValue) { - typedef variant<int, IncrementInDtor, NonCopyable> Variant; - int counter = 0; - Variant v(0); - ASSERT_TRUE(absl::holds_alternative<int>(v)); - v.emplace<IncrementInDtor>(&counter); - ASSERT_TRUE(absl::holds_alternative<IncrementInDtor>(v)); - ASSERT_EQ(0, counter); - v.emplace<NonCopyable>(); - ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v)); - EXPECT_EQ(1, counter); -} - -TEST(VariantTest, TestMoveSemantics) { - typedef variant<std::unique_ptr<int>, std::unique_ptr<std::string>> Variant; - - // Construct a variant by moving from an element value. - Variant v(absl::WrapUnique(new int(10))); - EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v)); - - // Construct a variant by moving from another variant. - Variant v2(absl::move(v)); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v2)); - ASSERT_NE(nullptr, absl::get<std::unique_ptr<int>>(v2)); - EXPECT_EQ(10, *absl::get<std::unique_ptr<int>>(v2)); - - // Moving from a variant object leaves it holding moved-from value of the - // same element type. - EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v)); - ASSERT_NE(nullptr, absl::get_if<std::unique_ptr<int>>(&v)); - EXPECT_EQ(nullptr, absl::get<std::unique_ptr<int>>(v)); - - // Assign a variant from an element value by move. - v = absl::make_unique<std::string>("foo"); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v)); - EXPECT_EQ("foo", *absl::get<std::unique_ptr<std::string>>(v)); - - // Move-assign a variant. - v2 = absl::move(v); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v2)); - EXPECT_EQ("foo", *absl::get<std::unique_ptr<std::string>>(v2)); - EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v)); -} - -variant<int, std::string> PassThrough(const variant<int, std::string>& arg) { - return arg; -} - -TEST(VariantTest, TestImplicitConversion) { - EXPECT_TRUE(absl::holds_alternative<int>(PassThrough(0))); - - // We still need the explicit cast for std::string, because C++ won't apply - // two user-defined implicit conversions in a row. - EXPECT_TRUE( - absl::holds_alternative<std::string>(PassThrough(std::string("foo")))); -} - -struct Convertible2; -struct Convertible1 { - Convertible1() {} - Convertible1(const Convertible1&) {} - Convertible1& operator=(const Convertible1&) { return *this; } - - // implicit conversion from Convertible2 - Convertible1(const Convertible2&) {} // NOLINT(runtime/explicit) -}; - -struct Convertible2 { - Convertible2() {} - Convertible2(const Convertible2&) {} - Convertible2& operator=(const Convertible2&) { return *this; } - - // implicit conversion from Convertible1 - Convertible2(const Convertible1&) {} // NOLINT(runtime/explicit) -}; - -TEST(VariantTest, TestRvalueConversion) { -#if !defined(ABSL_USES_STD_VARIANT) - variant<double, std::string> var( - ConvertVariantTo<variant<double, std::string>>( - variant<std::string, int>(0))); - ASSERT_TRUE(absl::holds_alternative<double>(var)); - EXPECT_EQ(0.0, absl::get<double>(var)); - - var = ConvertVariantTo<variant<double, std::string>>( - variant<const char*, float>("foo")); - ASSERT_TRUE(absl::holds_alternative<std::string>(var)); - EXPECT_EQ("foo", absl::get<std::string>(var)); - - variant<double> singleton( - ConvertVariantTo<variant<double>>(variant<int, float>(42))); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_EQ(42.0, absl::get<double>(singleton)); - - singleton = ConvertVariantTo<variant<double>>(variant<int, float>(3.14f)); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton))); - - singleton = ConvertVariantTo<variant<double>>(variant<int>(0)); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_EQ(0.0, absl::get<double>(singleton)); - - variant<int32_t, uint32_t> variant2( - ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42))); - ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2)); - EXPECT_EQ(42, absl::get<int32_t>(variant2)); - - variant2 = - ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42)); - ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2)); - EXPECT_EQ(42, absl::get<uint32_t>(variant2)); -#endif // !ABSL_USES_STD_VARIANT - - variant<Convertible1, Convertible2> variant3( - ConvertVariantTo<variant<Convertible1, Convertible2>>( - (variant<Convertible2, Convertible1>(Convertible1())))); - ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3)); - - variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>( - variant<Convertible2, Convertible1>(Convertible2())); - ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3)); -} - -TEST(VariantTest, TestLvalueConversion) { -#if !defined(ABSL_USES_STD_VARIANT) - variant<std::string, int> source1 = 0; - variant<double, std::string> destination( - ConvertVariantTo<variant<double, std::string>>(source1)); - ASSERT_TRUE(absl::holds_alternative<double>(destination)); - EXPECT_EQ(0.0, absl::get<double>(destination)); - - variant<const char*, float> source2 = "foo"; - destination = ConvertVariantTo<variant<double, std::string>>(source2); - ASSERT_TRUE(absl::holds_alternative<std::string>(destination)); - EXPECT_EQ("foo", absl::get<std::string>(destination)); - - variant<int, float> source3(42); - variant<double> singleton(ConvertVariantTo<variant<double>>(source3)); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_EQ(42.0, absl::get<double>(singleton)); - - source3 = 3.14f; - singleton = ConvertVariantTo<variant<double>>(source3); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton))); - - variant<int> source4(0); - singleton = ConvertVariantTo<variant<double>>(source4); - ASSERT_TRUE(absl::holds_alternative<double>(singleton)); - EXPECT_EQ(0.0, absl::get<double>(singleton)); - - variant<int32_t> source5(42); - variant<int32_t, uint32_t> variant2( - ConvertVariantTo<variant<int32_t, uint32_t>>(source5)); - ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2)); - EXPECT_EQ(42, absl::get<int32_t>(variant2)); - - variant<uint32_t> source6(42); - variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6); - ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2)); - EXPECT_EQ(42, absl::get<uint32_t>(variant2)); -#endif - - variant<Convertible2, Convertible1> source7((Convertible1())); - variant<Convertible1, Convertible2> variant3( - ConvertVariantTo<variant<Convertible1, Convertible2>>(source7)); - ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3)); - - source7 = Convertible2(); - variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(source7); - ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3)); -} - -TEST(VariantTest, TestMoveConversion) { - using Variant = - variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>; - using OtherVariant = - variant<std::unique_ptr<int>, std::unique_ptr<std::string>>; - - Variant var( - ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(0)})); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const int>>(var)); - ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr); - EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var)); - - var = ConvertVariantTo<Variant>( - OtherVariant(absl::make_unique<std::string>("foo"))); - ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var)); - EXPECT_EQ("foo", *absl::get<std::unique_ptr<const std::string>>(var)); -} - -TEST(VariantTest, DoesNotMoveFromLvalues) { - // We use shared_ptr here because it's both copyable and movable, and - // a moved-from shared_ptr is guaranteed to be null, so we can detect - // whether moving or copying has occurred. - using Variant = - variant<std::shared_ptr<const int>, std::shared_ptr<const std::string>>; - using OtherVariant = - variant<std::shared_ptr<int>, std::shared_ptr<std::string>>; - - Variant v1(std::make_shared<const int>(0)); - - // Test copy constructor - Variant v2(v1); - EXPECT_EQ(absl::get<std::shared_ptr<const int>>(v1), - absl::get<std::shared_ptr<const int>>(v2)); - - // Test copy-assignment operator - v1 = std::make_shared<const std::string>("foo"); - v2 = v1; - EXPECT_EQ(absl::get<std::shared_ptr<const std::string>>(v1), - absl::get<std::shared_ptr<const std::string>>(v2)); - - // Test converting copy constructor - OtherVariant other(std::make_shared<int>(0)); - Variant v3(ConvertVariantTo<Variant>(other)); - EXPECT_EQ(absl::get<std::shared_ptr<int>>(other), - absl::get<std::shared_ptr<const int>>(v3)); - - other = std::make_shared<std::string>("foo"); - v3 = ConvertVariantTo<Variant>(other); - EXPECT_EQ(absl::get<std::shared_ptr<std::string>>(other), - absl::get<std::shared_ptr<const std::string>>(v3)); -} - -TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) { -#if !defined(ABSL_USES_STD_VARIANT) - variant<double, std::string> var( - ConvertVariantTo<variant<double, std::string>>( - variant<std::string, int>(3))); - EXPECT_THAT(absl::get_if<double>(&var), Pointee(3.0)); - - var = ConvertVariantTo<variant<double, std::string>>( - variant<const char*, float>("foo")); - EXPECT_THAT(absl::get_if<std::string>(&var), Pointee(std::string("foo"))); - - variant<double> singleton( - ConvertVariantTo<variant<double>>(variant<int, float>(42))); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(42.0)); - - singleton = ConvertVariantTo<variant<double>>(variant<int, float>(3.14f)); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(DoubleEq(3.14f))); - - singleton = ConvertVariantTo<variant<double>>(variant<int>(3)); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(3.0)); - - variant<int32_t, uint32_t> variant2( - ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42))); - EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42)); - - variant2 = - ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42)); - EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42)); -#endif - - variant<Convertible1, Convertible2> variant3( - ConvertVariantTo<variant<Convertible1, Convertible2>>( - (variant<Convertible2, Convertible1>(Convertible1())))); - ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3)); - - variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>( - variant<Convertible2, Convertible1>(Convertible2())); - ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3)); -} - -TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) { -#if !defined(ABSL_USES_STD_VARIANT) - variant<std::string, int> source1 = 3; - variant<double, std::string> destination( - ConvertVariantTo<variant<double, std::string>>(source1)); - EXPECT_THAT(absl::get_if<double>(&destination), Pointee(3.0)); - - variant<const char*, float> source2 = "foo"; - destination = ConvertVariantTo<variant<double, std::string>>(source2); - EXPECT_THAT(absl::get_if<std::string>(&destination), - Pointee(std::string("foo"))); - - variant<int, float> source3(42); - variant<double> singleton(ConvertVariantTo<variant<double>>(source3)); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(42.0)); - - source3 = 3.14f; - singleton = ConvertVariantTo<variant<double>>(source3); - EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton))); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(DoubleEq(3.14f))); - - variant<int> source4(3); - singleton = ConvertVariantTo<variant<double>>(source4); - EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(3.0)); - - variant<int32_t> source5(42); - variant<int32_t, uint32_t> variant2( - ConvertVariantTo<variant<int32_t, uint32_t>>(source5)); - EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42)); - - variant<uint32_t> source6(42); - variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6); - EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42)); -#endif // !ABSL_USES_STD_VARIANT - - variant<Convertible2, Convertible1> source7((Convertible1())); - variant<Convertible1, Convertible2> variant3( - ConvertVariantTo<variant<Convertible1, Convertible2>>(source7)); - ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3)); - - source7 = Convertible2(); - variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(source7); - ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3)); -} - -TEST(VariantTest, TestMoveConversionViaConvertVariantTo) { - using Variant = - variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>; - using OtherVariant = - variant<std::unique_ptr<int>, std::unique_ptr<std::string>>; - - Variant var( - ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(3)})); - EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var), - Pointee(Pointee(3))); - - var = ConvertVariantTo<Variant>( - OtherVariant(absl::make_unique<std::string>("foo"))); - EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var), - Pointee(Pointee(std::string("foo")))); -} - -// If all alternatives are trivially copy/move constructible, variant should -// also be trivially copy/move constructible. This is not required by the -// standard and we know that libstdc++ variant doesn't have this feature. -// For more details see the paper: -// http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0602r0.html -#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__)) -#define ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY 1 -#endif - -TEST(VariantTest, TestCopyAndMoveTypeTraits) { - EXPECT_TRUE(std::is_copy_constructible<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(absl::is_move_assignable<variant<std::string>>::value); - EXPECT_TRUE(std::is_move_constructible<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(absl::is_copy_assignable<variant<std::unique_ptr<int>>>::value); - - EXPECT_FALSE( - absl::is_trivially_copy_constructible<variant<std::string>>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<variant<std::string>>::value); -#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY - EXPECT_TRUE(absl::is_trivially_copy_constructible<variant<int>>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<variant<int>>::value); - EXPECT_TRUE(is_trivially_move_constructible<variant<int>>::value); - EXPECT_TRUE(is_trivially_move_assignable<variant<int>>::value); -#endif // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY -} - -TEST(VariantTest, TestVectorOfMoveonlyVariant) { - // Verify that variant<MoveonlyType> works correctly as a std::vector element. - std::vector<variant<std::unique_ptr<int>, std::string>> vec; - vec.push_back(absl::make_unique<int>(42)); - vec.emplace_back("Hello"); - vec.reserve(3); - auto another_vec = absl::move(vec); - // As a sanity check, verify vector contents. - ASSERT_EQ(2, another_vec.size()); - EXPECT_EQ(42, *absl::get<std::unique_ptr<int>>(another_vec[0])); - EXPECT_EQ("Hello", absl::get<std::string>(another_vec[1])); -} - -TEST(VariantTest, NestedVariant) { -#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY - static_assert(absl::is_trivially_copy_constructible<variant<int>>(), ""); - static_assert(absl::is_trivially_copy_assignable<variant<int>>(), ""); - static_assert(is_trivially_move_constructible<variant<int>>(), ""); - static_assert(is_trivially_move_assignable<variant<int>>(), ""); - - static_assert(absl::is_trivially_copy_constructible<variant<variant<int>>>(), - ""); - static_assert(absl::is_trivially_copy_assignable<variant<variant<int>>>(), - ""); - static_assert(is_trivially_move_constructible<variant<variant<int>>>(), ""); - static_assert(is_trivially_move_assignable<variant<variant<int>>>(), ""); -#endif // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY - - variant<int> x(42); - variant<variant<int>> y(x); - variant<variant<int>> z(y); - EXPECT_TRUE(absl::holds_alternative<variant<int>>(z)); - EXPECT_EQ(x, absl::get<variant<int>>(z)); -} - -struct TriviallyDestructible { - TriviallyDestructible(TriviallyDestructible&&) {} - TriviallyDestructible(const TriviallyDestructible&) {} - TriviallyDestructible& operator=(TriviallyDestructible&&) { return *this; } - TriviallyDestructible& operator=(const TriviallyDestructible&) { - return *this; - } -}; - -struct TriviallyMovable { - TriviallyMovable(TriviallyMovable&&) = default; - TriviallyMovable(TriviallyMovable const&) {} - TriviallyMovable& operator=(const TriviallyMovable&) { return *this; } -}; - -struct TriviallyCopyable { - TriviallyCopyable(const TriviallyCopyable&) = default; - TriviallyCopyable& operator=(const TriviallyCopyable&) { return *this; } -}; - -struct TriviallyMoveAssignable { - TriviallyMoveAssignable(TriviallyMoveAssignable&&) = default; - TriviallyMoveAssignable(const TriviallyMoveAssignable&) {} - TriviallyMoveAssignable& operator=(TriviallyMoveAssignable&&) = default; - TriviallyMoveAssignable& operator=(const TriviallyMoveAssignable&) { - return *this; - } -}; - -struct TriviallyCopyAssignable {}; - -#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY -TEST(VariantTest, TestTriviality) { - { - using TrivDestVar = absl::variant<TriviallyDestructible>; - - EXPECT_FALSE(is_trivially_move_constructible<TrivDestVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<TrivDestVar>::value); - EXPECT_FALSE(is_trivially_move_assignable<TrivDestVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivDestVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivDestVar>::value); - } - - { - using TrivMoveVar = absl::variant<TriviallyMovable>; - - EXPECT_TRUE(is_trivially_move_constructible<TrivMoveVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_constructible<TrivMoveVar>::value); - EXPECT_FALSE(is_trivially_move_assignable<TrivMoveVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivMoveVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivMoveVar>::value); - } - - { - using TrivCopyVar = absl::variant<TriviallyCopyable>; - - EXPECT_TRUE(is_trivially_move_constructible<TrivCopyVar>::value); - EXPECT_TRUE(absl::is_trivially_copy_constructible<TrivCopyVar>::value); - EXPECT_FALSE(is_trivially_move_assignable<TrivCopyVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivCopyVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivCopyVar>::value); - } - - { - using TrivMoveAssignVar = absl::variant<TriviallyMoveAssignable>; - - EXPECT_TRUE(is_trivially_move_constructible<TrivMoveAssignVar>::value); - EXPECT_FALSE( - absl::is_trivially_copy_constructible<TrivMoveAssignVar>::value); - EXPECT_TRUE(is_trivially_move_assignable<TrivMoveAssignVar>::value); - EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivMoveAssignVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivMoveAssignVar>::value); - } - - { - using TrivCopyAssignVar = absl::variant<TriviallyCopyAssignable>; - - EXPECT_TRUE(is_trivially_move_constructible<TrivCopyAssignVar>::value); - EXPECT_TRUE( - absl::is_trivially_copy_constructible<TrivCopyAssignVar>::value); - EXPECT_TRUE(is_trivially_move_assignable<TrivCopyAssignVar>::value); - EXPECT_TRUE(absl::is_trivially_copy_assignable<TrivCopyAssignVar>::value); - EXPECT_TRUE(absl::is_trivially_destructible<TrivCopyAssignVar>::value); - } -} -#endif // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY - -// To verify that absl::variant correctly use the nontrivial move ctor of its -// member rather than use the trivial copy constructor. -TEST(VariantTest, MoveCtorBug) { - // To simulate std::tuple in libstdc++. - struct TrivialCopyNontrivialMove { - TrivialCopyNontrivialMove() = default; - TrivialCopyNontrivialMove(const TrivialCopyNontrivialMove&) = default; - TrivialCopyNontrivialMove(TrivialCopyNontrivialMove&&) { called = true; } - bool called = false; - }; - { - using V = absl::variant<TrivialCopyNontrivialMove, int>; - V v1(absl::in_place_index<0>); - // this should invoke the move ctor, rather than the trivial copy ctor. - V v2(std::move(v1)); - EXPECT_TRUE(absl::get<0>(v2).called); - } - { - // this case failed to compile before our fix due to a GCC bug. - using V = absl::variant<int, TrivialCopyNontrivialMove>; - V v1(absl::in_place_index<1>); - // this should invoke the move ctor, rather than the trivial copy ctor. - V v2(std::move(v1)); - EXPECT_TRUE(absl::get<1>(v2).called); - } -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl - -#endif // #if !defined(ABSL_USES_STD_VARIANT) |