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 12 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
29 changes: 23 additions & 6 deletions stl/inc/variant
Original file line number Diff line number Diff line change
Expand Up @@ -967,18 +967,34 @@ 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>
struct _Variant_type_test { // build Ti x[] = {std::forward<T>(t)};
template <size_t _Idx, class _Type>
static constexpr auto _Construct_array(_Type(&&)[1]) -> _Meta_list<integral_constant<size_t, _Idx>, _Type>;

template <size_t _Idx, class _Type, class _Ty>
using type = decltype(_Construct_array<_Idx, _Type>({_STD declval<_Ty>()}));
};

MichaelRizkalla marked this conversation as resolved.
Show resolved Hide resolved
template <size_t _Idx, class _Type, class _Ty>
using _Variant_type_resolver = typename _Variant_type_test::template type<_Idx, _Type, _Ty>;

template <size_t _Idx, class _Type>
struct _Variant_init_single_overload {
using _FTy = _Meta_list<integral_constant<size_t, _Idx>, _Ty> (*)(_Ty);
operator _FTy();
template <class _Ty>
using _FTy = _Variant_type_resolver<_Idx, _Type, _Ty>;

template <class _Ty>
auto operator()(_Type, _Ty&&) -> _FTy<_Ty>;
};

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 +1003,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 @@ -106,6 +106,7 @@
// P0602R4 Propagating Copy/Move Triviality In variant/optional
// P0604R0 invoke_result, is_invocable, is_nothrow_invocable
// P0607R0 Inline Variables For The STL
// P0608R3 Improving variant's Converting Constructor/Assignment
// P0682R1 Repairing Elementary String Conversions
// P0739R0 Improving Class Template Argument Deduction For The STL
// P0858R0 Constexpr Iterator Requirements
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,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 "
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
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"
45 changes: 28 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,7 @@ 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
#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 +1778,15 @@ 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

return 0;
}
Expand Down Expand Up @@ -3048,7 +3050,7 @@ 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
#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 +3065,10 @@ 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__
{
struct X {};
struct Y {
Expand Down Expand Up @@ -3104,7 +3106,7 @@ void test_T_assignment_basic() {
assert(v.index() == 1);
assert(std::get<1>(v) == 43);
}
#if 0 // TRANSITION, P0608
#ifndef __EDG__ // TRANSITION, DevCom-1337958
#ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
{
std::variant<unsigned, long> v;
Expand All @@ -3116,19 +3118,21 @@ 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
{
std::variant<bool volatile, int> v = 42;
v = false;
Expand Down Expand Up @@ -3266,7 +3270,7 @@ 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
#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 +3282,12 @@ 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

return 0;
}
Expand Down Expand Up @@ -4567,7 +4572,7 @@ void test_T_ctor_sfinae() {
static_assert(!std::is_constructible<V, int>::value,
"no matching constructor");
}
#if 0 // TRANSITION, P0608
#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 +4587,10 @@ 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__
{
struct X {};
struct Y {
Expand Down Expand Up @@ -4629,25 +4634,27 @@ void test_T_ctor_basic() {
static_assert(v.index() == 1, "");
static_assert(std::get<1>(v) == 42, "");
}
#if 0 // TRANSITION, P0608
#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
{
std::variant<bool volatile const, int> v = true;
assert(v.index() == 0);
Expand Down Expand Up @@ -4681,6 +4688,7 @@ void test_T_ctor_basic() {
#endif
}

#if 0 // Narrowing check occurs with P0806
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
struct BoomOnAnything {
template <class T>
constexpr BoomOnAnything(T) { static_assert(!std::is_same<T, T>::value, ""); }
Expand All @@ -4692,6 +4700,7 @@ void test_no_narrowing_check_for_class_types() {
assert(v.index() == 0);
assert(std::get<0>(v) == 42);
}
#endif // Narrowing check occurs with P0806

struct Bar {};
struct Baz {};
Expand All @@ -4708,7 +4717,9 @@ int run_test() {
test_T_ctor_basic();
test_T_ctor_noexcept();
test_T_ctor_sfinae();
#if 0 // Narrowing check occurs with P0806
test_no_narrowing_check_for_class_types();
#endif // Narrowing check occurs with P0806
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_17_matrix.lst
Loading