From 47d877425d6ebb9ba61f062ac32c32cd05b3ddf9 Mon Sep 17 00:00:00 2001
From: Piotr Rak <piotr.rak@gmail.com>
Date: Mon, 19 Jul 2010 03:12:12 +0200
Subject: [PATCH] Add std::pointer_traits.

---
 libstdc++-v3/ChangeLog                             |   14 ++
 libstdc++-v3/include/Makefile.am                   |    1 +
 libstdc++-v3/include/Makefile.in                   |    1 +
 libstdc++-v3/include/bits/ptr_traits.h             |  208 ++++++++++++++++++++
 libstdc++-v3/include/std/memory                    |    1 +
 .../requirements/explicit_instantiation.cc         |   42 ++++
 .../20_util/pointer_traits/requirements/members.cc |   49 +++++
 .../pointer_traits/requirements/typedefs.cc        |  147 ++++++++++++++
 8 files changed, 463 insertions(+), 0 deletions(-)
 create mode 100644 libstdc++-v3/include/bits/ptr_traits.h
 create mode 100644 libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/pointer_traits/requirements/members.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/pointer_traits/requirements/typedefs.cc

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 2d41140..cec9d6e 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,17 @@
+2010-07-20  Piotr Rak  <piotr.rak@gmail.com>
+
+	* include/bits/ptr_traits.h: New.
+	(_DEFINE_HAS_MEMTY, _DEFINE_HAS_MEMTY_AUX, __has_element_type,
+	__ptr_element_type, __has_difference_type, __ptr_difference_type,
+	__has_rebind, __ptr_rebind, pointer_traits): Define.
+	* include/std/memory: Add in C++0x mode.
+	* include/Makefile.am: Add.
+	* include/Makefile.in: Regenerate.
+	* testsuite/20_util/pointer_traits/requirements/
+	explicit-instantionation.cc: New.
+	* testsuite/20_util/pointer_traits/requirements/members.cc: New.
+	* testsuite/20_util/pointer_traits/requirements/typedefs.cc: New.
+
 2010-07-14  Jonathan Wakely  <jwakely.gcc@gmail.com>
 
 	* doc/xml/manual/shared_ptr.xml: Update.
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 6c0230a..96e28fb 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -119,6 +119,7 @@ bits_headers = \
 	${bits_srcdir}/ostream.tcc \
 	${bits_srcdir}/ostream_insert.h \
 	${bits_srcdir}/postypes.h \
+	${bits_srcdir}/ptr_traits.h \
 	${bits_srcdir}/random.h \
 	${bits_srcdir}/random.tcc \
 	${bits_srcdir}/regex.h \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 430f85a..a800c10 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -361,6 +361,7 @@ bits_headers = \
 	${bits_srcdir}/ostream.tcc \
 	${bits_srcdir}/ostream_insert.h \
 	${bits_srcdir}/postypes.h \
+	${bits_srcdir}/ptr_traits.h \
 	${bits_srcdir}/random.h \
 	${bits_srcdir}/random.tcc \
 	${bits_srcdir}/regex.h \
diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h
new file mode 100644
index 0000000..4a171cf
--- /dev/null
+++ b/libstdc++-v3/include/bits/ptr_traits.h
@@ -0,0 +1,208 @@
+// pointer_traits implementation -*- C++ -*-
+
+// Copyright (C) 2010 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ptr_traits.h
+ *  This is an internal header file, included by other library headers.
+ *  You should not attempt to use it directly.
+ */
+
+#ifndef _PTR_TRAITS_H
+#define _PTR_TRAITS_H 1
+
+#include <bits/c++config.h>
+#include <bits/move.h>
+#include <type_traits>
+
+_GLIBCXX_BEGIN_NAMESPACE(std)
+
+#define _DEFINE_HAS_MEMTY_AUX(_Name, _MemType)                          \
+  template <typename _Tp>                                               \
+    struct __has_ ## _Name                                              \
+    : std::__sfinae_types                                               \
+  {                                                                     \
+    template<typename _Tp1>                                             \
+      static __one __test(typename _Tp1::_MemType*);                    \
+                                                                        \
+    template<typename>                                                  \
+      static __two __test(...);                                         \
+                                                                        \
+    static const bool __value = sizeof(__test<_Tp>(nullptr)) == 1;      \
+  };                                                                    
+
+#define _DEFINE_HAS_MEMTY(_MemType)                                     \
+  _DEFINE_HAS_MEMTY_AUX(_MemType, _MemType)
+
+  // __has_element_type
+  _DEFINE_HAS_MEMTY(element_type)
+
+  template<typename _Tp, bool = __has_element_type<_Tp>::__value>
+    struct __ptr_element_type;
+   
+  template<typename _Tp>
+    struct __ptr_element_type<_Tp, true>
+    { typedef typename _Tp::element_type                __type; };
+
+  template<template<typename, typename...> class _Ptr,
+           typename _Tp,
+           typename..._Args>
+    struct __ptr_element_type<_Ptr<_Tp, _Args...>, true>
+    { typedef typename _Ptr<_Tp, _Args...>::element_type __type; };
+
+  template<template<typename, typename...> class _Ptr,
+           typename _Tp,
+           typename... _Args>
+    struct __ptr_element_type<_Ptr<_Tp, _Args...>, false>
+    { typedef _Tp                                       __type; };
+
+  // __has_difference_type
+  _DEFINE_HAS_MEMTY(difference_type)
+
+  template<typename _Tp, bool = __has_difference_type<_Tp>::__value>
+    struct __ptr_difference_type
+    { typedef typename _Tp::difference_type             __type; };
+
+  template<typename _Tp>
+    struct __ptr_difference_type<_Tp, false>
+    { typedef std::ptrdiff_t                            __type; };
+
+  template<typename _Tp, typename _Up>
+    struct __has_rebind
+    : __sfinae_types
+    {
+      template<typename _Tp1>
+        static __one __test(typename _Tp1::template rebind<_Up>*);
+
+      template<typename>
+        static __two __test(...);
+
+      static const bool __value = sizeof(__test<_Tp>(nullptr)) == 1;
+    };
+
+  template<typename _Tp,
+           typename _Up,
+           bool = __has_rebind<_Tp,_Up>::__value>
+  struct __ptr_rebind;
+
+  template<typename _Tp, typename _Up>
+    struct __ptr_rebind<_Tp, _Up, true>
+    {
+#if 0
+      typedef typename _Tp::template rebind<_Up>        __type;
+#else
+      typedef typename _Tp::template rebind<_Up>::other __type;
+#endif
+    };
+
+  template<template<typename, typename...> class _Ptr,
+           typename _Tp,
+           typename _Up,
+           typename... _Args>
+    struct __ptr_rebind<_Ptr<_Tp, _Args...>, _Up, true>
+    {
+#if 0
+      typedef typename _Ptr<_Tp, _Args...>::
+              template rebind<_Up>                      __type;
+#else
+      typedef typename _Ptr<_Tp, _Args...>::
+              template rebind<_Up>::other               __type;
+#endif
+    };
+    
+  template<template<typename, typename...> class _Ptr,
+           typename _Tp,
+           typename _Up,
+           typename... _Args>
+    struct __ptr_rebind<_Ptr<_Tp, _Args...>, _Up, false>
+    { typedef _Ptr<_Up, _Args...>                       __type; };
+
+  /**
+   * @addtogroup pointer_abstractions
+   * @{
+   */
+
+  /// 20.9.3 Primary template, pointer_traits.
+  template<typename _Tp>
+    struct pointer_traits
+    {
+      typedef _Tp                                       pointer;
+      typedef typename 
+        __ptr_element_type<_Tp>::__type                 element_type;
+      typedef typename 
+        __ptr_difference_type<_Tp>::__type              difference_type;
+
+      template<typename _Up>
+#if 0
+        using rebind = __ptr_rebind<_Tp, _Up>::__type;
+#else
+        struct rebind
+        { typedef typename __ptr_rebind<_Tp, _Up>::__type other; };
+#endif
+
+    private:
+      struct __unspecified_type {};
+      typedef typename remove_cv<element_type>::type    _Elem_NoCV;
+
+    public:
+      static pointer pointer_to(typename conditional<is_void<_Elem_NoCV>::value,
+                                                    __unspecified_type,
+                                                    element_type>::type& __r)
+      { return pointer::pointer_to(__r); }
+    };
+
+  /// 20.9.3 pointer_traits, specialization for raw pointers.
+  template<typename _Tp>
+    struct pointer_traits<_Tp*>
+    {
+      typedef _Tp*                                      pointer;
+      typedef _Tp                                       element_type;
+      typedef std::ptrdiff_t                            difference_type;
+
+      template<typename _Up>
+#if 0
+        using rebind = _Up;
+#else
+        struct rebind
+        { typedef _Up*                                  other; };
+#endif
+
+    private:
+      struct __unspecified_type {};
+      typedef typename remove_cv<element_type>::type    _Elem_NoCV;
+
+      // Members.
+    public:
+      static pointer pointer_to(typename conditional<is_void<_Elem_NoCV>::value,
+                                                    __unspecified_type,
+                                                    element_type>::type& __r)
+      { return std::addressof(__r); }
+    };
+
+  /// @} group pointer_abstractions
+
+#undef _DEFINE_HAS_MEMTY
+#undef _DEFINE_HAS_MEMTY_AUX
+
+_GLIBCXX_END_NAMESPACE
+
+#endif /* _PTR_TRAITS_H */ 
diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory
index 3e7d4e8..f070f34 100644
--- a/libstdc++-v3/include/std/memory
+++ b/libstdc++-v3/include/std/memory
@@ -77,6 +77,7 @@
 #  include <ext/atomicity.h>
 #  include <ext/concurrence.h>
 #  include <bits/functexcept.h>
+#  include <bits/ptr_traits.h>
 #  include <bits/stl_function.h>  // std::less
 #  include <type_traits>
 #  include <functional>
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
new file mode 100644
index 0000000..8ee8748
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/explicit_instantiation.cc
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// 2010-07-20  Piotr Rak  <piotr.rak@gmail.com>
+//
+// Copyright (C) 2010 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/>.
+
+// NB: This file is for testing memory with NO OTHER INCLUDES.
+
+#include <memory>
+
+template<typename Tp_, typename...>
+  struct P 
+  {
+    typedef Tp_ element_type;
+
+    static P pointer_to(element_type& r);
+  };
+
+namespace std
+{
+  template class pointer_traits<void*>;
+  template class pointer_traits<int*>;
+  template class pointer_traits<P<int>>;
+  template class pointer_traits<P<int, int>>;
+}
+
diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/members.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/members.cc
new file mode 100644
index 0000000..32c3545
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/members.cc
@@ -0,0 +1,49 @@
+// { dg-options "-std=gnu++0x" }
+// 2010-07-20  Piotr Rak  <piotr.rak@gmail.com>
+//
+// Copyright (C) 2010 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 <type_traits>
+#include <testsuite_hooks.h>
+
+struct P
+{
+  typedef int element_type;
+
+  P(int* p = nullptr)
+  : _p(p)
+  { }
+
+  static P pointer_to(int&)
+  { return &instance; }
+
+  int* _p;
+  static int instance;
+};
+
+int P::instance = 0;
+
+int main()
+{
+  int i;
+
+  VERIFY( std::pointer_traits<int*>::pointer_to(i) == std::addressof(i) );
+  VERIFY( std::pointer_traits<P>::pointer_to(i)._p == &P::instance );
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/typedefs.cc
new file mode 100644
index 0000000..bdad4ee
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pointer_traits/requirements/typedefs.cc
@@ -0,0 +1,147 @@
+// { dg-options "-std=gnu++0x" }
+// 2010-07-20  Piotr Rak  <piotr.rak@gmail.com>
+//
+// Copyright (C) 2010 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 <type_traits>
+#include <testsuite_hooks.h>
+
+template <typename, typename...> struct X { };
+
+struct P0
+{
+  typedef int element_type;
+
+  template<typename>
+#if 0
+  using rebind = int;
+#else
+    struct rebind
+    { typedef int other; };
+#endif
+};
+
+template<typename>
+  struct P1
+  {
+    typedef int element_type;
+    typedef void difference_type;
+  };
+
+template<typename Tp_>
+  struct P2
+  {
+    typedef void difference_type;
+
+    template<typename>
+#if 0
+      using rebind = int;
+#else
+      struct rebind
+      { typedef int other; };
+#endif
+  };
+
+template<typename _Tp, typename...>
+  struct P3
+  {
+    typedef void difference_type;
+  };
+
+
+template<typename Tp_, typename... Args_>
+  struct P4
+  {
+    template<typename Up_>
+#if 0
+      using rebind = X<Up_, Args_..>
+#else
+      struct rebind
+      { typedef X<Up_, Args_...> other; };
+#endif
+  };
+
+void test01()
+{
+  using std::is_same;
+
+  typedef std::pointer_traits<P0>                  pt_0;
+  typedef std::pointer_traits<P1<void>>            pt_1;
+  typedef std::pointer_traits<P2<void>>            pt_2;
+  typedef std::pointer_traits<P3<void, int, int>>  pt_3;
+  typedef std::pointer_traits<P4<void, int, int>>  pt_4;
+
+  VERIFY( (is_same<pt_0::pointer,          P0                >::value) );
+  VERIFY( (is_same<pt_0::element_type,     int               >::value) );
+  VERIFY( (is_same<pt_0::difference_type,  std::ptrdiff_t    >::value) );
+
+  VERIFY( (is_same<pt_1::pointer,          P1<void>          >::value) );
+  VERIFY( (is_same<pt_1::element_type,     int               >::value) );
+  VERIFY( (is_same<pt_1::difference_type,  void              >::value) );
+
+  VERIFY( (is_same<pt_2::pointer,          P2<void>          >::value) );
+  VERIFY( (is_same<pt_2::element_type,     void              >::value) );
+  VERIFY( (is_same<pt_2::difference_type,  void              >::value) );
+
+  VERIFY( (is_same<pt_3::pointer,          P3<void,int, int> >::value) );
+  VERIFY( (is_same<pt_3::element_type,     void              >::value) );
+  VERIFY( (is_same<pt_3::difference_type,  void              >::value) );
+
+  VERIFY( (is_same<pt_4::pointer,          P4<void,int, int> >::value) );
+  VERIFY( (is_same<pt_4::element_type,     void              >::value) );
+  VERIFY( (is_same<pt_4::difference_type,  std::ptrdiff_t    >::value) );
+
+#if 0
+  VERIFY( (is_same<pt_0::rebind<void>, int                >::value) );
+  VERIFY( (is_same<pt_1::rebind<void>, P1<void>           >::value) );
+  VERIFY( (is_same<pt_2::rebind<void>, int                >::value) );
+  VERIFY( (is_same<pt_3::rebind<int>,  P3<int, int, int>  >::value) );
+  VERIFY( (is_same<pt_4::rebind<int>,  X<int, int, int>   >::value) );
+#else
+  VERIFY( (is_same<pt_0::rebind<void>::other, int               >::value) );
+  VERIFY( (is_same<pt_1::rebind<void>::other, P1<void>          >::value) );
+  VERIFY( (is_same<pt_2::rebind<void>::other, int               >::value) );
+  VERIFY( (is_same<pt_3::rebind<int>::other, P3<int, int, int>  >::value) );
+  VERIFY( (is_same<pt_4::rebind<int>::other, X<int, int, int>   >::value) );
+#endif
+
+}
+
+void test02()
+{
+  using std::is_same;
+
+  typedef std::pointer_traits<int*> pt;
+
+  VERIFY( (is_same<pt::pointer,             int*            >::value) );
+  VERIFY( (is_same<pt::element_type,        int             >::value) );
+  VERIFY( (is_same<pt::difference_type,     std::ptrdiff_t  >::value) );
+#if 0
+  VERIFY( (is_same<pt::rebind<void>,        void*           >::value) );
+#else
+  VERIFY( (is_same<pt::rebind<void>::other, void*           >::value) );
+#endif
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
-- 
1.7.1.1

