From c53cbd1b0fcd9b09d3f4275c6d91006eb28ce50c Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Thu, 5 Aug 2021 18:46:43 -0700 Subject: [PATCH 01/11] LWG-2774 `std::function` construction vs assignment --- stl/inc/functional | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/functional b/stl/inc/functional index dc2a4f7df86..c455344f0b5 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1135,12 +1135,12 @@ public: } #if _USE_FUNCTION_INT_0_SFINAE - template = 0> + template &, function> = 0> #else // ^^^ _USE_FUNCTION_INT_0_SFINAE // !_USE_FUNCTION_INT_0_SFINAE vvv - template > + template &, function>> #endif // _USE_FUNCTION_INT_0_SFINAE - function(_Fx _Func) { - this->_Reset(_STD move(_Func)); + function(_Fx&& _Func) { + this->_Reset(_STD forward<_Fx>(_Func)); } #if _HAS_FUNCTION_ALLOCATOR_SUPPORT From 436e0ba7b275e8615c136526fea0c74db608e9f2 Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Thu, 5 Aug 2021 20:30:33 -0700 Subject: [PATCH 02/11] Added mandates --- stl/inc/functional | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stl/inc/functional b/stl/inc/functional index c455344f0b5..9327585e887 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1140,6 +1140,11 @@ public: template &, function>> #endif // _USE_FUNCTION_INT_0_SFINAE function(_Fx&& _Func) { + // Per LWG-2774 + static_assert(is_copy_constructible_v>, "decay_t shall be copy constructible"); + // Per LWG-2774 + static_assert(is_constructible_v, _Fx>, "decay_t shall be constructible with F"); + this->_Reset(_STD forward<_Fx>(_Func)); } From 373117bd87a0ee9b5bc567aba0dd042d5198654e Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Fri, 6 Aug 2021 07:19:44 -0700 Subject: [PATCH 03/11] Add tests --- .../env.lst | 4 ++++ .../test.cpp | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/std/tests/LWG2774_function_construction_vs_assignment/env.lst create mode 100644 tests/std/tests/LWG2774_function_construction_vs_assignment/test.cpp diff --git a/tests/std/tests/LWG2774_function_construction_vs_assignment/env.lst b/tests/std/tests/LWG2774_function_construction_vs_assignment/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/LWG2774_function_construction_vs_assignment/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/LWG2774_function_construction_vs_assignment/test.cpp b/tests/std/tests/LWG2774_function_construction_vs_assignment/test.cpp new file mode 100644 index 00000000000..a277abcea1c --- /dev/null +++ b/tests/std/tests/LWG2774_function_construction_vs_assignment/test.cpp @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include + +using namespace std; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct Fn { + Fn(const Fn&) = delete; + Fn(Fn&&) = delete; + + void operator()() const {} +}; + +STATIC_ASSERT(!is_constructible_v, const Fn&>); +STATIC_ASSERT(!is_constructible_v, Fn&&>); + +int main() {} // COMPILE-ONLY From 11ec6c8b5539c2dbf43f25b1a40f288d80c20004 Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Fri, 6 Aug 2021 09:16:03 -0700 Subject: [PATCH 04/11] Rename to `test.compile.pass.cpp` --- .../test.compile.pass.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp diff --git a/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp b/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp new file mode 100644 index 00000000000..a277abcea1c --- /dev/null +++ b/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include + +using namespace std; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct Fn { + Fn(const Fn&) = delete; + Fn(Fn&&) = delete; + + void operator()() const {} +}; + +STATIC_ASSERT(!is_constructible_v, const Fn&>); +STATIC_ASSERT(!is_constructible_v, Fn&&>); + +int main() {} // COMPILE-ONLY From 43467eeff182c7f0a9719cb9b837b2be1226aeda Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Fri, 6 Aug 2021 09:16:35 -0700 Subject: [PATCH 05/11] Remove unnecessary copy constructible mandate --- stl/inc/functional | 2 -- 1 file changed, 2 deletions(-) diff --git a/stl/inc/functional b/stl/inc/functional index 9327585e887..953d45b14e0 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1140,8 +1140,6 @@ public: template &, function>> #endif // _USE_FUNCTION_INT_0_SFINAE function(_Fx&& _Func) { - // Per LWG-2774 - static_assert(is_copy_constructible_v>, "decay_t shall be copy constructible"); // Per LWG-2774 static_assert(is_constructible_v, _Fx>, "decay_t shall be constructible with F"); From f94d74093032881c4b4c4695870d43f88ff1f44e Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Fri, 6 Aug 2021 09:16:46 -0700 Subject: [PATCH 06/11] Renamed --- .../test.cpp | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 tests/std/tests/LWG2774_function_construction_vs_assignment/test.cpp diff --git a/tests/std/tests/LWG2774_function_construction_vs_assignment/test.cpp b/tests/std/tests/LWG2774_function_construction_vs_assignment/test.cpp deleted file mode 100644 index a277abcea1c..00000000000 --- a/tests/std/tests/LWG2774_function_construction_vs_assignment/test.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include -#include - -using namespace std; - -#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) - -struct Fn { - Fn(const Fn&) = delete; - Fn(Fn&&) = delete; - - void operator()() const {} -}; - -STATIC_ASSERT(!is_constructible_v, const Fn&>); -STATIC_ASSERT(!is_constructible_v, Fn&&>); - -int main() {} // COMPILE-ONLY From 676c21e5df672d82972e98da1346ab3ef0cf6860 Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Fri, 6 Aug 2021 09:16:57 -0700 Subject: [PATCH 07/11] Add the test to `test.lst` --- tests/std/test.lst | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/std/test.lst b/tests/std/test.lst index 3fb435eca19..3e91b5b9d8f 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -179,6 +179,7 @@ tests\GH_001850_clog_tied_to_cout tests\GH_002039_byte_is_not_trivially_swappable tests\GH_002058_debug_iterator_race tests\LWG2597_complex_branch_cut +tests\LWG2774_function_construction_vs_assignment tests\LWG3018_shared_ptr_function tests\P0019R8_atomic_ref tests\P0024R2_parallel_algorithms_adjacent_difference From 5aef558f357c9b63c066cecb55d79380a6ea2c47 Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Fri, 6 Aug 2021 10:00:57 -0700 Subject: [PATCH 08/11] Use detector pattern to check for instantiation --- .../test.compile.pass.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp b/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp index a277abcea1c..b21c73ca6ff 100644 --- a/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp +++ b/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp @@ -15,7 +15,16 @@ struct Fn { void operator()() const {} }; -STATIC_ASSERT(!is_constructible_v, const Fn&>); -STATIC_ASSERT(!is_constructible_v, Fn&&>); +template +struct detector : false_type {}; + +template +struct detector()...))>, Args...> : true_type {}; + +template +using can_instantiate = detector, Arg>; + +STATIC_ASSERT(!can_instantiate::value); +STATIC_ASSERT(!can_instantiate::value); int main() {} // COMPILE-ONLY From 06c3d6108ff0da82ca20e5ad885be04c473fd844 Mon Sep 17 00:00:00 2001 From: Sam Huang Date: Fri, 6 Aug 2021 10:59:35 -0700 Subject: [PATCH 09/11] Remove unimplementable test --- tests/std/test.lst | 1 - .../env.lst | 4 --- .../test.compile.pass.cpp | 30 ------------------- 3 files changed, 35 deletions(-) delete mode 100644 tests/std/tests/LWG2774_function_construction_vs_assignment/env.lst delete mode 100644 tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index 3e91b5b9d8f..3fb435eca19 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -179,7 +179,6 @@ tests\GH_001850_clog_tied_to_cout tests\GH_002039_byte_is_not_trivially_swappable tests\GH_002058_debug_iterator_race tests\LWG2597_complex_branch_cut -tests\LWG2774_function_construction_vs_assignment tests\LWG3018_shared_ptr_function tests\P0019R8_atomic_ref tests\P0024R2_parallel_algorithms_adjacent_difference diff --git a/tests/std/tests/LWG2774_function_construction_vs_assignment/env.lst b/tests/std/tests/LWG2774_function_construction_vs_assignment/env.lst deleted file mode 100644 index 19f025bd0e6..00000000000 --- a/tests/std/tests/LWG2774_function_construction_vs_assignment/env.lst +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp b/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp deleted file mode 100644 index b21c73ca6ff..00000000000 --- a/tests/std/tests/LWG2774_function_construction_vs_assignment/test.compile.pass.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include -#include - -using namespace std; - -#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) - -struct Fn { - Fn(const Fn&) = delete; - Fn(Fn&&) = delete; - - void operator()() const {} -}; - -template -struct detector : false_type {}; - -template -struct detector()...))>, Args...> : true_type {}; - -template -using can_instantiate = detector, Arg>; - -STATIC_ASSERT(!can_instantiate::value); -STATIC_ASSERT(!can_instantiate::value); - -int main() {} // COMPILE-ONLY From 830df5b1849179960140177c5b8fe8914ac11cbb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 8 Dec 2021 21:12:06 -0800 Subject: [PATCH 10/11] Remove unnecessary comment and static_assert. --- stl/inc/functional | 3 --- 1 file changed, 3 deletions(-) diff --git a/stl/inc/functional b/stl/inc/functional index f5410aa9d1b..b10399de7a4 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1050,9 +1050,6 @@ public: template &, function>> #endif // _USE_FUNCTION_INT_0_SFINAE function(_Fx&& _Func) { - // Per LWG-2774 - static_assert(is_constructible_v, _Fx>, "decay_t shall be constructible with F"); - this->_Reset(_STD forward<_Fx>(_Func)); } From 247459508c64c59f5f0ba6addde06b5a73db3327 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 8 Dec 2021 21:21:45 -0800 Subject: [PATCH 11/11] Align _Enable_if_callable_t with the Standard, update allocator_arg_t ctor. --- stl/inc/functional | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/stl/inc/functional b/stl/inc/functional index b10399de7a4..5038e78c9b7 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -886,9 +886,9 @@ public: protected: template - using _Enable_if_callable_t = - enable_if_t, _Function>>, _Is_invocable_r<_Ret, _Fx, _Types...>>, - int>; + using _Enable_if_callable_t = enable_if_t, _Function>>, + _Is_invocable_r<_Ret, decay_t<_Fx>&, _Types...>>, + int>; bool _Empty() const noexcept { return !_Getimpl(); @@ -1045,9 +1045,9 @@ public: } #if _USE_FUNCTION_INT_0_SFINAE - template &, function> = 0> + template = 0> #else // ^^^ _USE_FUNCTION_INT_0_SFINAE // !_USE_FUNCTION_INT_0_SFINAE vvv - template &, function>> + template > #endif // _USE_FUNCTION_INT_0_SFINAE function(_Fx&& _Func) { this->_Reset(_STD forward<_Fx>(_Func)); @@ -1066,12 +1066,12 @@ public: } #if _USE_FUNCTION_INT_0_SFINAE - template = 0> + template = 0> #else // ^^^ _USE_FUNCTION_INT_0_SFINAE // !_USE_FUNCTION_INT_0_SFINAE vvv - template > + template > #endif // _USE_FUNCTION_INT_0_SFINAE - function(allocator_arg_t, const _Alloc& _Ax, _Fx _Func) { - this->_Reset_alloc(_STD move(_Func), _Ax); + function(allocator_arg_t, const _Alloc& _Ax, _Fx&& _Func) { + this->_Reset_alloc(_STD forward<_Fx>(_Func), _Ax); } #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT @@ -1100,9 +1100,9 @@ public: } #if _USE_FUNCTION_INT_0_SFINAE - template &, function> = 0> + template = 0> #else // ^^^ _USE_FUNCTION_INT_0_SFINAE // !_USE_FUNCTION_INT_0_SFINAE vvv - template &, function>> + template > #endif // _USE_FUNCTION_INT_0_SFINAE function& operator=(_Fx&& _Func) { function(_STD forward<_Fx>(_Func)).swap(*this);