Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<variant>: P0608R3 Improving variant's converting constructor/assignment #1629

Merged
merged 19 commits into from
Feb 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions stl/inc/variant
Original file line number Diff line number Diff line change
Expand Up @@ -967,18 +967,35 @@ using _Variant_destroy_layer = conditional_t<conjunction_v<is_trivially_destruct
#pragma warning(disable : 4365) // '%s': conversion from '%s' to '%s', signed/unsigned mismatch
#pragma warning(disable : 5215) // '%s' a function parameter with volatile qualified type is deprecated in C++20
#endif // __clang__
template <size_t _Idx, class _Ty>

#if _HAS_CXX20
// build Ti x[] = {std::forward<T>(t)};
template <size_t _Idx, class _TargetType>
auto _Construct_array(_TargetType(&&)[1]) -> _Meta_list<integral_constant<size_t, _Idx>, _TargetType>;

MichaelRizkalla marked this conversation as resolved.
Show resolved Hide resolved
template <size_t _Idx, class _TargetType, class _InitializerType>
using _Variant_type_resolver = decltype(_Construct_array<_Idx, _TargetType>({_STD declval<_InitializerType>()}));
#endif // _HAS_CXX20

template <size_t _Idx, class _TargetType>
struct _Variant_init_single_overload {
using _FTy = _Meta_list<integral_constant<size_t, _Idx>, _Ty> (*)(_Ty);
operator _FTy();
#if _HAS_CXX20
template <class _InitializerType>
auto operator()(_TargetType, _InitializerType&&) -> _Variant_type_resolver<_Idx, _TargetType, _InitializerType>;
#else // _HAS_CXX20
template <class _InitializerType>
auto operator()(_TargetType, _InitializerType&&) -> _Meta_list<integral_constant<size_t, _Idx>, _TargetType>;
#endif // _HAS_CXX20
};

template <class _Indices, class... _Types>
struct _Variant_init_overload_set_;

template <size_t... _Indices, class... _Types>
struct _Variant_init_overload_set_<index_sequence<_Indices...>, _Types...>
: _Variant_init_single_overload<_Indices, _Types>... {};
: _Variant_init_single_overload<_Indices, _Types>... {
using _Variant_init_single_overload<_Indices, _Types>::operator()...;
};

template <class... _Types>
using _Variant_init_overload_set = _Variant_init_overload_set_<index_sequence_for<_Types...>, _Types...>;
Expand All @@ -987,11 +1004,12 @@ template <class Enable, class _Ty, class... _Types>
struct _Variant_init_helper {}; // failure case (has no member "type")

template <class _Ty, class... _Types>
struct _Variant_init_helper<void_t<decltype(_Variant_init_overload_set<_Types...>{}(_STD declval<_Ty>()))>, _Ty,
struct _Variant_init_helper<
void_t<decltype(_Variant_init_overload_set<_Types...>{}(_STD declval<_Ty>(), _STD declval<_Ty>()))>, _Ty,
_Types...> {
// perform overload resolution to determine the unique alternative that should be initialized in
// variant<_Types...> from an argument expression with type and value category _Ty
using type = decltype(_Variant_init_overload_set<_Types...>{}(_STD declval<_Ty>()));
using type = decltype(_Variant_init_overload_set<_Types...>{}(_STD declval<_Ty>(), _STD declval<_Ty>()));
};

template <class _Ty, class... _Types> // extract the type from _Variant_init_helper
Expand Down
1 change: 1 addition & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
// P0556R3 <bit> Integral Power-Of-2 Operations (renamed by P1956R1)
// P0586R2 Integer Comparison Functions
// P0595R2 is_constant_evaluated()
// P0608R3 Improving variant's Converting Constructor/Assignment
// P0616R0 Using move() In <numeric>
// P0631R8 <numbers> Math Constants
// P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ tests\P0556R3_bit_integral_power_of_two_operations
tests\P0586R2_integer_comparison
tests\P0595R2_is_constant_evaluated
tests\P0607R0_inline_variables
tests\P0608R3_improved_variant_converting_constructor
tests\P0616R0_using_move_in_numeric
tests\P0631R8_numbers_math_constants
tests\P0660R10_jthread_and_cv_any
Expand Down
10 changes: 5 additions & 5 deletions tests/std/tests/P0088R3_variant/env.lst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ RUNALL_CROSSLIST
PM_CL="/w14640 /Zc:threadSafeInit-"
RUNALL_CROSSLIST
PM_CL="/EHsc /MD /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /Zc:noexceptTypes-"
PM_CL="/EHsc /MD /D_ITERATOR_DEBUG_LEVEL=0 /std:c++17 /DCONSTEXPR_NOTHROW"
PM_CL="/EHsc /MD /D_ITERATOR_DEBUG_LEVEL=0 /std:c++17 /DCONSTEXPR_NOTHROW /DTEST_PERMISSIVE"
PM_CL="/EHsc /MD /D_ITERATOR_DEBUG_LEVEL=1 /std:c++latest /permissive-"
PM_CL="/EHsc /MD /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /Zc:char8_t- /Zc:preprocessor"
PM_CL="/EHsc /MDd /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /Zc:wchar_t-"
Expand All @@ -22,15 +22,15 @@ PM_CL="/EHsc /MT /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /analyze:
PM_CL="/EHsc /MT /D_ITERATOR_DEBUG_LEVEL=1 /std:c++latest /permissive-"
PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=0 /std:c++latest /permissive- /fp:strict"
PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=1 /std:c++latest /permissive-"
PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive /DCONSTEXPR_NOTHROW"
PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive /DCONSTEXPR_NOTHROW /DTEST_PERMISSIVE"
PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze:only /analyze:autolog-"
PM_CL="/Za /EHsc /MD /std:c++latest /permissive-"
PM_CL="/Za /EHsc /MDd /std:c++latest /permissive-"
PM_CL="/clr /MD /std:c++17 /DCONSTEXPR_NOTHROW"
PM_CL="/clr /MDd /std:c++17 /DCONSTEXPR_NOTHROW"
PM_CL="/clr /MD /std:c++17 /DCONSTEXPR_NOTHROW /DTEST_PERMISSIVE"
PM_CL="/clr /MDd /std:c++17 /DCONSTEXPR_NOTHROW /DTEST_PERMISSIVE"
PM_CL="/BE /c /EHsc /MD /std:c++latest /permissive-"
PM_CL="/BE /c /EHsc /MDd /std:c++17 /permissive-"
PM_CL="/BE /c /EHsc /MTd /std:c++latest /permissive-"
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing /EHsc /MD /std:c++latest /permissive-"
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing /EHsc /MDd /std:c++17"
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing /EHsc /MDd /std:c++17 /DTEST_PERMISSIVE"
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing /EHsc /MTd /std:c++latest /permissive- /fp:strict"
57 changes: 40 additions & 17 deletions tests/std/tests/P0088R3_variant/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,8 @@ int run_test()
{
static_assert(!std::is_assignable<std::variant<int, int>, int>::value, "");
static_assert(!std::is_assignable<std::variant<long, long long>, int>::value, "");
#if 0 // TRANSITION, P0608
#if _HAS_CXX20
#ifndef __EDG__ // TRANSITION, DevCom-1337958
static_assert(std::is_assignable<std::variant<char>, int>::value == VariantAllowsNarrowingConversions, "");

static_assert(std::is_assignable<std::variant<std::string, float>, int>::value
Expand All @@ -1778,13 +1779,16 @@ int run_test()
static_assert(!std::is_assignable<std::variant<std::string, bool>, int>::value, "");

static_assert(!std::is_assignable<std::variant<int, bool>, decltype("meow")>::value, "");
#endif // !__EDG__
static_assert(!std::is_assignable<std::variant<int, const bool>, decltype("meow")>::value, "");
static_assert(!std::is_assignable<std::variant<int, const volatile bool>, decltype("meow")>::value, "");

static_assert(!std::is_assignable<std::variant<bool>, std::true_type>::value, "");
static_assert(std::is_assignable<std::variant<bool>, std::true_type>::value, "");
static_assert(!std::is_assignable<std::variant<bool>, std::unique_ptr<char> >::value, "");
#ifndef TEST_PERMISSIVE
static_assert(!std::is_assignable<std::variant<bool>, decltype(nullptr)>::value, "");
#endif // TRANSITION, P0608
#endif // !TEST_PERMISSIVE
#endif // _HAS_CXX20

return 0;
}
Expand Down Expand Up @@ -3048,7 +3052,8 @@ void test_T_assignment_sfinae() {
using V = std::variant<std::string, void *>;
static_assert(!std::is_assignable<V, int>::value, "no matching operator=");
}
#if 0 // TRANSITION, P0608
#if _HAS_CXX20
#ifndef __EDG__ // TRANSITION, DevCom-1337958
{
using V = std::variant<std::string, float>;
static_assert(std::is_assignable<V, int>::value == VariantAllowsNarrowingConversions,
Expand All @@ -3063,10 +3068,11 @@ void test_T_assignment_sfinae() {
};
static_assert(!std::is_assignable<V, X>::value,
"no boolean conversion in operator=");
static_assert(!std::is_assignable<V, std::false_type>::value,
static_assert(std::is_assignable<V, std::false_type>::value,
"no converted to bool in operator=");
}
#endif // TRANSITION, P0608
#endif // !__EDG__
#endif // _HAS_CXX20
{
struct X {};
struct Y {
Expand Down Expand Up @@ -3104,7 +3110,8 @@ void test_T_assignment_basic() {
assert(v.index() == 1);
assert(std::get<1>(v) == 43);
}
#if 0 // TRANSITION, P0608
#if _HAS_CXX20
#ifndef __EDG__ // TRANSITION, DevCom-1337958
#ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
{
std::variant<unsigned, long> v;
Expand All @@ -3116,19 +3123,22 @@ void test_T_assignment_basic() {
assert(std::get<0>(v) == 43);
}
#endif
#endif // !__EDG__
{
std::variant<std::string, bool> v = true;
v = "bar";
assert(v.index() == 0);
assert(std::get<0>(v) == "bar");
}
#ifndef TEST_PERMISSIVE
{
std::variant<bool, std::unique_ptr<int>> v;
v = nullptr;
assert(v.index() == 1);
assert(std::get<1>(v) == nullptr);
}
#endif // TRANSITION, P0608
#endif // !TEST_PERMISSIVE
#endif // _HAS_CXX20
{
std::variant<bool volatile, int> v = 42;
v = false;
Expand Down Expand Up @@ -3266,7 +3276,8 @@ int run_test()
{
static_assert(!std::is_constructible<std::variant<int, int>, int>::value, "");
static_assert(!std::is_constructible<std::variant<long, long long>, int>::value, "");
#if 0 // TRANSITION, P0608
#if _HAS_CXX20
#ifndef __EDG__ // TRANSITION, DevCom-1337958
static_assert(std::is_constructible<std::variant<char>, int>::value == VariantAllowsNarrowingConversions, "");

static_assert(std::is_constructible<std::variant<std::string, float>, int>::value
Expand All @@ -3278,11 +3289,13 @@ int run_test()
static_assert(!std::is_constructible<std::variant<int, bool>, decltype("meow")>::value, "");
static_assert(!std::is_constructible<std::variant<int, const bool>, decltype("meow")>::value, "");
static_assert(!std::is_constructible<std::variant<int, const volatile bool>, decltype("meow")>::value, "");

static_assert(!std::is_constructible<std::variant<bool>, std::true_type>::value, "");
#endif // !__EDG__
static_assert(std::is_constructible<std::variant<bool>, std::true_type>::value, "");
static_assert(!std::is_constructible<std::variant<bool>, std::unique_ptr<char> >::value, "");
#ifndef TEST_PERMISSIVE
static_assert(!std::is_constructible<std::variant<bool>, decltype(nullptr)>::value, "");
#endif // TRANSITION, P0608
#endif // !TEST_PERMISSIVE
#endif // _HAS_CXX20

return 0;
}
Expand Down Expand Up @@ -4567,7 +4580,8 @@ void test_T_ctor_sfinae() {
static_assert(!std::is_constructible<V, int>::value,
"no matching constructor");
}
#if 0 // TRANSITION, P0608
#if _HAS_CXX20
#ifndef __EDG__ // TRANSITION, DevCom-1337958
{
using V = std::variant<std::string, float>;
static_assert(std::is_constructible<V, int>::value == VariantAllowsNarrowingConversions,
Expand All @@ -4582,10 +4596,11 @@ void test_T_ctor_sfinae() {
};
static_assert(!std::is_constructible<V, X>::value,
"no boolean conversion in constructor");
static_assert(!std::is_constructible<V, std::false_type>::value,
static_assert(std::is_constructible<V, std::false_type>::value,
"no converted to bool in constructor");
}
#endif // TRANSITION, P0608
#endif // !__EDG__
#endif // _HAS_CXX20
{
struct X {};
struct Y {
Expand Down Expand Up @@ -4629,25 +4644,29 @@ void test_T_ctor_basic() {
static_assert(v.index() == 1, "");
static_assert(std::get<1>(v) == 42, "");
}
#if 0 // TRANSITION, P0608
#if _HAS_CXX20
#ifndef __EDG__ // TRANSITION, DevCom-1337958
#ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
{
constexpr std::variant<unsigned, long> v(42);
static_assert(v.index() == 1, "");
static_assert(std::get<1>(v) == 42, "");
}
#endif
#endif // !__EDG__
{
std::variant<std::string, bool const> v = "meow";
assert(v.index() == 0);
assert(std::get<0>(v) == "meow");
}
#ifndef TEST_PERMISSIVE
{
std::variant<bool volatile, std::unique_ptr<int>> v = nullptr;
assert(v.index() == 1);
assert(std::get<1>(v) == nullptr);
}
#endif // TRANSITION, P0608
#endif // !TEST_PERMISSIVE
#endif // _HAS_CXX20
{
std::variant<bool volatile const, int> v = true;
assert(v.index() == 0);
Expand Down Expand Up @@ -4681,6 +4700,7 @@ void test_T_ctor_basic() {
#endif
}

#if !_HAS_CXX20 // Narrowing check occurs with P0608R3
struct BoomOnAnything {
template <class T>
constexpr BoomOnAnything(T) { static_assert(!std::is_same<T, T>::value, ""); }
Expand All @@ -4692,6 +4712,7 @@ void test_no_narrowing_check_for_class_types() {
assert(v.index() == 0);
assert(std::get<0>(v) == 42);
}
#endif // Narrowing check occurs with P0608R3

struct Bar {};
struct Baz {};
Expand All @@ -4708,7 +4729,9 @@ int run_test() {
test_T_ctor_basic();
test_T_ctor_noexcept();
test_T_ctor_sfinae();
#if !_HAS_CXX20 // Narrowing check occurs with P0608R3
test_no_narrowing_check_for_class_types();
#endif // Narrowing check occurs with P0608R3
test_construction_with_repeated_types();
return 0;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
Loading