diff --git a/stl/inc/any b/stl/inc/any index b3be1b1001..4986245dc3 100644 --- a/stl/inc/any +++ b/stl/inc/any @@ -78,17 +78,17 @@ struct _Any_small_RTTI { // Hand-rolled vtable for nontrivial types that can be template static void __CLRCALL_PURE_OR_CDECL _Destroy_impl(void* const _Target) noexcept { - _Destroy_in_place(*static_cast<_Ty*>(_Target)); + _STD _Destroy_in_place(*static_cast<_Ty*>(_Target)); } template static void __CLRCALL_PURE_OR_CDECL _Copy_impl(void* const _Target, const void* const _Source) { - _Construct_in_place(*static_cast<_Ty*>(_Target), *static_cast(_Source)); + _STD _Construct_in_place(*static_cast<_Ty*>(_Target), *static_cast(_Source)); } template static void __CLRCALL_PURE_OR_CDECL _Move_impl(void* const _Target, void* const _Source) noexcept { - _Construct_in_place(*static_cast<_Ty*>(_Target), _STD move(*static_cast<_Ty*>(_Source))); + _STD _Construct_in_place(*static_cast<_Ty*>(_Target), _STD move(*static_cast<_Ty*>(_Source))); } _Destroy_fn* _Destroy; @@ -163,13 +163,12 @@ public: // Assignment [any.assign] any& operator=(const any& _That) { - *this = any{_That}; + _Assign(_That); return *this; } any& operator=(any&& _That) noexcept { - reset(); - _Move_from(_That); + _Assign(_STD move(_That)); return *this; } @@ -178,7 +177,7 @@ public: int> = 0> any& operator=(_ValueType&& _Value) { // replace contained value with an object of type decay_t<_ValueType> initialized from _Value - *this = any{_STD forward<_ValueType>(_Value)}; + _Assign(_STD forward<_ValueType>(_Value)); return *this; } @@ -290,19 +289,24 @@ private: } } + void _Assign(any _That) noexcept { // intentionally pass by value + reset(); + _Move_from(_That); + } + template _Decayed& _Emplace(_Types&&... _Args) { // emplace construct _Decayed if constexpr (_Any_is_trivial<_Decayed>) { // using the _Trivial representation auto& _Obj = reinterpret_cast<_Decayed&>(_Storage._TrivialData); - _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...); _Storage._TypeData = reinterpret_cast(&typeid(_Decayed)) | static_cast(_Any_representation::_Trivial); return _Obj; } else if constexpr (_Any_is_small<_Decayed>) { // using the _Small representation auto& _Obj = reinterpret_cast<_Decayed&>(_Storage._SmallStorage._Data); - _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_Obj, _STD forward<_Types>(_Args)...); _Storage._SmallStorage._RTTI = &_Any_small_RTTI_obj<_Decayed>; _Storage._TypeData = reinterpret_cast(&typeid(_Decayed)) | static_cast(_Any_representation::_Small); diff --git a/tests/std/tests/P0220R1_any/test.cpp b/tests/std/tests/P0220R1_any/test.cpp index 6d3d25e355..23b1a93fb5 100644 --- a/tests/std/tests/P0220R1_any/test.cpp +++ b/tests/std/tests/P0220R1_any/test.cpp @@ -2570,21 +2570,41 @@ namespace msvc { // empty any a; a = std::move(a); + assertEmpty(a); + + a = std::make_any(); + a = any_cast(std::move(a)); // extract inner any + assertEmpty(a); } { // small any a{small{42}}; a = std::move(a); + assertContains(a, 42); + + a = std::make_any(small{42}); + a = any_cast(std::move(a)); // extract inner any + assertContains(a, 42); } { // large any a{large{42}}; a = std::move(a); + assertContains(a, 42); + + a = std::make_any(large{42}); + a = any_cast(std::move(a)); // extract inner any + assertContains(a, 42); } { // trivial any a{int{42}}; a = std::move(a); + assertContains(a, 42); + + a = std::make_any(int{42}); + a = any_cast(std::move(a)); // extract inner any + assertContains(a, 42); } } #ifdef __clang__ @@ -3160,6 +3180,40 @@ namespace msvc { } #pragma warning(pop) } // namespace trivial + +#ifndef _M_CEE // TRANSITION, VSO-1659496 + namespace gh_140_robust_against_adl { + struct incomplete; + + template + struct wrapper { + T t; + }; + + template + void test_for() { + any a; + a = any{Type()}; + a = any{std::in_place_type}; + a = Type(); + a = std::make_any(); + a.emplace(); + assert(any_cast(&a) != nullptr); + } + + void run_test() { + using _trivial = wrapper*; + using _small = std::pair<_trivial, small>; + using _large = std::pair<_trivial, large>; + + globalMemCounter.disable_allocations = true; + test_for<_trivial>(); + test_for<_small>(); + globalMemCounter.disable_allocations = false; + test_for<_large>(); + } + } // namespace gh_140_robust_against_adl +#endif // _M_CEE } // namespace msvc int main() { @@ -3196,4 +3250,7 @@ int main() { msvc::size_and_alignment::run_test(); msvc::small_type::run_test(); msvc::trivial::run_test(); +#ifndef _M_CEE // TRANSITION, VSO-1659496 + msvc::gh_140_robust_against_adl::run_test(); +#endif // _M_CEE }