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.

 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