diff options
Diffstat (limited to 'absl/types/optional_test.cc')
-rw-r--r-- | absl/types/optional_test.cc | 90 |
1 files changed, 60 insertions, 30 deletions
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc index fc4f00a4..e6a36eb8 100644 --- a/absl/types/optional_test.cc +++ b/absl/types/optional_test.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// 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, @@ -157,6 +157,16 @@ struct NonMovable { 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); @@ -169,15 +179,7 @@ TEST(optionalTest, DefaultConstructor) { TEST(optionalTest, nulloptConstructor) { absl::optional<int> empty(absl::nullopt); EXPECT_FALSE(empty); - -#ifdef ABSL_HAVE_STD_OPTIONAL constexpr absl::optional<int> cempty{absl::nullopt}; -#else - // Creating a temporary absl::nullopt_t object instead of using absl::nullopt - // because absl::nullopt cannot be constexpr and have external linkage at the - // same time. - constexpr absl::optional<int> cempty{absl::nullopt_t(absl::nullopt_t::init)}; -#endif static_assert(!cempty.has_value(), ""); EXPECT_TRUE((std::is_nothrow_constructible<absl::optional<int>, absl::nullopt_t>::value)); @@ -337,16 +339,18 @@ TEST(optionalTest, InPlaceConstructor) { static_assert((*opt2).x == ConstexprType::kCtorInitializerList, ""); #endif - // TODO(absl-team): uncomment these when std::is_constructible<T, Args&&...> - // SFINAE is added to optional::optional(absl::in_place_t, Args&&...). - // struct I { - // I(absl::in_place_t); - // }; + 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<I>, - // absl::in_place_t>::value)); - // EXPECT_FALSE((std::is_constructible<absl::optional<I>, const - // 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&&); @@ -1476,8 +1480,8 @@ TEST(optionalTest, MoveAssignRegression) { 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_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)); } @@ -1504,18 +1508,19 @@ TEST(optionalTest, Hash) { 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 defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \ - _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11) - // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a - // static_assert to catch any user-defined type that doesn't provide a hash - // specialization. So instantiating std::hash<absl::optional<T>> will result - // in a hard error which is not SFINAE friendly. -#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1 -#endif - -#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY +#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 @@ -1623,4 +1628,29 @@ TEST(optionalTest, AssignmentConstraints) { 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 |