Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
This commit is contained in:
achabense 2023-09-22 03:20:01 +08:00 коммит произвёл GitHub
Родитель ddebb7b361
Коммит 40476391b9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 70 добавлений и 9 удалений

Просмотреть файл

@ -78,17 +78,17 @@ struct _Any_small_RTTI { // Hand-rolled vtable for nontrivial types that can be
template <class _Ty>
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 <class _Ty>
static void __CLRCALL_PURE_OR_CDECL _Copy_impl(void* const _Target, const void* const _Source) {
_Construct_in_place(*static_cast<_Ty*>(_Target), *static_cast<const _Ty*>(_Source));
_STD _Construct_in_place(*static_cast<_Ty*>(_Target), *static_cast<const _Ty*>(_Source));
}
template <class _Ty>
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 <class _Decayed, class... _Types>
_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<uintptr_t>(&typeid(_Decayed)) | static_cast<uintptr_t>(_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<uintptr_t>(&typeid(_Decayed)) | static_cast<uintptr_t>(_Any_representation::_Small);

Просмотреть файл

@ -2570,21 +2570,41 @@ namespace msvc {
// empty
any a;
a = std::move(a);
assertEmpty(a);
a = std::make_any<any>();
a = any_cast<any&&>(std::move(a)); // extract inner any
assertEmpty(a);
}
{
// small
any a{small{42}};
a = std::move(a);
assertContains<small>(a, 42);
a = std::make_any<any>(small{42});
a = any_cast<any&&>(std::move(a)); // extract inner any
assertContains<small>(a, 42);
}
{
// large
any a{large{42}};
a = std::move(a);
assertContains<large>(a, 42);
a = std::make_any<any>(large{42});
a = any_cast<any&&>(std::move(a)); // extract inner any
assertContains<large>(a, 42);
}
{
// trivial
any a{int{42}};
a = std::move(a);
assertContains<int>(a, 42);
a = std::make_any<any>(int{42});
a = any_cast<any&&>(std::move(a)); // extract inner any
assertContains<int>(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 <class T>
struct wrapper {
T t;
};
template <class Type>
void test_for() {
any a;
a = any{Type()};
a = any{std::in_place_type<Type>};
a = Type();
a = std::make_any<Type>();
a.emplace<Type>();
assert(any_cast<Type>(&a) != nullptr);
}
void run_test() {
using _trivial = wrapper<incomplete>*;
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
}