`<variant>`: Make `visit<R>` correctly handle conversions to non-movable types (#2971)

Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
Co-authored-by: Casey Carter <Casey@Carter.net>
This commit is contained in:
A. Jiang 2022-08-06 07:33:51 +08:00 коммит произвёл GitHub
Родитель 4677baef1c
Коммит 097e59ba9a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 24 добавлений и 2 удалений

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

@ -35,8 +35,8 @@ template <class _First, class... _Rest>
struct _All_same<_First, _Rest...> : bool_constant<conjunction_v<is_same<_First, _Rest>...>> {}; // variadic is_same struct _All_same<_First, _Rest...> : bool_constant<conjunction_v<is_same<_First, _Rest>...>> {}; // variadic is_same
template <class _To, class... _From> template <class _To, class... _From>
struct _Convertible_from_all : bool_constant<conjunction_v<is_convertible<_From, _To>...>> { struct _Convertible_from_all : bool_constant<conjunction_v<_Invoke_convertible<_From, _To>...>> {
// variadic is_convertible // variadic _Invoke_convertible
}; };
template <class...> template <class...>

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

@ -6971,6 +6971,28 @@ namespace msvc {
using R = immobile_data; using R = immobile_data;
assert(std::visit<R>(std::identity{}, std::variant<int, short>{13}).x == 13); assert(std::visit<R>(std::identity{}, std::variant<int, short>{13}).x == 13);
assert(std::visit<R>(std::identity{}, std::variant<int, short>{short{42}}).x == 42); assert(std::visit<R>(std::identity{}, std::variant<int, short>{short{42}}).x == 42);
// Verify that conversions to an object that can't be copied/moved are correctly handled
struct convertible_to_immobile_one {
operator immobile_data() const {
return immobile_data{1729};
}
};
struct convertible_to_immobile_other {
operator immobile_data() const {
return immobile_data{1138};
}
};
using VarTestConv = std::variant<convertible_to_immobile_one, convertible_to_immobile_other>;
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10112408
assert(std::visit<R>(std::identity{}, VarTestConv{convertible_to_immobile_one{}}).x == 1729);
assert(std::visit<R>(std::identity{}, VarTestConv{convertible_to_immobile_other{}}).x == 1138);
#endif // TRANSITION, DevCom-10112408
auto immobile_converter = [](auto src) -> immobile_data { return src; };
assert(std::visit<R>(immobile_converter, VarTestConv{convertible_to_immobile_one{}}).x == 1729);
assert(std::visit<R>(immobile_converter, VarTestConv{convertible_to_immobile_other{}}).x == 1138);
} }
{ {
// Verify that a returned object is not copied/moved/modified // Verify that a returned object is not copied/moved/modified