From: Jonathan Wakely Date: Mon, 14 Jul 2025 10:11:28 +0000 (+0100) Subject: libstdc++: Make all experimental::observer_ptr functions constexpr X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aeeeeef39689cceefbea6b383a3da78e3de016b0;p=thirdparty%2Fgcc.git libstdc++: Make all experimental::observer_ptr functions constexpr I've just created LWG 4295 proposing this change, and am implementing it via this patch. libstdc++-v3/ChangeLog: * include/experimental/memory (swap, make_observer_ptr): Add constexpr. (operator==, operator!=, operator<, operator>, operator<=) (operator>=): Likewise. * testsuite/experimental/memory/observer_ptr/make_observer.cc: Checks for constant evaluation. * testsuite/experimental/memory/observer_ptr/relops/relops.cc: Likewise. * testsuite/experimental/memory/observer_ptr/swap/swap.cc: Likewise. Reviewed-by: Tomasz KamiƄski --- diff --git a/libstdc++-v3/include/experimental/memory b/libstdc++-v3/include/experimental/memory index 131e5acc03d9..1b01462e1b26 100644 --- a/libstdc++-v3/include/experimental/memory +++ b/libstdc++-v3/include/experimental/memory @@ -148,42 +148,42 @@ inline namespace fundamentals_v2 }; // observer_ptr<> template - void + constexpr void swap(observer_ptr<_Tp>& __p1, observer_ptr<_Tp>& __p2) noexcept { __p1.swap(__p2); } template - observer_ptr<_Tp> + constexpr observer_ptr<_Tp> make_observer(_Tp* __p) noexcept { return observer_ptr<_Tp>(__p); } template - bool + constexpr bool operator==(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2) { return __p1.get() == __p2.get(); } template - bool + constexpr bool operator!=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2) { return !(__p1 == __p2); } template - bool + constexpr bool operator==(observer_ptr<_Tp> __p, nullptr_t) noexcept { return !__p; } template - bool + constexpr bool operator==(nullptr_t, observer_ptr<_Tp> __p) noexcept { return !__p; @@ -197,14 +197,14 @@ inline namespace fundamentals_v2 } template - bool + constexpr bool operator!=(nullptr_t, observer_ptr<_Tp> __p) noexcept { return bool(__p); } template - bool + constexpr bool operator<(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2) { return std::less::type, @@ -214,21 +214,21 @@ inline namespace fundamentals_v2 } template - bool + constexpr bool operator>(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2) { return __p2 < __p1; } template - bool + constexpr bool operator<=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2) { return !(__p2 < __p1); } template - bool + constexpr bool operator>=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2) { return !(__p1 < __p2); diff --git a/libstdc++-v3/testsuite/experimental/memory/observer_ptr/make_observer.cc b/libstdc++-v3/testsuite/experimental/memory/observer_ptr/make_observer.cc index 048735ff63ae..1de9cf095092 100644 --- a/libstdc++-v3/testsuite/experimental/memory/observer_ptr/make_observer.cc +++ b/libstdc++-v3/testsuite/experimental/memory/observer_ptr/make_observer.cc @@ -20,12 +20,19 @@ #include #include -int main() +constexpr bool test() { const int i = 42; auto o = std::experimental::make_observer(&i); static_assert( std::is_same>(), "" ); + std::experimental::observer_ptr>(), "" ); VERIFY( o && *o == 42 ); VERIFY( o.get() == &i ); + return true; +} + +int main() +{ + test(); + static_assert( test(), "LWG 4295 - make_observer should be constexpr" ); } diff --git a/libstdc++-v3/testsuite/experimental/memory/observer_ptr/relops/relops.cc b/libstdc++-v3/testsuite/experimental/memory/observer_ptr/relops/relops.cc index 3e23e0b452be..d03dd5dcbd80 100644 --- a/libstdc++-v3/testsuite/experimental/memory/observer_ptr/relops/relops.cc +++ b/libstdc++-v3/testsuite/experimental/memory/observer_ptr/relops/relops.cc @@ -22,13 +22,13 @@ using std::experimental::observer_ptr; -void test01() +constexpr void test01() { observer_ptr a, b; VERIFY(a == b); } -void test02() +constexpr void test02() { int x[2]{}; observer_ptr a{&x[0]}; @@ -40,7 +40,7 @@ void test02() VERIFY(b > a); } -void test03() +constexpr void test03() { int x{}; observer_ptr a{&x}; @@ -48,9 +48,10 @@ void test03() VERIFY(a == b); } -void test04() +int x[2]{}; + +constexpr void test04() { - static constexpr int x[2]{}; constexpr observer_ptr a{&x[0]}; constexpr observer_ptr b{&x[1]}; VERIFY(a != b); @@ -60,20 +61,25 @@ void test04() VERIFY(b > a); } -void test05() +constexpr void test05() { - static constexpr int x{}; - constexpr observer_ptr a{&x}; - constexpr observer_ptr b{&x}; + constexpr observer_ptr a{&x[0]}; + constexpr observer_ptr b{&x[0]}; VERIFY(a == b); } - -int main() +constexpr bool all_tests() { test01(); test02(); test03(); test04(); test05(); + return true; +} + +int main() +{ + all_tests(); + static_assert( all_tests(), "LWG 4295 - relops should be constexpr" ); } diff --git a/libstdc++-v3/testsuite/experimental/memory/observer_ptr/swap/swap.cc b/libstdc++-v3/testsuite/experimental/memory/observer_ptr/swap/swap.cc index 9e7678863512..84b8844af34d 100644 --- a/libstdc++-v3/testsuite/experimental/memory/observer_ptr/swap/swap.cc +++ b/libstdc++-v3/testsuite/experimental/memory/observer_ptr/swap/swap.cc @@ -25,7 +25,7 @@ using std::experimental::observer_ptr; struct B {}; struct D : B {}; -void test01() +constexpr void test01() { observer_ptr a, b; VERIFY(a == b); @@ -33,7 +33,7 @@ void test01() VERIFY(a == b); } -void test02() +constexpr void test02() { int x{}; observer_ptr a; @@ -45,7 +45,7 @@ void test02() VERIFY(!b); } -void test03() +constexpr void test03() { int x[2]{1,2}; observer_ptr a{&x[0]}; @@ -57,10 +57,16 @@ void test03() VERIFY(*b == 1); } - int main() { - test01(); - test02(); - test03(); + auto tests = [] { + test01(); + test02(); + test03(); + return true; + }; + tests(); +#if __cpp_lib_constexpr_algorithms >= 201806L // >= C++20 + static_assert( tests(), "LWG 4295 - swap should be constexpr" ); +#endif }