From c74a3867ee985d6dfeaf47196086cb6e6707cb5e Mon Sep 17 00:00:00 2001 From: MichaelRizkalla Date: Mon, 18 Jan 2021 00:36:36 +0000 Subject: [PATCH 01/18] Implement P0608R3: A sane variant converting constructor, and add tests This is a squash of multiple commits for readability Changes according to P1957R2 Adjust variant type selection templates, add unit tests --- stl/inc/variant | 25 ++- tests/std/test.lst | 1 + .../env.lst | 4 + .../test.cpp | 153 ++++++++++++++++++ 4 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 tests/std/tests/P0608R3_sane_variant_converting_constructor/env.lst create mode 100644 tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp diff --git a/stl/inc/variant b/stl/inc/variant index bccf5add82a..d752271c895 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -967,10 +967,24 @@ using _Variant_destroy_layer = conditional_t +struct _Variant_type_test { // build Ti x[] = {std::forward(t)}; + template + static constexpr auto _Construct_array(_Type(&&)[1]) -> _Meta_list, _Type>; + + template + using type = decltype(_Construct_array<_Idx, _Type>({_STD declval<_Ty&>()})); +}; + +template +using _Variant_type_resolver = typename _Variant_type_test::template type<_Idx, _Ty, _Type>; + +template struct _Variant_init_single_overload { - using _FTy = _Meta_list, _Ty> (*)(_Ty); - operator _FTy(); + template + using _FTy = _Variant_type_resolver<_Idx, _Ty, _Type>; + + template + auto operator()(_Ty, _Type) -> _FTy<_Ty>; }; template @@ -987,11 +1001,12 @@ template struct _Variant_init_helper {}; // failure case (has no member "type") template -struct _Variant_init_helper{}(_STD declval<_Ty>()))>, _Ty, +struct _Variant_init_helper< + void_t{}(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 // extract the type from _Variant_init_helper diff --git a/tests/std/test.lst b/tests/std/test.lst index 695d770af47..1e0dd6bb878 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -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_sane_variant_converting_constructor tests\P0616R0_using_move_in_numeric tests\P0631R8_numbers_math_constants tests\P0660R10_jthread_and_cv_any diff --git a/tests/std/tests/P0608R3_sane_variant_converting_constructor/env.lst b/tests/std/tests/P0608R3_sane_variant_converting_constructor/env.lst new file mode 100644 index 00000000000..2de7aab2959 --- /dev/null +++ b/tests/std/tests/P0608R3_sane_variant_converting_constructor/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_17_matrix.lst diff --git a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp new file mode 100644 index 00000000000..ecf8b06d155 --- /dev/null +++ b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp @@ -0,0 +1,153 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Also tests for P1957R2: Converting from T* to bool should be considered narrowing + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +struct double_double { + double_double(double x) : x_(x) {} + + double x_; +}; +struct convertible_bool { + convertible_bool(bool) {} + ~convertible_bool() = default; + + operator bool() { + return true; + } +}; + +// P0608R3 examples +static_assert(is_constructible_v, const char*>); +static_assert(is_constructible_v, string>); +static_assert(is_constructible_v>, char16_t>); +static_assert(is_constructible_v>, double&>); +static_assert(is_constructible_v, char>); +static_assert(is_constructible_v, int>); +static_assert(is_constructible_v, int>); +static_assert(is_constructible_v, int>); +static_assert(is_constructible_v, long long int>, int>); +static_assert(is_constructible_v, char>); + +static_assert(!is_constructible_v, int>); +static_assert(!is_constructible_v>, int>); +static_assert(!is_constructible_v, int>); + +// P1957R2 +static_assert(is_constructible_v, bool>); + +// more examples +static_assert(is_constructible_v, double>); +static_assert(is_constructible_v>, optional, int>, int>); +static_assert(is_constructible_v>, optional>, int>); +static_assert(is_constructible_v, optional, float>, int>); +static_assert(is_constructible_v, convertible_bool>); +static_assert(is_constructible_v, convertible_bool>); +static_assert(is_constructible_v, bool>); +static_assert(is_constructible_v, convertible_bool>); +static_assert(is_constructible_v, bool>); +static_assert(is_constructible_v, bool>); + +static_assert(!is_constructible_v, int>); +static_assert(!is_constructible_v, unsigned int>); +static_assert(!is_constructible_v, int>); + +void test_variant_constructor_P0608R3() { + // P0608R3 runtime checks + variant a = "abc"; // string + assert(a.index() == 0); + assert(get<0>(a) == string("abc")); + + variant> b = u'\u2043'; // optional + assert(b.index() == 1); + assert(get>(b) == u'\u2043'); + + double c_data = 3.14; + variant> c = c_data; // reference_wrapper + assert(c.index() == 1); + assert(get<1>(c) == c_data); + + using T1 = variant; + T1 d; + assert(d.index() == 0); + d = 0; // int + assert(d.index() == 1); + + using T2 = variant; + T2 e; + assert(e.index() == 0); + e = 0; // long + assert(e.index() == 1); + + variant f = 'a'; // int + assert(f.index() == 1); + assert(get(f) == 97); + + variant g = 0; // long + assert(g.index() == 1); + + variant h = 0; // long + assert(h.index() == 1); + + variant, long long int> i = 0; // long long int + assert(i.index() == 2); + + variant j = 'a'; // int + assert(j.index() == 1); + assert(get(j) == 97); +} + +void test_variant_constructor_P1957R2() { + bitset<4> a_bitset("0101"); + bool a_data = a_bitset[2]; + variant a = a_data; // bool + assert(a.index() == 0); + assert(get<0>(a)); + + bitset<4> b_bitset("0101"); + variant b = b_bitset[2]; // bool + variant b2 = b_bitset[1]; // bool + assert(b.index() == 0); + assert(get<0>(b)); + assert(b2.index() == 0); + assert(!get<0>(b2)); +} + +void test_variant_constructor_more_tests() { + variant> a = true; // bool + assert(a.index() == 3); + + variant b = convertible_bool{true}; // bool + assert(b.index() == 0); + assert(get<0>(b)); + + variant c = false; // bool + assert(c.index() == 2); + + variant d = convertible_bool{true}; // convertible_bool + assert(d.index() == 2); + + variant e = bool{}; // bool + assert(e.index() == 1); + assert(!get<1>(e)); + + variant f = convertible_bool{true}; // bool + assert(f.index() == 1); + assert(get<1>(f)); +} + +int main() { + test_variant_constructor_P0608R3(); + test_variant_constructor_P1957R2(); + test_variant_constructor_more_tests(); +} From 4822a81c7501d0899021fa744e9b86d4515a6111 Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Sat, 6 Feb 2021 03:20:17 +0000 Subject: [PATCH 02/18] Use _STD macro - Also propagate the type as R-value correctly Co-Authored-By: Igor Zhukov <4289847+fsb4000@users.noreply.github.com> --- stl/inc/variant | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index d752271c895..88a9bd1ef95 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -972,7 +972,7 @@ struct _Variant_type_test { // build Ti x[] = {std::forward(t)}; static constexpr auto _Construct_array(_Type(&&)[1]) -> _Meta_list, _Type>; template - using type = decltype(_Construct_array<_Idx, _Type>({_STD declval<_Ty&>()})); + using type = decltype(_Construct_array<_Idx, _Type>({_STD declval<_Ty&&>()})); }; template @@ -984,7 +984,7 @@ struct _Variant_init_single_overload { using _FTy = _Variant_type_resolver<_Idx, _Ty, _Type>; template - auto operator()(_Ty, _Type) -> _FTy<_Ty>; + auto operator()(_Ty&&, _Type) -> _FTy<_Ty>; }; template @@ -1002,11 +1002,11 @@ struct _Variant_init_helper {}; // failure case (has no member "type") template struct _Variant_init_helper< - void_t{}(std::declval<_Ty>(), std::declval<_Ty>()))>, _Ty, + void_t{}(_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>(), std::declval<_Ty>())); + using type = decltype(_Variant_init_overload_set<_Types...>{}(_STD declval<_Ty&&>(), _STD declval<_Ty>())); }; template // extract the type from _Variant_init_helper From 751ecf921c0562c9cdfc0dbe4f8f0ac33f022d97 Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Sat, 6 Feb 2021 13:42:47 +0000 Subject: [PATCH 03/18] Enable libc++ tests, include missing header Co-Authored-By: Igor Zhukov <4289847+fsb4000@users.noreply.github.com> --- tests/libcxx/expected_results.txt | 6 ------ tests/libcxx/skipped_tests.txt | 6 ------ .../P0608R3_sane_variant_converting_constructor/test.cpp | 1 + 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index e406827dbd4..bda25ac35f4 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -299,12 +299,6 @@ std/utilities/time/time.clock/time.clock.file/rep_signed.pass.cpp FAIL # C++20 P0466R5 "Layout-Compatibility And Pointer-Interconvertibility Traits" std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp:1 FAIL -# C++20 P0608R3 "Improving variant's Converting Constructor/Assignment" -std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp FAIL -std/utilities/variant/variant.variant/variant.assign/T.pass.cpp FAIL -std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp FAIL -std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp FAIL - # C++20 P0645R10 " Text Formatting" std/language.support/support.limits/support.limits.general/format.version.pass.cpp FAIL std/utilities/format/format.error/format.error.pass.cpp FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 9482df7db03..961df487464 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -299,12 +299,6 @@ utilities\time\time.clock\time.clock.file\rep_signed.pass.cpp # C++20 P0466R5 "Layout-Compatibility And Pointer-Interconvertibility Traits" language.support\support.limits\support.limits.general\type_traits.version.pass.cpp -# C++20 P0608R3 "Improving variant's Converting Constructor/Assignment" -utilities\variant\variant.variant\variant.assign\conv.pass.cpp -utilities\variant\variant.variant\variant.assign\T.pass.cpp -utilities\variant\variant.variant\variant.ctor\conv.pass.cpp -utilities\variant\variant.variant\variant.ctor\T.pass.cpp - # C++20 P0645R10 " Text Formatting" language.support\support.limits\support.limits.general\format.version.pass.cpp utilities\format\format.error\format.error.pass.cpp diff --git a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp index ecf8b06d155..97978cdaa69 100644 --- a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace std; From 31bcd373efaf19d919b9463f76a3762bbd656388 Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Sat, 6 Feb 2021 13:49:49 +0000 Subject: [PATCH 04/18] update tests --- .../test.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp index 97978cdaa69..b60023dcd59 100644 --- a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp @@ -5,12 +5,12 @@ #include #include +#include #include #include #include #include #include -#include using namespace std; @@ -20,12 +20,14 @@ struct double_double { double x_; }; struct convertible_bool { - convertible_bool(bool) {} + convertible_bool(bool x) : x_(x) {} ~convertible_bool() = default; operator bool() { - return true; + return x_; } + + bool x_; }; // P0608R3 examples @@ -142,9 +144,9 @@ void test_variant_constructor_more_tests() { assert(e.index() == 1); assert(!get<1>(e)); - variant f = convertible_bool{true}; // bool + variant f = convertible_bool{false}; // bool assert(f.index() == 1); - assert(get<1>(f)); + assert(!get<1>(f)); } int main() { From 769d62fbf0ad0464c24d0c8fa39c00ec3cf14840 Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Thu, 11 Feb 2021 14:30:45 +0000 Subject: [PATCH 05/18] Disable libc++ tests, guard failing tests on clang-cl This commit re-disables libc++ tests and guards tests which exhibit a behavior where narrowing conversion in user-defined type constructor is allowed by clang-cl and disallowed by cl. I assume cl is correct with this commit. Co-Authored-By: Igor Zhukov <4289847+fsb4000@users.noreply.github.com> --- tests/libcxx/expected_results.txt | 6 ++++++ tests/libcxx/skipped_tests.txt | 6 ++++++ tests/std/tests/P0088R3_variant/test.cpp | 4 ++++ .../test.cpp | 14 +++++++++++--- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index bda25ac35f4..e406827dbd4 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -299,6 +299,12 @@ std/utilities/time/time.clock/time.clock.file/rep_signed.pass.cpp FAIL # C++20 P0466R5 "Layout-Compatibility And Pointer-Interconvertibility Traits" std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp:1 FAIL +# C++20 P0608R3 "Improving variant's Converting Constructor/Assignment" +std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp FAIL +std/utilities/variant/variant.variant/variant.assign/T.pass.cpp FAIL +std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp FAIL +std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp FAIL + # C++20 P0645R10 " Text Formatting" std/language.support/support.limits/support.limits.general/format.version.pass.cpp FAIL std/utilities/format/format.error/format.error.pass.cpp FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 961df487464..9482df7db03 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -299,6 +299,12 @@ utilities\time\time.clock\time.clock.file\rep_signed.pass.cpp # C++20 P0466R5 "Layout-Compatibility And Pointer-Interconvertibility Traits" language.support\support.limits\support.limits.general\type_traits.version.pass.cpp +# C++20 P0608R3 "Improving variant's Converting Constructor/Assignment" +utilities\variant\variant.variant\variant.assign\conv.pass.cpp +utilities\variant\variant.variant\variant.assign\T.pass.cpp +utilities\variant\variant.variant\variant.ctor\conv.pass.cpp +utilities\variant\variant.variant\variant.ctor\T.pass.cpp + # C++20 P0645R10 " Text Formatting" language.support\support.limits\support.limits.general\format.version.pass.cpp utilities\format\format.error\format.error.pass.cpp diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 7a66a9f06e0..84c1fd090ff 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -4681,6 +4681,7 @@ void test_T_ctor_basic() { #endif } +#ifndef __clang__ // TRANSITION, ... struct BoomOnAnything { template constexpr BoomOnAnything(T) { static_assert(!std::is_same::value, ""); } @@ -4692,6 +4693,7 @@ void test_no_narrowing_check_for_class_types() { assert(v.index() == 0); assert(std::get<0>(v) == 42); } +#endif // !__clang__ struct Bar {}; struct Baz {}; @@ -4708,7 +4710,9 @@ int run_test() { test_T_ctor_basic(); test_T_ctor_noexcept(); test_T_ctor_sfinae(); +#ifndef __clang__ // TRANSITION, ... test_no_narrowing_check_for_class_types(); +#endif // !__clang__ test_construction_with_repeated_types(); return 0; } diff --git a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp index b60023dcd59..ff716c6c10e 100644 --- a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp @@ -23,7 +23,7 @@ struct convertible_bool { convertible_bool(bool x) : x_(x) {} ~convertible_bool() = default; - operator bool() { + operator bool() const noexcept { return x_; } @@ -46,10 +46,12 @@ static_assert(!is_constructible_v, int>); static_assert(!is_constructible_v>, int>); static_assert(!is_constructible_v, int>); -// P1957R2 +// P1957R2 examples static_assert(is_constructible_v, bool>); +static_assert(is_constructible_v, std::bitset<4>::reference>); +static_assert(is_constructible_v, std::bitset<4>::reference>); -// more examples +// More examples static_assert(is_constructible_v, double>); static_assert(is_constructible_v>, optional, int>, int>); static_assert(is_constructible_v>, optional>, int>); @@ -61,7 +63,9 @@ static_assert(is_constructible_v, convert static_assert(is_constructible_v, bool>); static_assert(is_constructible_v, bool>); +#ifndef __clang__ // TRANSITION, ... static_assert(!is_constructible_v, int>); +#endif // !__clang__ static_assert(!is_constructible_v, unsigned int>); static_assert(!is_constructible_v, int>); @@ -147,6 +151,10 @@ void test_variant_constructor_more_tests() { variant f = convertible_bool{false}; // bool assert(f.index() == 1); assert(!get<1>(f)); + + variant g = true_type{}; // bool + assert(g.index() == 0); + assert(get<0>(g)); } int main() { From 2d4c87b0bb3bd53dd83bccbc7ab7e4c621ea8e76 Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Fri, 12 Feb 2021 00:02:39 +0000 Subject: [PATCH 06/18] Make sure base class members are visible Co-Authored-By: S. B. Tam <8998201+cpplearner@users.noreply.github.com> --- stl/inc/variant | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stl/inc/variant b/stl/inc/variant index 88a9bd1ef95..c8bafde250c 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -992,7 +992,9 @@ struct _Variant_init_overload_set_; template struct _Variant_init_overload_set_, _Types...> - : _Variant_init_single_overload<_Indices, _Types>... {}; + : _Variant_init_single_overload<_Indices, _Types>... { + using _Variant_init_single_overload<_Indices, _Types>::operator()...; +}; template using _Variant_init_overload_set = _Variant_init_overload_set_, _Types...>; From 72b2de122a396fc6f91bd3dad7df4c7e984ba847 Mon Sep 17 00:00:00 2001 From: Igor Zhukov Date: Fri, 12 Feb 2021 07:31:36 +0700 Subject: [PATCH 07/18] Guard failing tests on EDG (#2) * Guard failing tests on EDG Co-Authored-By: Michael S. Rizkalla --- .../test.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp index ff716c6c10e..e7788367801 100644 --- a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp @@ -36,14 +36,18 @@ static_assert(is_constructible_v, string>); static_assert(is_constructible_v>, char16_t>); static_assert(is_constructible_v>, double&>); static_assert(is_constructible_v, char>); +#ifndef __EDG__ // TRANSITION, ... static_assert(is_constructible_v, int>); static_assert(is_constructible_v, int>); static_assert(is_constructible_v, int>); static_assert(is_constructible_v, long long int>, int>); +#endif // !__EDG__ static_assert(is_constructible_v, char>); +#ifndef __EDG__ // TRANSITION, ... static_assert(!is_constructible_v, int>); static_assert(!is_constructible_v>, int>); +#endif // !__EDG__ static_assert(!is_constructible_v, int>); // P1957R2 examples @@ -63,10 +67,12 @@ static_assert(is_constructible_v, convert static_assert(is_constructible_v, bool>); static_assert(is_constructible_v, bool>); +#ifndef __EDG__ // TRANSITION, ... #ifndef __clang__ // TRANSITION, ... static_assert(!is_constructible_v, int>); #endif // !__clang__ static_assert(!is_constructible_v, unsigned int>); +#endif // !__EDG__ static_assert(!is_constructible_v, int>); void test_variant_constructor_P0608R3() { @@ -93,13 +99,16 @@ void test_variant_constructor_P0608R3() { using T2 = variant; T2 e; assert(e.index() == 0); +#ifndef __EDG__ // TRANSITION, ... e = 0; // long assert(e.index() == 1); +#endif // !__EDG__ variant f = 'a'; // int assert(f.index() == 1); assert(get(f) == 97); +#ifndef __EDG__ // TRANSITION, ... variant g = 0; // long assert(g.index() == 1); @@ -108,6 +117,7 @@ void test_variant_constructor_P0608R3() { variant, long long int> i = 0; // long long int assert(i.index() == 2); +#endif // !__EDG__ variant j = 'a'; // int assert(j.index() == 1); From 8a6d8ed3d356e9286f229565c1a3fb2ef39ce474 Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Fri, 12 Feb 2021 16:01:43 +0000 Subject: [PATCH 08/18] Apply code review suggestions Co-Authored-By: Stephan T. Lavavej --- stl/inc/variant | 16 +++++++-------- stl/inc/yvals_core.h | 1 + tests/std/test.lst | 2 +- .../env.lst | 0 .../test.cpp | 20 +++++++++---------- 5 files changed, 20 insertions(+), 19 deletions(-) rename tests/std/tests/{P0608R3_sane_variant_converting_constructor => P0608R3_improved_variant_converting_constructor}/env.lst (100%) rename tests/std/tests/{P0608R3_sane_variant_converting_constructor => P0608R3_improved_variant_converting_constructor}/test.cpp (86%) diff --git a/stl/inc/variant b/stl/inc/variant index c8bafde250c..7cfb187f406 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -971,20 +971,20 @@ struct _Variant_type_test { // build Ti x[] = {std::forward(t)}; template static constexpr auto _Construct_array(_Type(&&)[1]) -> _Meta_list, _Type>; - template - using type = decltype(_Construct_array<_Idx, _Type>({_STD declval<_Ty&&>()})); + template + using type = decltype(_Construct_array<_Idx, _Type>({_STD declval<_Ty>()})); }; -template -using _Variant_type_resolver = typename _Variant_type_test::template type<_Idx, _Ty, _Type>; +template +using _Variant_type_resolver = typename _Variant_type_test::template type<_Idx, _Type, _Ty>; template struct _Variant_init_single_overload { template - using _FTy = _Variant_type_resolver<_Idx, _Ty, _Type>; + using _FTy = _Variant_type_resolver<_Idx, _Type, _Ty>; template - auto operator()(_Ty&&, _Type) -> _FTy<_Ty>; + auto operator()(_Type, _Ty&&) -> _FTy<_Ty>; }; template @@ -1004,11 +1004,11 @@ struct _Variant_init_helper {}; // failure case (has no member "type") template struct _Variant_init_helper< - void_t{}(_STD declval<_Ty&&>(), _STD declval<_Ty>()))>, _Ty, + void_t{}(_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&&>(), _STD declval<_Ty>())); + using type = decltype(_Variant_init_overload_set<_Types...>{}(_STD declval<_Ty>(), _STD declval<_Ty>())); }; template // extract the type from _Variant_init_helper diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index d5d0f8f2e84..184efe3db9a 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -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 diff --git a/tests/std/test.lst b/tests/std/test.lst index 1e0dd6bb878..79827325fdb 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -249,7 +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_sane_variant_converting_constructor +tests\P0608R3_improved_variant_converting_constructor tests\P0616R0_using_move_in_numeric tests\P0631R8_numbers_math_constants tests\P0660R10_jthread_and_cv_any diff --git a/tests/std/tests/P0608R3_sane_variant_converting_constructor/env.lst b/tests/std/tests/P0608R3_improved_variant_converting_constructor/env.lst similarity index 100% rename from tests/std/tests/P0608R3_sane_variant_converting_constructor/env.lst rename to tests/std/tests/P0608R3_improved_variant_converting_constructor/env.lst diff --git a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp similarity index 86% rename from tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp rename to tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp index e7788367801..c308d6357f4 100644 --- a/tests/std/tests/P0608R3_sane_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp @@ -37,12 +37,12 @@ static_assert(is_constructible_v>, char16_t>); static_assert(is_constructible_v>, double&>); static_assert(is_constructible_v, char>); #ifndef __EDG__ // TRANSITION, ... -static_assert(is_constructible_v, int>); -static_assert(is_constructible_v, int>); +static_assert(is_constructible_v, int>); +static_assert(is_constructible_v, int>); static_assert(is_constructible_v, int>); -static_assert(is_constructible_v, long long int>, int>); +static_assert(is_constructible_v, long long>, int>); #endif // !__EDG__ -static_assert(is_constructible_v, char>); +static_assert(is_constructible_v, char>); #ifndef __EDG__ // TRANSITION, ... static_assert(!is_constructible_v, int>); @@ -52,8 +52,8 @@ static_assert(!is_constructible_v, int>); // P1957R2 examples static_assert(is_constructible_v, bool>); -static_assert(is_constructible_v, std::bitset<4>::reference>); -static_assert(is_constructible_v, std::bitset<4>::reference>); +static_assert(is_constructible_v, bitset<4>::reference>); +static_assert(is_constructible_v, bitset<4>::reference>); // More examples static_assert(is_constructible_v, double>); @@ -73,13 +73,13 @@ static_assert(!is_constructible_v, int>); #endif // !__clang__ static_assert(!is_constructible_v, unsigned int>); #endif // !__EDG__ -static_assert(!is_constructible_v, int>); +static_assert(!is_constructible_v, int>); void test_variant_constructor_P0608R3() { // P0608R3 runtime checks variant a = "abc"; // string assert(a.index() == 0); - assert(get<0>(a) == string("abc")); + assert(get<0>(a) == "abc"); variant> b = u'\u2043'; // optional assert(b.index() == 1); @@ -115,11 +115,11 @@ void test_variant_constructor_P0608R3() { variant h = 0; // long assert(h.index() == 1); - variant, long long int> i = 0; // long long int + variant, long long> i = 0; // long long assert(i.index() == 2); #endif // !__EDG__ - variant j = 'a'; // int + variant j = 'a'; // int assert(j.index() == 1); assert(get(j) == 97); } From 45bb1da3fbf73559d92bb8c45536d913fedf3815 Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Fri, 12 Feb 2021 16:03:13 +0000 Subject: [PATCH 09/18] Update transition comment with bug report ID --- .../test.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp index c308d6357f4..958b0621343 100644 --- a/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp @@ -36,7 +36,7 @@ static_assert(is_constructible_v, string>); static_assert(is_constructible_v>, char16_t>); static_assert(is_constructible_v>, double&>); static_assert(is_constructible_v, char>); -#ifndef __EDG__ // TRANSITION, ... +#ifndef __EDG__ // TRANSITION, DevCom-1337958 static_assert(is_constructible_v, int>); static_assert(is_constructible_v, int>); static_assert(is_constructible_v, int>); @@ -44,7 +44,7 @@ static_assert(is_constructible_v, long long>, int>); #endif // !__EDG__ static_assert(is_constructible_v, char>); -#ifndef __EDG__ // TRANSITION, ... +#ifndef __EDG__ // TRANSITION, DevCom-1337958 static_assert(!is_constructible_v, int>); static_assert(!is_constructible_v>, int>); #endif // !__EDG__ @@ -67,7 +67,7 @@ static_assert(is_constructible_v, convert static_assert(is_constructible_v, bool>); static_assert(is_constructible_v, bool>); -#ifndef __EDG__ // TRANSITION, ... +#ifndef __EDG__ // TRANSITION, DevCom-1337958 #ifndef __clang__ // TRANSITION, ... static_assert(!is_constructible_v, int>); #endif // !__clang__ @@ -99,7 +99,7 @@ void test_variant_constructor_P0608R3() { using T2 = variant; T2 e; assert(e.index() == 0); -#ifndef __EDG__ // TRANSITION, ... +#ifndef __EDG__ // TRANSITION, DevCom-1337958 e = 0; // long assert(e.index() == 1); #endif // !__EDG__ @@ -108,7 +108,7 @@ void test_variant_constructor_P0608R3() { assert(f.index() == 1); assert(get(f) == 97); -#ifndef __EDG__ // TRANSITION, ... +#ifndef __EDG__ // TRANSITION, DevCom-1337958 variant g = 0; // long assert(g.index() == 1); From becac58244fc999319d4430307e203556031da1d Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Fri, 12 Feb 2021 19:06:23 +0000 Subject: [PATCH 10/18] Enable existing P0608 tests, guard for permissive flag This commit partially enables them when /permissive is used --- tests/std/tests/P0088R3_variant/env.lst | 10 +++--- tests/std/tests/P0088R3_variant/test.cpp | 41 ++++++++++++++---------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/tests/std/tests/P0088R3_variant/env.lst b/tests/std/tests/P0088R3_variant/env.lst index 48e3b76c748..e5b2f702cb0 100644 --- a/tests/std/tests/P0088R3_variant/env.lst +++ b/tests/std/tests/P0088R3_variant/env.lst @@ -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-" @@ -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" diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 84c1fd090ff..e5f101e881e 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -1768,7 +1768,7 @@ int run_test() { static_assert(!std::is_assignable, int>::value, ""); static_assert(!std::is_assignable, int>::value, ""); -#if 0 // TRANSITION, P0608 +#ifndef __EDG__ // TRANSITION, DevCom-1337958 static_assert(std::is_assignable, int>::value == VariantAllowsNarrowingConversions, ""); static_assert(std::is_assignable, int>::value @@ -1778,13 +1778,15 @@ int run_test() static_assert(!std::is_assignable, int>::value, ""); static_assert(!std::is_assignable, decltype("meow")>::value, ""); +#endif // !__EDG__ static_assert(!std::is_assignable, decltype("meow")>::value, ""); static_assert(!std::is_assignable, decltype("meow")>::value, ""); - static_assert(!std::is_assignable, std::true_type>::value, ""); + static_assert(std::is_assignable, std::true_type>::value, ""); static_assert(!std::is_assignable, std::unique_ptr >::value, ""); +#ifndef TEST_PERMISSIVE static_assert(!std::is_assignable, decltype(nullptr)>::value, ""); -#endif // TRANSITION, P0608 +#endif // !TEST_PERMISSIVE return 0; } @@ -3048,7 +3050,7 @@ void test_T_assignment_sfinae() { using V = std::variant; static_assert(!std::is_assignable::value, "no matching operator="); } -#if 0 // TRANSITION, P0608 +#ifndef __EDG__ // TRANSITION, DevCom-1337958 { using V = std::variant; static_assert(std::is_assignable::value == VariantAllowsNarrowingConversions, @@ -3063,10 +3065,10 @@ void test_T_assignment_sfinae() { }; static_assert(!std::is_assignable::value, "no boolean conversion in operator="); - static_assert(!std::is_assignable::value, + static_assert(std::is_assignable::value, "no converted to bool in operator="); } -#endif // TRANSITION, P0608 +#endif // !__EDG__ { struct X {}; struct Y { @@ -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 v; @@ -3116,19 +3118,21 @@ void test_T_assignment_basic() { assert(std::get<0>(v) == 43); } #endif +#endif // !__EDG__ { std::variant v = true; v = "bar"; assert(v.index() == 0); assert(std::get<0>(v) == "bar"); } +#ifndef TEST_PERMISSIVE { std::variant> v; v = nullptr; assert(v.index() == 1); assert(std::get<1>(v) == nullptr); } -#endif // TRANSITION, P0608 +#endif // !TEST_PERMISSIVE { std::variant v = 42; v = false; @@ -3266,7 +3270,7 @@ int run_test() { static_assert(!std::is_constructible, int>::value, ""); static_assert(!std::is_constructible, int>::value, ""); -#if 0 // TRANSITION, P0608 +#ifndef __EDG__ // TRANSITION, DevCom-1337958 static_assert(std::is_constructible, int>::value == VariantAllowsNarrowingConversions, ""); static_assert(std::is_constructible, int>::value @@ -3278,11 +3282,12 @@ int run_test() static_assert(!std::is_constructible, decltype("meow")>::value, ""); static_assert(!std::is_constructible, decltype("meow")>::value, ""); static_assert(!std::is_constructible, decltype("meow")>::value, ""); - - static_assert(!std::is_constructible, std::true_type>::value, ""); +#endif // !__EDG__ + static_assert(std::is_constructible, std::true_type>::value, ""); static_assert(!std::is_constructible, std::unique_ptr >::value, ""); +#ifndef TEST_PERMISSIVE static_assert(!std::is_constructible, decltype(nullptr)>::value, ""); -#endif // TRANSITION, P0608 +#endif // !TEST_PERMISSIVE return 0; } @@ -4567,7 +4572,7 @@ void test_T_ctor_sfinae() { static_assert(!std::is_constructible::value, "no matching constructor"); } -#if 0 // TRANSITION, P0608 +#ifndef __EDG__ // TRANSITION, DevCom-1337958 { using V = std::variant; static_assert(std::is_constructible::value == VariantAllowsNarrowingConversions, @@ -4582,10 +4587,10 @@ void test_T_ctor_sfinae() { }; static_assert(!std::is_constructible::value, "no boolean conversion in constructor"); - static_assert(!std::is_constructible::value, + static_assert(std::is_constructible::value, "no converted to bool in constructor"); } -#endif // TRANSITION, P0608 +#endif // !__EDG__ { struct X {}; struct Y { @@ -4629,7 +4634,7 @@ 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 v(42); @@ -4637,17 +4642,19 @@ void test_T_ctor_basic() { static_assert(std::get<1>(v) == 42, ""); } #endif +#endif // !__EDG__ { std::variant v = "meow"; assert(v.index() == 0); assert(std::get<0>(v) == "meow"); } +#ifndef TEST_PERMISSIVE { std::variant> v = nullptr; assert(v.index() == 1); assert(std::get<1>(v) == nullptr); } -#endif // TRANSITION, P0608 +#endif // !TEST_PERMISSIVE { std::variant v = true; assert(v.index() == 0); From 41b70442793eeef5d8941cc53443748840a10074 Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Sun, 14 Feb 2021 02:47:38 +0000 Subject: [PATCH 11/18] Add assignment tests, tidy tests --- tests/std/tests/P0088R3_variant/test.cpp | 8 +- .../test.cpp | 168 ++++++++++++++---- 2 files changed, 133 insertions(+), 43 deletions(-) diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index e5f101e881e..5be336f2ebd 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -4688,7 +4688,7 @@ void test_T_ctor_basic() { #endif } -#ifndef __clang__ // TRANSITION, ... +#if 0 // Narrowing check occurs with P0806 struct BoomOnAnything { template constexpr BoomOnAnything(T) { static_assert(!std::is_same::value, ""); } @@ -4700,7 +4700,7 @@ void test_no_narrowing_check_for_class_types() { assert(v.index() == 0); assert(std::get<0>(v) == 42); } -#endif // !__clang__ +#endif // Narrowing check occurs with P0806 struct Bar {}; struct Baz {}; @@ -4717,9 +4717,9 @@ int run_test() { test_T_ctor_basic(); test_T_ctor_noexcept(); test_T_ctor_sfinae(); -#ifndef __clang__ // TRANSITION, ... +#if 0 // Narrowing check occurs with P0806 test_no_narrowing_check_for_class_types(); -#endif // !__clang__ +#endif // Narrowing check occurs with P0806 test_construction_with_repeated_types(); return 0; } diff --git a/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp index 958b0621343..ee9cf492b06 100644 --- a/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp @@ -29,51 +29,99 @@ struct convertible_bool { bool x_; }; - -// P0608R3 examples -static_assert(is_constructible_v, const char*>); -static_assert(is_constructible_v, string>); -static_assert(is_constructible_v>, char16_t>); -static_assert(is_constructible_v>, double&>); -static_assert(is_constructible_v, char>); +struct default_struct {}; + +void assert_P0608R3() { + // P0608R3 examples + static_assert(is_constructible_v, const char*>); + static_assert(is_constructible_v, string>); + static_assert(is_constructible_v>, char16_t>); + static_assert(is_constructible_v>, double&>); + static_assert(is_constructible_v, char>); +#ifndef __EDG__ // TRANSITION, DevCom-1337958 + static_assert(is_constructible_v, int>); + static_assert(is_constructible_v, int>); + static_assert(is_constructible_v, int>); + static_assert(is_constructible_v, long long>, int>); +#endif // !__EDG__ + static_assert(is_constructible_v, char>); #ifndef __EDG__ // TRANSITION, DevCom-1337958 -static_assert(is_constructible_v, int>); -static_assert(is_constructible_v, int>); -static_assert(is_constructible_v, int>); -static_assert(is_constructible_v, long long>, int>); + static_assert(!is_constructible_v, int>); + static_assert(!is_constructible_v>, int>); #endif // !__EDG__ -static_assert(is_constructible_v, char>); + static_assert(!is_constructible_v, int>); + static_assert(is_assignable_v, const char*>); + static_assert(is_assignable_v, string>); + static_assert(is_assignable_v>, char16_t>); + static_assert(is_assignable_v>, double&>); + static_assert(is_assignable_v, char>); +#ifndef __EDG__ // TRANSITION, DevCom-1337958 + static_assert(is_assignable_v, int>); + static_assert(is_assignable_v, int>); + static_assert(is_assignable_v, int>); + static_assert(is_assignable_v, long long>, int>); +#endif // !__EDG__ + static_assert(is_assignable_v, char>); #ifndef __EDG__ // TRANSITION, DevCom-1337958 -static_assert(!is_constructible_v, int>); -static_assert(!is_constructible_v>, int>); + static_assert(!is_assignable_v, int>); + static_assert(!is_assignable_v>, int>); #endif // !__EDG__ -static_assert(!is_constructible_v, int>); - -// P1957R2 examples -static_assert(is_constructible_v, bool>); -static_assert(is_constructible_v, bitset<4>::reference>); -static_assert(is_constructible_v, bitset<4>::reference>); - -// More examples -static_assert(is_constructible_v, double>); -static_assert(is_constructible_v>, optional, int>, int>); -static_assert(is_constructible_v>, optional>, int>); -static_assert(is_constructible_v, optional, float>, int>); -static_assert(is_constructible_v, convertible_bool>); -static_assert(is_constructible_v, convertible_bool>); -static_assert(is_constructible_v, bool>); -static_assert(is_constructible_v, convertible_bool>); -static_assert(is_constructible_v, bool>); -static_assert(is_constructible_v, bool>); + static_assert(!is_assignable_v, int>); +} + +void assert_P1957R2() { + // P1957R2 examples + static_assert(is_constructible_v, bool>); + static_assert(is_constructible_v, bitset<4>::reference>); + static_assert(is_constructible_v, bitset<4>::reference>); + static_assert(is_assignable_v, bool>); + static_assert(is_assignable_v, bitset<4>::reference>); + static_assert(is_assignable_v, bitset<4>::reference>); +} + +void assert_more_examples() { + // More examples + static_assert(is_constructible_v, double>); + static_assert(is_constructible_v>, optional, int>, int>); + static_assert(is_constructible_v>, optional>, int>); + static_assert(is_constructible_v, optional, float>, int>); + static_assert(is_constructible_v, convertible_bool>); + static_assert(is_constructible_v, convertible_bool>); + static_assert(is_constructible_v, bool>); + static_assert(is_constructible_v, convertible_bool>); + static_assert(is_constructible_v, bool>); + static_assert(is_constructible_v, bool>); #ifndef __EDG__ // TRANSITION, DevCom-1337958 -#ifndef __clang__ // TRANSITION, ... -static_assert(!is_constructible_v, int>); -#endif // !__clang__ -static_assert(!is_constructible_v, unsigned int>); +#ifdef __clang__ // TRANSITION, DevCom-1338628 + static_assert(is_constructible_v, int>); +#endif // __clang__ + static_assert(!is_constructible_v, unsigned int>); + static_assert(!is_constructible_v, int>); #endif // !__EDG__ -static_assert(!is_constructible_v, int>); + static_assert(!is_constructible_v, int>); + static_assert(!is_constructible_v, int>); + + static_assert(is_assignable_v, double>); + static_assert(is_assignable_v>, optional, int>, int>); + static_assert(is_assignable_v>, optional>, int>); + static_assert(is_assignable_v, optional, float>, int>); + static_assert(is_assignable_v, convertible_bool>); + static_assert(is_assignable_v, convertible_bool>); + static_assert(is_assignable_v, bool>); + static_assert(is_assignable_v, convertible_bool>); + static_assert(is_assignable_v, bool>); + static_assert(is_assignable_v, bool>); +#ifndef __EDG__ // TRANSITION, DevCom-1337958 +#ifdef __clang__ // TRANSITION, DevCom-1338628 + static_assert(is_assignable_v, int>); +#endif // __clang__ + static_assert(!is_assignable_v, unsigned int>); +#endif // !__EDG__ + static_assert(!is_assignable_v, int>); + static_assert(!is_assignable_v, int>); +} void test_variant_constructor_P0608R3() { // P0608R3 runtime checks @@ -140,7 +188,7 @@ void test_variant_constructor_P1957R2() { assert(!get<0>(b2)); } -void test_variant_constructor_more_tests() { +void test_variant_constructor_more_examples() { variant> a = true; // bool assert(a.index() == 3); @@ -167,8 +215,50 @@ void test_variant_constructor_more_tests() { assert(get<0>(g)); } +void test_assignment_operator() { + variant a; // string + assert(a.index() == 0); + assert(get(a) == ""); + a = 3; // int + assert(a.index() == 2); + assert(get(a) == 3); + a = true; // bool + assert(a.index() == 1); + assert(get(a) == true); + + bool b_data = true; + variant b = b_data; // bool + assert(b.index() == 0); + assert(get<0>(b) == b_data); + b = 12; // int + assert(b.index() == 1); + assert(get<1>(b) == 12); + b = 12.5; // double_double + assert(b.index() == 2); + assert(get<2>(b).x_ == 12.5); + +#ifdef __clang__ // TRANSITION, DevCom-1338628 + variant c; + assert(c.index() == 0); + c = false; // bool + assert(c.index() == 1); + assert(get<1>(c) == false); + c = 5.12; // double_double + assert(c.index() == 2); + assert(get<2>(c).x_ == 5.12); + double_double c_data{1.2}; + c = static_cast(&c_data); // void* + assert(c.index() == 0); + assert(static_cast(get<0>(c))->x_ == 1.2); +#endif // __clang__ +} + int main() { + assert_P0608R3(); + assert_P1957R2(); + assert_more_examples(); test_variant_constructor_P0608R3(); test_variant_constructor_P1957R2(); - test_variant_constructor_more_tests(); + test_variant_constructor_more_examples(); + test_assignment_operator(); } From 0cf9c5fe8bfef74b8a69e50e76c9265b24c316db Mon Sep 17 00:00:00 2001 From: Michael Rizkalla Date: Sun, 14 Feb 2021 02:58:31 +0000 Subject: [PATCH 12/18] Guard failing tests for EDG --- .../P0608R3_improved_variant_converting_constructor/test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp index ee9cf492b06..038381f2261 100644 --- a/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp @@ -100,7 +100,6 @@ void assert_more_examples() { static_assert(!is_constructible_v, unsigned int>); static_assert(!is_constructible_v, int>); #endif // !__EDG__ - static_assert(!is_constructible_v, int>); static_assert(!is_constructible_v, int>); static_assert(is_assignable_v, double>); @@ -118,8 +117,8 @@ void assert_more_examples() { static_assert(is_assignable_v, int>); #endif // __clang__ static_assert(!is_assignable_v, unsigned int>); -#endif // !__EDG__ static_assert(!is_assignable_v, int>); +#endif // !__EDG__ static_assert(!is_assignable_v, int>); } @@ -226,6 +225,7 @@ void test_assignment_operator() { assert(a.index() == 1); assert(get(a) == true); +#ifndef __EDG__ // TRANSITION, DevCom-1337958 bool b_data = true; variant b = b_data; // bool assert(b.index() == 0); @@ -236,6 +236,7 @@ void test_assignment_operator() { b = 12.5; // double_double assert(b.index() == 2); assert(get<2>(b).x_ == 12.5); +#endif // !__EDG__ #ifdef __clang__ // TRANSITION, DevCom-1338628 variant c; From b0c2836e8909c452828e9de58651376def903b58 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 14 Feb 2021 16:29:02 -0800 Subject: [PATCH 13/18] Remove extra spaces. --- tests/std/tests/P0088R3_variant/env.lst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0088R3_variant/env.lst b/tests/std/tests/P0088R3_variant/env.lst index e5b2f702cb0..474ef952dd3 100644 --- a/tests/std/tests/P0088R3_variant/env.lst +++ b/tests/std/tests/P0088R3_variant/env.lst @@ -26,8 +26,8 @@ PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive /DCONSTEX 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 /DTEST_PERMISSIVE " -PM_CL="/clr /MDd /std:c++17 /DCONSTEXPR_NOTHROW /DTEST_PERMISSIVE " +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-" From 90c24af0e1e4ee8045db2c6813b12f1ee0ad94ca Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 14 Feb 2021 16:33:44 -0800 Subject: [PATCH 14/18] Fix paper citations. --- tests/std/tests/P0088R3_variant/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 5be336f2ebd..64cde505d46 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -4688,7 +4688,7 @@ void test_T_ctor_basic() { #endif } -#if 0 // Narrowing check occurs with P0806 +#if 0 // Narrowing check occurs with P0608R3 struct BoomOnAnything { template constexpr BoomOnAnything(T) { static_assert(!std::is_same::value, ""); } @@ -4700,7 +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 +#endif // Narrowing check occurs with P0608R3 struct Bar {}; struct Baz {}; @@ -4717,9 +4717,9 @@ int run_test() { test_T_ctor_basic(); test_T_ctor_noexcept(); test_T_ctor_sfinae(); -#if 0 // Narrowing check occurs with P0806 +#if 0 // Narrowing check occurs with P0608R3 test_no_narrowing_check_for_class_types(); -#endif // Narrowing check occurs with P0806 +#endif // Narrowing check occurs with P0608R3 test_construction_with_repeated_types(); return 0; } From 424620f8166c4adce9de86ad657f7b71418d13c2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 14 Feb 2021 16:55:30 -0800 Subject: [PATCH 15/18] T1 and T2 were used exactly once each. --- .../test.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp index 038381f2261..2d407f7d1e5 100644 --- a/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp +++ b/tests/std/tests/P0608R3_improved_variant_converting_constructor/test.cpp @@ -137,14 +137,12 @@ void test_variant_constructor_P0608R3() { assert(c.index() == 1); assert(get<1>(c) == c_data); - using T1 = variant; - T1 d; + variant d; assert(d.index() == 0); d = 0; // int assert(d.index() == 1); - using T2 = variant; - T2 e; + variant e; assert(e.index() == 0); #ifndef __EDG__ // TRANSITION, DevCom-1337958 e = 0; // long From 41854422b14a37e44008494438543795a26f036a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 14 Feb 2021 18:31:10 -0800 Subject: [PATCH 16/18] Guard the feature for C++20. --- stl/inc/variant | 11 ++++++++--- stl/inc/yvals_core.h | 2 +- tests/std/tests/P0088R3_variant/test.cpp | 16 ++++++++++++++-- .../env.lst | 2 +- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index 7cfb187f406..0c8b90c60c9 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -967,6 +967,8 @@ using _Variant_destroy_layer = conditional_t(t)}; template static constexpr auto _Construct_array(_Type(&&)[1]) -> _Meta_list, _Type>; @@ -977,14 +979,17 @@ struct _Variant_type_test { // build Ti x[] = {std::forward(t)}; template using _Variant_type_resolver = typename _Variant_type_test::template type<_Idx, _Type, _Ty>; +#endif // _HAS_CXX20 template struct _Variant_init_single_overload { +#if _HAS_CXX20 template - using _FTy = _Variant_type_resolver<_Idx, _Type, _Ty>; - + auto operator()(_Type, _Ty&&) -> _Variant_type_resolver<_Idx, _Type, _Ty>; +#else // _HAS_CXX20 template - auto operator()(_Type, _Ty&&) -> _FTy<_Ty>; + auto operator()(_Type, _Ty&&) -> _Meta_list, _Type>; +#endif // _HAS_CXX20 }; template diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 184efe3db9a..1b4a9bbaa7e 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -106,7 +106,6 @@ // 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 @@ -160,6 +159,7 @@ // P0556R3 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 // P0631R8 Math Constants // P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 64cde505d46..87e482ffec0 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -1768,6 +1768,7 @@ int run_test() { static_assert(!std::is_assignable, int>::value, ""); static_assert(!std::is_assignable, int>::value, ""); +#if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, DevCom-1337958 static_assert(std::is_assignable, int>::value == VariantAllowsNarrowingConversions, ""); @@ -1787,6 +1788,7 @@ int run_test() #ifndef TEST_PERMISSIVE static_assert(!std::is_assignable, decltype(nullptr)>::value, ""); #endif // !TEST_PERMISSIVE +#endif // _HAS_CXX20 return 0; } @@ -3050,6 +3052,7 @@ void test_T_assignment_sfinae() { using V = std::variant; static_assert(!std::is_assignable::value, "no matching operator="); } +#if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, DevCom-1337958 { using V = std::variant; @@ -3069,6 +3072,7 @@ void test_T_assignment_sfinae() { "no converted to bool in operator="); } #endif // !__EDG__ +#endif // _HAS_CXX20 { struct X {}; struct Y { @@ -3106,6 +3110,7 @@ void test_T_assignment_basic() { assert(v.index() == 1); assert(std::get<1>(v) == 43); } +#if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, DevCom-1337958 #ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS { @@ -3133,6 +3138,7 @@ void test_T_assignment_basic() { assert(std::get<1>(v) == nullptr); } #endif // !TEST_PERMISSIVE +#endif // _HAS_CXX20 { std::variant v = 42; v = false; @@ -3270,6 +3276,7 @@ int run_test() { static_assert(!std::is_constructible, int>::value, ""); static_assert(!std::is_constructible, int>::value, ""); +#if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, DevCom-1337958 static_assert(std::is_constructible, int>::value == VariantAllowsNarrowingConversions, ""); @@ -3288,6 +3295,7 @@ int run_test() #ifndef TEST_PERMISSIVE static_assert(!std::is_constructible, decltype(nullptr)>::value, ""); #endif // !TEST_PERMISSIVE +#endif // _HAS_CXX20 return 0; } @@ -4572,6 +4580,7 @@ void test_T_ctor_sfinae() { static_assert(!std::is_constructible::value, "no matching constructor"); } +#if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, DevCom-1337958 { using V = std::variant; @@ -4591,6 +4600,7 @@ void test_T_ctor_sfinae() { "no converted to bool in constructor"); } #endif // !__EDG__ +#endif // _HAS_CXX20 { struct X {}; struct Y { @@ -4634,6 +4644,7 @@ void test_T_ctor_basic() { static_assert(v.index() == 1, ""); static_assert(std::get<1>(v) == 42, ""); } +#if _HAS_CXX20 #ifndef __EDG__ // TRANSITION, DevCom-1337958 #ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS { @@ -4655,6 +4666,7 @@ void test_T_ctor_basic() { assert(std::get<1>(v) == nullptr); } #endif // !TEST_PERMISSIVE +#endif // _HAS_CXX20 { std::variant v = true; assert(v.index() == 0); @@ -4688,7 +4700,7 @@ void test_T_ctor_basic() { #endif } -#if 0 // Narrowing check occurs with P0608R3 +#if !_HAS_CXX20 // Narrowing check occurs with P0608R3 struct BoomOnAnything { template constexpr BoomOnAnything(T) { static_assert(!std::is_same::value, ""); } @@ -4717,7 +4729,7 @@ int run_test() { test_T_ctor_basic(); test_T_ctor_noexcept(); test_T_ctor_sfinae(); -#if 0 // Narrowing check occurs with P0608R3 +#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(); diff --git a/tests/std/tests/P0608R3_improved_variant_converting_constructor/env.lst b/tests/std/tests/P0608R3_improved_variant_converting_constructor/env.lst index 2de7aab2959..642f530ffad 100644 --- a/tests/std/tests/P0608R3_improved_variant_converting_constructor/env.lst +++ b/tests/std/tests/P0608R3_improved_variant_converting_constructor/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\usual_17_matrix.lst +RUNALL_INCLUDE ..\usual_latest_matrix.lst From 5fb05c84dc536dadc0ffeff959ce02643afc1c77 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 14 Feb 2021 19:13:52 -0800 Subject: [PATCH 17/18] Rename types, remove unnecessary keywords. Casey suggested _TargetType and _InitializerType to avoid confusion. constexpr is unnecessary for _Construct_array. typename/template keywords aren't necessary as _Variant_type_test isn't templated. --- stl/inc/variant | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index 0c8b90c60c9..e455a4366f7 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -970,25 +970,25 @@ using _Variant_destroy_layer = conditional_t(t)}; - template - static constexpr auto _Construct_array(_Type(&&)[1]) -> _Meta_list, _Type>; + template + static auto _Construct_array(_TargetType(&&)[1]) -> _Meta_list, _TargetType>; - template - using type = decltype(_Construct_array<_Idx, _Type>({_STD declval<_Ty>()})); + template + using type = decltype(_Construct_array<_Idx, _TargetType>({_STD declval<_InitializerType>()})); }; -template -using _Variant_type_resolver = typename _Variant_type_test::template type<_Idx, _Type, _Ty>; +template +using _Variant_type_resolver = _Variant_type_test::type<_Idx, _TargetType, _InitializerType>; #endif // _HAS_CXX20 -template +template struct _Variant_init_single_overload { #if _HAS_CXX20 - template - auto operator()(_Type, _Ty&&) -> _Variant_type_resolver<_Idx, _Type, _Ty>; + template + auto operator()(_TargetType, _InitializerType&&) -> _Variant_type_resolver<_Idx, _TargetType, _InitializerType>; #else // _HAS_CXX20 - template - auto operator()(_Type, _Ty&&) -> _Meta_list, _Type>; + template + auto operator()(_TargetType, _InitializerType&&) -> _Meta_list, _TargetType>; #endif // _HAS_CXX20 }; From 597b2800424a788074d08a94fcf7e0352f845b6d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 17 Feb 2021 15:59:12 -0800 Subject: [PATCH 18/18] Simplify metaprogramming. Co-authored-by: Casey Carter --- stl/inc/variant | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index e455a4366f7..339410bfd7d 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -969,16 +969,12 @@ using _Variant_destroy_layer = conditional_t(t)}; - template - static auto _Construct_array(_TargetType(&&)[1]) -> _Meta_list, _TargetType>; - - template - using type = decltype(_Construct_array<_Idx, _TargetType>({_STD declval<_InitializerType>()})); -}; +// build Ti x[] = {std::forward(t)}; +template +auto _Construct_array(_TargetType(&&)[1]) -> _Meta_list, _TargetType>; template -using _Variant_type_resolver = _Variant_type_test::type<_Idx, _TargetType, _InitializerType>; +using _Variant_type_resolver = decltype(_Construct_array<_Idx, _TargetType>({_STD declval<_InitializerType>()})); #endif // _HAS_CXX20 template