From 2f1b8558f44a5045401637393643c8c8e2b1ef93 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 13 Feb 2020 20:26:30 +0100 Subject: [PATCH 01/10] Implement construct_at() --- stl/inc/memory | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/stl/inc/memory b/stl/inc/memory index afdfcf91424..fd9addffdbd 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -308,6 +308,20 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, } #endif // _HAS_IF_CONSTEXPR +#if _HAS_CXX20 +template +/* constexpr */ _Ty* construct_at(_Ty* const _Location, _Args_pack&&... _Args) { + return ::new (static_cast(_Location)) _Ty(_STD forward<_Args_pack>(_Args)...); +} + +namespace ranges { + template + /* constexpr */ _Ty* construct_at(_Ty* const _Location, _Args_pack&&... _Args) { + return ::new (static_cast(_Location)) _Ty(_STD forward<_Args_pack>(_Args)...); + } +} // namespace ranges +#endif // _HAS_CXX20 + #if _HAS_CXX17 // FUNCTION TEMPLATE destroy_at template From aa7a66ab85c3707e7a2475bafb1b7235b116b3d2 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Sat, 15 Feb 2020 18:20:28 +0100 Subject: [PATCH 02/10] Fix pointer conversion --- stl/inc/memory | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index fd9addffdbd..8625ffe6c07 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -309,15 +309,15 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, #endif // _HAS_IF_CONSTEXPR #if _HAS_CXX20 -template -/* constexpr */ _Ty* construct_at(_Ty* const _Location, _Args_pack&&... _Args) { - return ::new (static_cast(_Location)) _Ty(_STD forward<_Args_pack>(_Args)...); +template +/* constexpr */ _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { + return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); } namespace ranges { - template - /* constexpr */ _Ty* construct_at(_Ty* const _Location, _Args_pack&&... _Args) { - return ::new (static_cast(_Location)) _Ty(_STD forward<_Args_pack>(_Args)...); + template + /* constexpr */ _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { + return _STD construct_at<_Ty, _Types...>(_Location, _STD forward<_Types>(_Args)...); } } // namespace ranges #endif // _HAS_CXX20 From 2ccb7cab6ad9a7d24cbfa0fac8246d99d284fb80 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Sat, 15 Feb 2020 19:13:40 +0100 Subject: [PATCH 03/10] _CONSTEXPR_NEW --- stl/inc/memory | 4 ++-- stl/inc/yvals_core.h | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 8625ffe6c07..8b8e7b322a5 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -310,13 +310,13 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, #if _HAS_CXX20 template -/* constexpr */ _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { +_CONSTEXPR_NEW _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); } namespace ranges { template - /* constexpr */ _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { + _CONSTEXPR_NEW _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { return _STD construct_at<_Ty, _Types...>(_Location, _STD forward<_Types>(_Args)...); } } // namespace ranges diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 77bc73dd7cc..cd17e807466 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -470,6 +470,12 @@ #define _CONSTEXPR20 inline #endif // ^^^ inline (not constexpr) in C++17 and earlier ^^^ +#if 0 // TRANSITION: #ifdef __cpp_constexpr_dynamic_alloc +#define _CONSTEXPR_NEW constexpr +#else // ^^^__cpp_constexpr_dynamic_alloc / !__cpp_constexpr_dynamic_alloc vvv +#define _CONSTEXPR_NEW inline +#endif // !__cpp_constexpr_dynamic_alloc + // P0607R0 Inline Variables For The STL #if _HAS_CXX17 #define _INLINE_VAR inline From 59ebd802b8441216846660e5bd9f1fe4174e2596 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 20 Feb 2020 17:42:59 +0100 Subject: [PATCH 04/10] Improve debug performance of ranges version --- stl/inc/memory | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/memory b/stl/inc/memory index 8b8e7b322a5..ec4a5300c8b 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -317,7 +317,8 @@ _CONSTEXPR_NEW _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { namespace ranges { template _CONSTEXPR_NEW _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { - return _STD construct_at<_Ty, _Types...>(_Location, _STD forward<_Types>(_Args)...); + return ::new (const_cast(static_cast(_Location))) + _Ty(_STD forward<_Types>(_Args)...); } } // namespace ranges #endif // _HAS_CXX20 From 09cfb869c049d04354ea89d0b4b3c67a17c06fea Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Fri, 21 Feb 2020 13:50:31 +0100 Subject: [PATCH 05/10] Remove _CONSTEXPR_NEW --- stl/inc/memory | 4 ++-- stl/inc/yvals_core.h | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index ec4a5300c8b..4b6ebf21522 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -310,13 +310,13 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, #if _HAS_CXX20 template -_CONSTEXPR_NEW _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { +_Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); } namespace ranges { template - _CONSTEXPR_NEW _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { + _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); } diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index cd17e807466..77bc73dd7cc 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -470,12 +470,6 @@ #define _CONSTEXPR20 inline #endif // ^^^ inline (not constexpr) in C++17 and earlier ^^^ -#if 0 // TRANSITION: #ifdef __cpp_constexpr_dynamic_alloc -#define _CONSTEXPR_NEW constexpr -#else // ^^^__cpp_constexpr_dynamic_alloc / !__cpp_constexpr_dynamic_alloc vvv -#define _CONSTEXPR_NEW inline -#endif // !__cpp_constexpr_dynamic_alloc - // P0607R0 Inline Variables For The STL #if _HAS_CXX17 #define _INLINE_VAR inline From 5eb0ae6f20615652fbfcdb873a13ed24972c640a Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 27 Feb 2020 11:54:04 -0800 Subject: [PATCH 06/10] Deduplicate the "ranges" version, strengthen noexcept on construct_at and destroy_at, and add test. --- stl/inc/memory | 11 ++--- tests/std/test.lst | 1 + .../env.lst | 4 ++ .../test.cpp | 48 +++++++++++++++++++ 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/env.lst create mode 100644 tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp diff --git a/stl/inc/memory b/stl/inc/memory index 57ed12c1518..81ca93a2046 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -310,23 +310,20 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, #if _HAS_CXX20 template -_Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { +_Ty* construct_at(_Ty* const _Location, _Types&&... _Args) noexcept( + is_nothrow_constructible_v<_Ty, _Types...>) /* strengthened */ { return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); } namespace ranges { - template - _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) { - return ::new (const_cast(static_cast(_Location))) - _Ty(_STD forward<_Types>(_Args)...); - } + using _STD construct_at; } // namespace ranges #endif // _HAS_CXX20 #if _HAS_CXX17 // FUNCTION TEMPLATE destroy_at template -void destroy_at(_Ty* const _Location) { // destroy _Ty at memory address _Location +void destroy_at(_Ty* const _Location) noexcept(noexcept(_Location->~_Ty())) /* strengthened */ { _Location->~_Ty(); } diff --git a/tests/std/test.lst b/tests/std/test.lst index e4db82afbca..873da5cdf40 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -221,6 +221,7 @@ tests\P0674R1_make_shared_for_arrays tests\P0758R1_is_nothrow_convertible tests\P0768R1_spaceship_operator tests\P0769R2_shift_left_shift_right +tests\P0784R7_library_support_for_more_constexpr_containers tests\P0811R3_midpoint_lerp tests\P0896R4_P1614R2_comparisons tests\P0896R4_ranges_iterator_machinery diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/env.lst b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp new file mode 100644 index 00000000000..3893f64951b --- /dev/null +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +static_assert(noexcept(std::construct_at(std::declval(), 42))); +static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); +static_assert(noexcept(std::construct_at(std::declval(), 42))); +static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); +static_assert(noexcept(std::construct_at(std::declval(), 42))); +static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); +static_assert(noexcept(std::construct_at(std::declval(), 42))); +static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); + +static_assert(noexcept(std::destroy_at(std::declval()))); +static_assert(noexcept(std::destroy_at(std::declval()))); +static_assert(noexcept(std::destroy_at(std::declval()))); +static_assert(noexcept(std::destroy_at(std::declval()))); +static_assert(noexcept(std::destroy_at(std::declval()))); +static_assert(noexcept(std::destroy_at(std::declval()))); +static_assert(noexcept(std::destroy_at(std::declval()))); +static_assert(noexcept(std::destroy_at(std::declval()))); + +template +void test_runtime(const Ty& _Val) { + alignas(Ty) unsigned char storage[sizeof(Ty)]; + memset(storage, 42, sizeof(Ty)); + const auto asPtrTy = reinterpret_cast(&storage); + std::construct_at(asPtrTy, _Val); + assert(*asPtrTy == _Val); + std::destroy_at(asPtrTy); + + // test voidify: + const auto asCv = static_cast(_AsPtrTy); + std::construct_at(asCv, _Val); + assert(const_cast(*asCv) == _Val); + std::destroy_at(asCv); +} + +int main() { + test_runtime(1234); + test_runtime(std::string("hello world")); + test_runtime(std::string("hello to some really long world that certainly doesn't fit in SSO")); +} From 83007e82402c9359435f8750618786e0e267b525 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 27 Feb 2020 11:57:56 -0800 Subject: [PATCH 07/10] Fix test syntax errors. --- .../test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index 3893f64951b..dd7e05f35ea 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -35,9 +35,9 @@ void test_runtime(const Ty& _Val) { std::destroy_at(asPtrTy); // test voidify: - const auto asCv = static_cast(_AsPtrTy); + const auto asCv = static_cast(asPtrTy); std::construct_at(asCv, _Val); - assert(const_cast(*asCv) == _Val); + assert(const_cast(*asCv) == _Val); std::destroy_at(asCv); } From 8877a1ad86dd02fd53819325af6c9822028238cc Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 27 Feb 2020 22:35:20 -0800 Subject: [PATCH 08/10] Add constraints and other CR feedback. --- stl/inc/memory | 7 +- .../test.cpp | 71 +++++++++++++++++-- 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 5f3819d552e..600f782837c 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -310,8 +310,9 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, #if _HAS_CXX20 template -_Ty* construct_at(_Ty* const _Location, _Types&&... _Args) noexcept( - is_nothrow_constructible_v<_Ty, _Types...>) /* strengthened */ { +auto construct_at(_Ty* const _Location, _Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) + -> decltype( + ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...)) { return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); } @@ -323,7 +324,7 @@ namespace ranges { #if _HAS_CXX17 // FUNCTION TEMPLATE destroy_at template -void destroy_at(_Ty* const _Location) noexcept(noexcept(_Location->~_Ty())) /* strengthened */ { +void destroy_at(_Ty* const _Location) noexcept /* strengthened */ { _Location->~_Ty(); } diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index dd7e05f35ea..b8a3c4b40a6 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -5,8 +5,58 @@ #include #include #include +#include #include +struct X {}; + +template +inline constexpr bool can_construct_at = false; + +template +inline constexpr bool can_construct_at< + std::void_t(), std::declval()...))>, Ty, Types...> = true; + +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); + +static_assert(!can_construct_at); +static_assert(!can_construct_at); + +static_assert(!can_construct_at); // note that references can be constructed by not new'd +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); + +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); + +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); + static_assert(noexcept(std::construct_at(std::declval(), 42))); static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); static_assert(noexcept(std::construct_at(std::declval(), 42))); @@ -25,19 +75,30 @@ static_assert(noexcept(std::destroy_at(std::declval()))); static_assert(noexcept(std::destroy_at(std::declval()))); static_assert(noexcept(std::destroy_at(std::declval()))); +struct throwing_dtor { + ~throwing_dtor() noexcept(false) {} +}; + +static_assert(noexcept(std::destroy_at(std::declval()))); + template -void test_runtime(const Ty& _Val) { +void test_runtime(const Ty& val) { alignas(Ty) unsigned char storage[sizeof(Ty)]; memset(storage, 42, sizeof(Ty)); const auto asPtrTy = reinterpret_cast(&storage); - std::construct_at(asPtrTy, _Val); - assert(*asPtrTy == _Val); + assert(asPtrTy == std::construct_at(asPtrTy, val)); + assert(*asPtrTy == val); + std::destroy_at(asPtrTy); + + // test ranges: + assert(asPtrTy == std::ranges::construct_at(asPtrTy, val)); + assert(*asPtrTy == val); std::destroy_at(asPtrTy); // test voidify: const auto asCv = static_cast(asPtrTy); - std::construct_at(asCv, _Val); - assert(const_cast(*asCv) == _Val); + assert(asPtrTy == std::construct_at(asCv, val)); + assert(const_cast(*asCv) == val); std::destroy_at(asCv); } From e49387bb138debcc8ada12f6f3ef888e800c4cdf Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 28 Feb 2020 15:20:11 -0800 Subject: [PATCH 09/10] More CR feedback, test indestructible. --- stl/inc/memory | 3 +- .../test.cpp | 166 ++++++++++-------- 2 files changed, 96 insertions(+), 73 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 600f782837c..c3bc6e6718c 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -310,7 +310,8 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, #if _HAS_CXX20 template -auto construct_at(_Ty* const _Location, _Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) +auto construct_at(_Ty* const _Location, _Types&&... _Args) noexcept(noexcept(::new (const_cast( + static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...))) // strengthened -> decltype( ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...)) { return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index b8a3c4b40a6..e175d37fd59 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -3,107 +3,129 @@ #include #include +#include #include #include #include #include -struct X {}; +using namespace std; -template -inline constexpr bool can_construct_at = false; +template +inline constexpr bool can_construct_at_impl = false; template -inline constexpr bool can_construct_at< - std::void_t(), std::declval()...))>, Ty, Types...> = true; - -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); - -static_assert(!can_construct_at); -static_assert(!can_construct_at); - -static_assert(!can_construct_at); // note that references can be constructed by not new'd -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); - -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); - -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(!can_construct_at); -static_assert(!can_construct_at); - -static_assert(noexcept(std::construct_at(std::declval(), 42))); -static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); -static_assert(noexcept(std::construct_at(std::declval(), 42))); -static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); -static_assert(noexcept(std::construct_at(std::declval(), 42))); -static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); -static_assert(noexcept(std::construct_at(std::declval(), 42))); -static_assert(!noexcept(std::construct_at(std::declval(), "hello"))); - -static_assert(noexcept(std::destroy_at(std::declval()))); -static_assert(noexcept(std::destroy_at(std::declval()))); -static_assert(noexcept(std::destroy_at(std::declval()))); -static_assert(noexcept(std::destroy_at(std::declval()))); -static_assert(noexcept(std::destroy_at(std::declval()))); -static_assert(noexcept(std::destroy_at(std::declval()))); -static_assert(noexcept(std::destroy_at(std::declval()))); -static_assert(noexcept(std::destroy_at(std::declval()))); +inline constexpr bool + can_construct_at_impl(), declval()...))>, Ty, Types...> = true; + +template +inline constexpr bool can_construct_at = can_construct_at_impl; + +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); + +struct X {}; + +#ifndef __EDG__ // TRANSITION, VSO-1075296 +static_assert(!can_construct_at); +static_assert(!can_construct_at); +#endif // __EDG__ + +// note that indestructible isn't constructible but is construct_at-ible: +struct indestructible { + void destroy() { + this->~indestructible(); + }; + +private: + ~indestructible() = default; +}; + +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); + +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(can_construct_at); + +static_assert(can_construct_at); +static_assert(can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); + +// The following static_asserts test our strengthening of noexcept + +#ifndef __EDG__ // TRANSITION, VSO-1075296 +static_assert(noexcept(construct_at(declval(), 42))); +static_assert(noexcept(construct_at(declval(), 42))); +static_assert(noexcept(construct_at(declval(), 42))); +static_assert(noexcept(construct_at(declval(), 42))); +#endif // __EDG__ + +static_assert(!noexcept(construct_at(declval(), "hello"))); +static_assert(!noexcept(construct_at(declval(), "hello"))); +static_assert(!noexcept(construct_at(declval(), "hello"))); +static_assert(!noexcept(construct_at(declval(), "hello"))); + +static_assert(noexcept(destroy_at(declval()))); +static_assert(noexcept(destroy_at(declval()))); +static_assert(noexcept(destroy_at(declval()))); +static_assert(noexcept(destroy_at(declval()))); +static_assert(noexcept(destroy_at(declval()))); +static_assert(noexcept(destroy_at(declval()))); +static_assert(noexcept(destroy_at(declval()))); +static_assert(noexcept(destroy_at(declval()))); struct throwing_dtor { ~throwing_dtor() noexcept(false) {} }; -static_assert(noexcept(std::destroy_at(std::declval()))); +static_assert(noexcept(destroy_at(declval()))); template void test_runtime(const Ty& val) { alignas(Ty) unsigned char storage[sizeof(Ty)]; memset(storage, 42, sizeof(Ty)); const auto asPtrTy = reinterpret_cast(&storage); - assert(asPtrTy == std::construct_at(asPtrTy, val)); + assert(asPtrTy == construct_at(asPtrTy, val)); assert(*asPtrTy == val); - std::destroy_at(asPtrTy); + destroy_at(asPtrTy); // test ranges: - assert(asPtrTy == std::ranges::construct_at(asPtrTy, val)); + assert(asPtrTy == ranges::construct_at(asPtrTy, val)); assert(*asPtrTy == val); - std::destroy_at(asPtrTy); + destroy_at(asPtrTy); // test voidify: const auto asCv = static_cast(asPtrTy); - assert(asPtrTy == std::construct_at(asCv, val)); + assert(asPtrTy == construct_at(asCv, val)); assert(const_cast(*asCv) == val); - std::destroy_at(asCv); + destroy_at(asCv); } int main() { test_runtime(1234); - test_runtime(std::string("hello world")); - test_runtime(std::string("hello to some really long world that certainly doesn't fit in SSO")); + test_runtime(string("hello world")); + test_runtime(string("hello to some really long world that certainly doesn't fit in SSO")); + + { + alignas(indestructible) unsigned char storage[sizeof(indestructible)]; + const auto ptr = reinterpret_cast(storage); + construct_at(ptr); + ptr->destroy(); + } } From 238205f535b42fe3c2e0fec94a9d3a49ae7c4bbb Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 28 Feb 2020 16:52:28 -0800 Subject: [PATCH 10/10] clang-format --- .../test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index e175d37fd59..733265ddd20 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -18,7 +18,7 @@ template inline constexpr bool can_construct_at_impl(), declval()...))>, Ty, Types...> = true; -template +template inline constexpr bool can_construct_at = can_construct_at_impl; static_assert(can_construct_at);