On Mon, Jul 14, 2025 at 2:00 PM Jonathan Wakely <jwak...@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
>
>

Reply via email to