public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Implement std::pointer_traits::to_address as per P0653R0
@ 2017-07-16 21:54 Glen Fernandes
  2017-07-18 12:48 ` Jonathan Wakely
  2017-07-20 16:53 ` Jonathan Wakely
  0 siblings, 2 replies; 4+ messages in thread
From: Glen Fernandes @ 2017-07-16 21:54 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 522 bytes --]

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

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 6290 bytes --]

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.

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;
+}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Implement std::pointer_traits::to_address as per P0653R0
  2017-07-16 21:54 [PATCH] Implement std::pointer_traits::to_address as per P0653R0 Glen Fernandes
@ 2017-07-18 12:48 ` Jonathan Wakely
  2017-07-20 16:53 ` Jonathan Wakely
  1 sibling, 0 replies; 4+ messages in thread
From: Jonathan Wakely @ 2017-07-18 12:48 UTC (permalink / raw)
  To: Glen Fernandes; +Cc: libstdc++, gcc-patches

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.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Implement std::pointer_traits::to_address as per P0653R0
  2017-07-16 21:54 [PATCH] Implement std::pointer_traits::to_address as per P0653R0 Glen Fernandes
  2017-07-18 12:48 ` Jonathan Wakely
@ 2017-07-20 16:53 ` Jonathan Wakely
  2017-07-20 18:31   ` Glen Fernandes
  1 sibling, 1 reply; 4+ messages in thread
From: Jonathan Wakely @ 2017-07-20 16:53 UTC (permalink / raw)
  To: Glen Fernandes; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4528 bytes --]

On 16/07/17 17:54 -0400, Glen Fernandes wrote:
>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); }

Much nicer :-)

However, it's unfortunately not that simple. The proposal hasn't been
approved yet, so we can't add "to_address" as a new identifier, and we
certainly can't add it to C++17 or earlier modes, otherwise this valid
C++17 program won't compile:

#define to_address(iter) (&*iter)
#include <memory>
int main() { }

Realistically, I don't think we should be adding this (in this form)
to libstdc++ before it's been approved by the committee. But more on
this at the end of the email.

>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); }

There should be a blank line after this function.

>+    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->()); }

This would need to be guarded by #if __cplusplus > 201707L so it's not
present for C++17 and lower.

>+
>       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; }

#if __cplusplus > 201707L

>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->(); }

#if __cplusplus > 201707L


>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 } }

We can't test a C++20 feature when the effective-target is c++11.

We have a more general problem with this, which is that if it's only
available for C++2a mode then we can't use the new feature in most of
the library. Which would be very unfortunate. I want to use this!

In order to clean up the various places in the library that
could/should use to_address I think we need our own version of it.
Something like our std::__addressof which can be used even for C++98,
and is used by the implementation of the C++11 std::addressof.

The attached patch does something like that. I think I'll commit this,
as it's a small improvement over what we have today. As the design of
P0653 evolves (*) we can revisit the definition of __to_address, to
use pointer_traits, or find user-defined overloads by ADL, or
something else.

(*) there's an active discussion on the LEWG reflector, and Glen said
he's revising the paper.



[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 2576 bytes --]

commit da6aa2c4ba47f91127c3caeb7a851d086b16f3bc
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Jul 20 16:19:53 2017 +0100

    Define std::__to_address helper
    
    	* include/bits/allocated_ptr.h (__allocated_ptr::get): Use
    	__to_address.
    	(__allocated_ptr::_S_raw_ptr): Remove.
    	* include/bits/ptr_traits.h (__to_address): Define new function
    	template.
    	* include/bits/stl_vector.h [__cplusplus >= 201103l]
    	(vector::_M_data_ptr): Use __to_address.

diff --git a/libstdc++-v3/include/bits/allocated_ptr.h b/libstdc++-v3/include/bits/allocated_ptr.h
index 773b3f5..96d7841 100644
--- a/libstdc++-v3/include/bits/allocated_ptr.h
+++ b/libstdc++-v3/include/bits/allocated_ptr.h
@@ -82,16 +82,9 @@ _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::__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..51c4a20 100644
--- a/libstdc++-v3/include/bits/ptr_traits.h
+++ b/libstdc++-v3/include/bits/ptr_traits.h
@@ -146,6 +146,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Ptr, typename _Tp>
     using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
 
+  template<typename _Tp>
+    constexpr _Tp*
+    __to_address(_Tp* __ptr) noexcept
+    { return __ptr; }
+
+  template<typename _Ptr>
+    inline _GLIBCXX14_CONSTEXPR
+    typename std::pointer_traits<_Ptr>::element_type*
+    __to_address(const _Ptr& __ptr)
+    { return std::__to_address(__ptr.operator->()); }
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 7ee3ce9..49f6974 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1561,7 +1561,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       template<typename _Ptr>
 	typename std::pointer_traits<_Ptr>::element_type*
 	_M_data_ptr(_Ptr __ptr) const
-	{ return empty() ? nullptr : std::__addressof(*__ptr); }
+	{ return empty() ? nullptr : std::__to_address(__ptr); }
 #else
       template<typename _Up>
 	_Up*

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Implement std::pointer_traits::to_address as per P0653R0
  2017-07-20 16:53 ` Jonathan Wakely
@ 2017-07-20 18:31   ` Glen Fernandes
  0 siblings, 0 replies; 4+ messages in thread
From: Glen Fernandes @ 2017-07-20 18:31 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On Thu, Jul 20, 2017 at 12:53 PM, Jonathan Wakely wrote:
> We have a more general problem with this, which is that if it's only
> available for C++2a mode then we can't use the new feature in most of
> the library. Which would be very unfortunate. I want to use this!
>
> In order to clean up the various places in the library that
> could/should use to_address I think we need our own version of it.
> Something like our std::__addressof which can be used even for C++98,
> and is used by the implementation of the C++11 std::addressof.
>
> The attached patch does something like that. I think I'll commit this,
> as it's a small improvement over what we have today. As the design of
> P0653 evolves (*) we can revisit the definition of __to_address, to
> use pointer_traits, or find user-defined overloads by ADL, or
> something else.
>
> (*) there's an active discussion on the LEWG reflector, and Glen said
> he's revising the paper.

Sounds good - thanks Jonathan.

I'll revise the patch when P0653 evolves (and approaches acceptance),
and when I do, I'll follow the suggestions and style that you've
mentioned above.

Glen

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-07-20 18:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-16 21:54 [PATCH] Implement std::pointer_traits::to_address as per P0653R0 Glen Fernandes
2017-07-18 12:48 ` Jonathan Wakely
2017-07-20 16:53 ` Jonathan Wakely
2017-07-20 18:31   ` Glen Fernandes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).