[PATCH] libstdc++: Make all experimental::observer_ptr functions constexpr
Tomasz Kaminski
tkaminsk@redhat.com
Tue Jul 15 08:27:11 GMT 2025
On Mon, Jul 14, 2025 at 2:00 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> 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.
> ---
>
> Tested x86_64-linux.
>
LGTM. Just P0 the issue.
>
> libstdc++-v3/include/experimental/memory | 22 +++++++--------
> .../memory/observer_ptr/make_observer.cc | 11 ++++++--
> .../memory/observer_ptr/relops/relops.cc | 28 +++++++++++--------
> .../memory/observer_ptr/swap/swap.cc | 20 ++++++++-----
> 4 files changed, 50 insertions(+), 31 deletions(-)
>
> 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<typename _Tp>
> - void
> + constexpr void
> swap(observer_ptr<_Tp>& __p1, observer_ptr<_Tp>& __p2) noexcept
> {
> __p1.swap(__p2);
> }
>
> template<typename _Tp>
> - observer_ptr<_Tp>
> + constexpr observer_ptr<_Tp>
> make_observer(_Tp* __p) noexcept
> {
> return observer_ptr<_Tp>(__p);
> }
>
> template<typename _Tp, typename _Up>
> - bool
> + constexpr bool
> operator==(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
> {
> return __p1.get() == __p2.get();
> }
>
> template<typename _Tp, typename _Up>
> - bool
> + constexpr bool
> operator!=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
> {
> return !(__p1 == __p2);
> }
>
> template<typename _Tp>
> - bool
> + constexpr bool
> operator==(observer_ptr<_Tp> __p, nullptr_t) noexcept
> {
> return !__p;
> }
>
> template<typename _Tp>
> - bool
> + constexpr bool
> operator==(nullptr_t, observer_ptr<_Tp> __p) noexcept
> {
> return !__p;
> @@ -197,14 +197,14 @@ inline namespace fundamentals_v2
> }
>
> template<typename _Tp>
> - bool
> + constexpr bool
> operator!=(nullptr_t, observer_ptr<_Tp> __p) noexcept
> {
> return bool(__p);
> }
>
> template<typename _Tp, typename _Up>
> - bool
> + constexpr bool
> operator<(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
> {
> return std::less<typename common_type<typename
> add_pointer<_Tp>::type,
> @@ -214,21 +214,21 @@ inline namespace fundamentals_v2
> }
>
> template<typename _Tp, typename _Up>
> - bool
> + constexpr bool
> operator>(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
> {
> return __p2 < __p1;
> }
>
> template<typename _Tp, typename _Up>
> - bool
> + constexpr bool
> operator<=(observer_ptr<_Tp> __p1, observer_ptr<_Up> __p2)
> {
> return !(__p2 < __p1);
> }
>
> template<typename _Tp, typename _Up>
> - 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 <experimental/memory>
> #include <testsuite_hooks.h>
>
> -int main()
> +constexpr bool test()
> {
> const int i = 42;
> auto o = std::experimental::make_observer(&i);
> static_assert( std::is_same<decltype(o),
> - std::experimental::observer_ptr<const int>>(), "" );
> + std::experimental::observer_ptr<const int>>(), "" );
> 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<int> a, b;
> VERIFY(a == b);
> }
>
> -void test02()
> +constexpr void test02()
> {
> int x[2]{};
> observer_ptr<int> a{&x[0]};
> @@ -40,7 +40,7 @@ void test02()
> VERIFY(b > a);
> }
>
> -void test03()
> +constexpr void test03()
> {
> int x{};
> observer_ptr<int> 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<const int> a{&x[0]};
> constexpr observer_ptr<const int> 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<const int> a{&x};
> - constexpr observer_ptr<const int> b{&x};
> + constexpr observer_ptr<const int> a{&x[0]};
> + constexpr observer_ptr<const int> 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<int> a, b;
> VERIFY(a == b);
> @@ -33,7 +33,7 @@ void test01()
> VERIFY(a == b);
> }
>
> -void test02()
> +constexpr void test02()
> {
> int x{};
> observer_ptr<int> a;
> @@ -45,7 +45,7 @@ void test02()
> VERIFY(!b);
> }
>
> -void test03()
> +constexpr void test03()
> {
> int x[2]{1,2};
> observer_ptr<int> 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
> }
> --
> 2.50.1
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250715/0cc01533/attachment-0001.htm>
More information about the Libstdc++
mailing list