diff mbox

Implement std::pointer_traits::to_address as per P0653R0

Message ID CAHVPgzk5ezf9uhZ+yFsLPZF_PK1TW+aijrJ+6MxM_raDj4RoQg@mail.gmail.com
State New
Headers show

Commit Message

Glen Fernandes July 16, 2017, 9:54 p.m. UTC
Implement pointer_traits::to_address as in P0653r0

        * include/bits/allocated_ptr.h (allocated_ptr): Use
pointer_traits::to_address.
        * include/bits/ptr_traits.h (pointer_traits): Implement to_address.
        * include/ext/pointer.h (pointer_traits): Define to_address in
pointer_traits specialization.
        * testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc:
Define operator->.
        * testsuite/20_util/pointer_traits/to_address.cc: New tests.

Tested i686-pc-linux-gnu.

Glen
commit 7180839baa6dff48dc7a1536a2de0688f79d38dc
Author: Glen Fernandes <glenjofe@gmail.com>
Date:   Sun Jul 16 16:49:18 2017 -0400

    Implement pointer_traits::to_address as in P0653r0
    
    	* include/bits/allocated_ptr.h (allocated_ptr): Use pointer_traits::to_address.
    	* include/bits/ptr_traits.h (pointer_traits): Implement to_address.
    	* include/ext/pointer.h (pointer_traits): Define to_address in pointer_traits specialization.
    	* testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc: Define operator->.
    	* testsuite/20_util/pointer_traits/to_address.cc: New tests.

Comments

Jonathan Wakely July 18, 2017, 12:48 p.m. UTC | #1
On 16/07/17 17:54 -0400, Glen Fernandes wrote:
>Implement pointer_traits::to_address as in P0653r0
>
>        * include/bits/allocated_ptr.h (allocated_ptr): Use
>pointer_traits::to_address.
>        * include/bits/ptr_traits.h (pointer_traits): Implement to_address.
>        * include/ext/pointer.h (pointer_traits): Define to_address in
>pointer_traits specialization.
>        * testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc:
>Define operator->.
>        * testsuite/20_util/pointer_traits/to_address.cc: New tests.
>
>Tested i686-pc-linux-gnu.
>

Thanks, Glen.

As discussed offlist, Glen is completing a copyright assignment and
we'll deal with this patch shortly.
diff mbox

Patch

diff --git a/libstdc++-v3/include/bits/allocated_ptr.h b/libstdc++-v3/include/bits/allocated_ptr.h
index 773b3f5..72e0179 100644
--- a/libstdc++-v3/include/bits/allocated_ptr.h
+++ b/libstdc++-v3/include/bits/allocated_ptr.h
@@ -82,16 +82,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
       /// Get the address that the owned pointer refers to.
-      value_type* get() { return _S_raw_ptr(_M_ptr); }
+      value_type* get()
+      { return std::pointer_traits<pointer>::to_address(_M_ptr); }
 
     private:
-      static value_type* _S_raw_ptr(value_type* __ptr) { return __ptr; }
-
-      template<typename _Ptr>
-	static auto
-	_S_raw_ptr(_Ptr __ptr) -> decltype(_S_raw_ptr(__ptr.operator->()))
-	{ return _S_raw_ptr(__ptr.operator->()); }
-
       _Alloc* _M_alloc;
       pointer _M_ptr;
     };
diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h
index 797e7fc..93e95ad 100644
--- a/libstdc++-v3/include/bits/ptr_traits.h
+++ b/libstdc++-v3/include/bits/ptr_traits.h
@@ -111,6 +111,22 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       pointer_to(__make_not_void<element_type>& __e)
       { return _Ptr::pointer_to(__e); }
 
+    private:
+      template<typename _Tp>
+      static element_type*
+      __to_address(_Tp __p) noexcept
+      { return pointer_traits<_Tp>::to_address(__p); }
+    public:
+      /**
+       *  @brief  Obtain address referenced by a pointer to an object
+       *  @param  __p  A pointer to an object
+       *  @return @c pointer_traits<decltype(Expr)>::to_address(Expr)
+                  where @c Expr is @c __p.operator->()
+      */
+      static element_type*
+      to_address(pointer __p) noexcept
+      { return __to_address(__p.operator->()); }
+
       static_assert(!is_same<element_type, __undefined>::value,
 	  "pointer type defines element_type or is like SomePointer<T, Args>");
     };
@@ -140,6 +156,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static pointer
       pointer_to(__make_not_void<element_type>& __r) noexcept
       { return std::addressof(__r); }
+
+      /**
+       *  @brief  Obtain address referenced by a pointer to an object
+       *  @param  __p  A pointer to an object
+       *  @return @c __p
+      */
+      static element_type*
+      to_address(pointer __p) noexcept { return __p; }
     };
 
   /// Convenience alias for rebinding pointers.
diff --git a/libstdc++-v3/include/ext/pointer.h b/libstdc++-v3/include/ext/pointer.h
index 8432da0..d7ab4e2 100644
--- a/libstdc++-v3/include/ext/pointer.h
+++ b/libstdc++-v3/include/ext/pointer.h
@@ -584,6 +584,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       static pointer pointer_to(typename pointer::reference __r) noexcept
       { return pointer(std::addressof(__r)); }
+
+      static element_type* to_address(pointer __p) noexcept
+      { return __p.operator->(); }
     };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc
index f54f793..a3ab52d 100644
--- a/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc
+++ b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc
@@ -28,12 +28,14 @@  struct P1
   using difference_type = long;
   template<typename U> using rebind = P1<U>;
   static P1 pointer_to(T&) { return {}; }
+  T* operator->() const noexcept { return {}; }
 };
 
 template<typename T>
 struct P2
 {
   static P2 pointer_to(T&) { return {}; }
+  T* operator->() const noexcept { return {}; }
 };
 
 namespace std
diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/to_address.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/to_address.cc
new file mode 100644
index 0000000..3c8cfbd
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pointer_traits/to_address.cc
@@ -0,0 +1,69 @@ 
+// { dg-do run { target c++11 } }
+
+// Copyright (C) 2011-2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct P1
+{
+  typedef int element_type;
+  int* value;
+  explicit P1(int* ptr) noexcept : value(ptr) { }
+  int* operator->() const noexcept { return value; }
+};
+
+struct P2
+{
+  typedef P1::element_type element_type;
+  P1 value;
+  explicit P2(P1 ptr) noexcept : value(ptr) { }
+  P1 operator->() const noexcept { return value; }
+};
+
+void test01()
+{
+  int i = 0;
+  P1 p1( &i );
+  VERIFY( std::pointer_traits<P1>::to_address(p1) == &i );
+}
+
+void test02()
+{
+  int i = 0;
+  P1 p1( &i );
+  P2 p2( p1 );
+  VERIFY( std::pointer_traits<P2>::to_address(p2) == &i );
+}
+
+void test03()
+{
+  int i = 0;
+  VERIFY( std::pointer_traits<int*>::to_address(&i) == &i );
+  VERIFY( std::pointer_traits<const int*>::to_address(&i) == &i );
+  VERIFY( std::pointer_traits<void*>::to_address(&i) == &i );
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}