Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. // Custom pointer adapter and sample storage policies
  2.  
  3. // Copyright (C) 2008-2013 Free Software Foundation, Inc.
  4. //
  5. // This file is part of the GNU ISO C++ Library.  This library is free
  6. // software; you can redistribute it and/or modify it under the
  7. // terms of the GNU General Public License as published by the
  8. // Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10.  
  11. // This library is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15.  
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. /**
  26.  *  @file ext/pointer.h
  27.  *  This file is a GNU extension to the Standard C++ Library.
  28.  *
  29.  *  @author Bob Walters
  30.  *
  31.  * Provides reusable _Pointer_adapter for assisting in the development of
  32.  * custom pointer types that can be used with the standard containers via
  33.  * the allocator::pointer and allocator::const_pointer typedefs.
  34.  */
  35.  
  36. #ifndef _POINTER_H
  37. #define _POINTER_H 1
  38.  
  39. #pragma GCC system_header
  40.  
  41. #include <iosfwd>
  42. #include <bits/stl_iterator_base_types.h>
  43. #include <ext/cast.h>
  44. #include <ext/type_traits.h>
  45. #if __cplusplus >= 201103L
  46. # include <bits/move.h>
  47. # include <bits/ptr_traits.h>
  48. #endif
  49.  
  50. namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
  51. {
  52. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  53.  
  54.   /**
  55.    * @brief A storage policy for use with _Pointer_adapter<> which yields a
  56.    *        standard pointer.
  57.    *
  58.    *  A _Storage_policy is required to provide 4 things:
  59.    *    1) A get() API for returning the stored pointer value.
  60.    *    2) An set() API for storing a pointer value.
  61.    *    3) An element_type typedef to define the type this points to.
  62.    *    4) An operator<() to support pointer comparison.
  63.    *    5) An operator==() to support pointer comparison.
  64.    */
  65.   template<typename _Tp>
  66.     class _Std_pointer_impl
  67.     {
  68.     public:
  69.       // the type this pointer points to.
  70.       typedef _Tp element_type;
  71.  
  72.       // A method to fetch the pointer value as a standard T* value;
  73.       inline _Tp*
  74.       get() const
  75.       { return _M_value; }
  76.  
  77.       // A method to set the pointer value, from a standard T* value;
  78.       inline void
  79.       set(element_type* __arg)
  80.       { _M_value = __arg; }
  81.  
  82.       // Comparison of pointers
  83.       inline bool
  84.       operator<(const _Std_pointer_impl& __rarg) const
  85.       { return (_M_value < __rarg._M_value); }
  86.  
  87.       inline bool
  88.       operator==(const _Std_pointer_impl& __rarg) const
  89.       { return (_M_value == __rarg._M_value); }
  90.  
  91.     private:
  92.       element_type* _M_value;
  93.     };
  94.  
  95.   /**
  96.    * @brief A storage policy for use with _Pointer_adapter<> which stores
  97.    *        the pointer's address as an offset value which is relative to
  98.    *        its own address.
  99.    *
  100.    * This is intended for pointers within shared memory regions which
  101.    * might be mapped at different addresses by different processes.
  102.    * For null pointers, a value of 1 is used.  (0 is legitimate
  103.    * sometimes for nodes in circularly linked lists) This value was
  104.    * chosen as the least likely to generate an incorrect null, As
  105.    * there is no reason why any normal pointer would point 1 byte into
  106.    * its own pointer address.
  107.    */
  108.   template<typename _Tp>
  109.     class _Relative_pointer_impl
  110.     {
  111.     public:
  112.       typedef _Tp element_type;
  113.  
  114.       _Tp*
  115.       get() const
  116.       {
  117.         if (_M_diff == 1)
  118.           return 0;
  119.         else
  120.           return reinterpret_cast<_Tp*>(reinterpret_cast<_UIntPtrType>(this)
  121.                                         + _M_diff);
  122.       }
  123.  
  124.       void
  125.       set(_Tp* __arg)
  126.       {
  127.         if (!__arg)
  128.           _M_diff = 1;
  129.         else
  130.           _M_diff = reinterpret_cast<_UIntPtrType>(__arg)
  131.                     - reinterpret_cast<_UIntPtrType>(this);
  132.       }
  133.  
  134.       // Comparison of pointers
  135.       inline bool
  136.       operator<(const _Relative_pointer_impl& __rarg) const
  137.       { return (reinterpret_cast<_UIntPtrType>(this->get())
  138.                 < reinterpret_cast<_UIntPtrType>(__rarg.get())); }
  139.  
  140.       inline bool
  141.       operator==(const _Relative_pointer_impl& __rarg) const
  142.       { return (reinterpret_cast<_UIntPtrType>(this->get())
  143.                 == reinterpret_cast<_UIntPtrType>(__rarg.get())); }
  144.  
  145.     private:
  146. #ifdef _GLIBCXX_USE_LONG_LONG
  147.       typedef __gnu_cxx::__conditional_type<
  148.          (sizeof(unsigned long) >= sizeof(void*)),
  149.          unsigned long, unsigned long long>::__type _UIntPtrType;
  150. #else
  151.       typedef unsigned long _UIntPtrType;
  152. #endif
  153.       _UIntPtrType _M_diff;
  154.     };
  155.  
  156.   /**
  157.    * Relative_pointer_impl needs a specialization for const T because of
  158.    * the casting done during pointer arithmetic.
  159.    */
  160.   template<typename _Tp>
  161.     class _Relative_pointer_impl<const _Tp>
  162.     {
  163.     public:
  164.       typedef const _Tp element_type;
  165.  
  166.       const _Tp*
  167.       get() const
  168.       {
  169.         if (_M_diff == 1)
  170.           return 0;
  171.         else
  172.           return reinterpret_cast<const _Tp*>
  173.               (reinterpret_cast<_UIntPtrType>(this) + _M_diff);
  174.       }
  175.  
  176.       void
  177.       set(const _Tp* __arg)
  178.       {
  179.         if (!__arg)
  180.           _M_diff = 1;
  181.         else
  182.           _M_diff = reinterpret_cast<_UIntPtrType>(__arg)
  183.                     - reinterpret_cast<_UIntPtrType>(this);
  184.       }
  185.  
  186.       // Comparison of pointers
  187.       inline bool
  188.       operator<(const _Relative_pointer_impl& __rarg) const
  189.       { return (reinterpret_cast<_UIntPtrType>(this->get())
  190.                 < reinterpret_cast<_UIntPtrType>(__rarg.get())); }
  191.  
  192.       inline bool
  193.       operator==(const _Relative_pointer_impl& __rarg) const
  194.       { return (reinterpret_cast<_UIntPtrType>(this->get())
  195.                 == reinterpret_cast<_UIntPtrType>(__rarg.get())); }
  196.  
  197.     private:
  198. #ifdef _GLIBCXX_USE_LONG_LONG
  199.       typedef __gnu_cxx::__conditional_type<
  200.          (sizeof(unsigned long) >= sizeof(void*)),
  201.          unsigned long, unsigned long long>::__type _UIntPtrType;
  202. #else
  203.       typedef unsigned long _UIntPtrType;
  204. #endif
  205.        _UIntPtrType _M_diff;
  206.     };
  207.  
  208.   /**
  209.    * The specialization on this type helps resolve the problem of
  210.    * reference to void, and eliminates the need to specialize
  211.    * _Pointer_adapter for cases of void*, const void*, and so on.
  212.    */
  213.   struct _Invalid_type { };
  214.  
  215.   template<typename _Tp>
  216.     struct _Reference_type
  217.     { typedef _Tp& reference; };
  218.  
  219.   template<>
  220.     struct _Reference_type<void>
  221.     { typedef _Invalid_type& reference; };
  222.  
  223.   template<>
  224.     struct _Reference_type<const void>
  225.     { typedef const _Invalid_type& reference; };
  226.  
  227.   template<>
  228.     struct _Reference_type<volatile void>
  229.     { typedef volatile _Invalid_type&  reference; };
  230.  
  231.   template<>
  232.     struct _Reference_type<volatile const void>
  233.     { typedef const volatile _Invalid_type&  reference; };
  234.  
  235.   /**
  236.    * This structure accommodates the way in which
  237.    * std::iterator_traits<> is normally specialized for const T*, so
  238.    * that value_type is still T.
  239.    */
  240.   template<typename _Tp>
  241.     struct _Unqualified_type
  242.     { typedef _Tp type; };
  243.    
  244.   template<typename _Tp>
  245.     struct _Unqualified_type<const _Tp>
  246.     { typedef _Tp type; };
  247.    
  248.   /**
  249.    * The following provides an 'alternative pointer' that works with
  250.    * the containers when specified as the pointer typedef of the
  251.    * allocator.
  252.    *
  253.    * The pointer type used with the containers doesn't have to be this
  254.    * class, but it must support the implicit conversions, pointer
  255.    * arithmetic, comparison operators, etc. that are supported by this
  256.    * class, and avoid raising compile-time ambiguities.  Because
  257.    * creating a working pointer can be challenging, this pointer
  258.    * template was designed to wrapper an easier storage policy type,
  259.    * so that it becomes reusable for creating other pointer types.
  260.    *
  261.    * A key point of this class is also that it allows container
  262.    * writers to 'assume' Allocator::pointer is a typedef for a normal
  263.    * pointer.  This class supports most of the conventions of a true
  264.    * pointer, and can, for instance handle implicit conversion to
  265.    * const and base class pointer types.  The only impositions on
  266.    * container writers to support extended pointers are: 1) use the
  267.    * Allocator::pointer typedef appropriately for pointer types.  2)
  268.    * if you need pointer casting, use the __pointer_cast<> functions
  269.    * from ext/cast.h.  This allows pointer cast operations to be
  270.    * overloaded as necessary by custom pointers.
  271.    *
  272.    * Note: The const qualifier works with this pointer adapter as
  273.    * follows:
  274.    *
  275.    * _Tp*             == _Pointer_adapter<_Std_pointer_impl<_Tp> >;
  276.    * const _Tp*       == _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
  277.    * _Tp* const       == const _Pointer_adapter<_Std_pointer_impl<_Tp> >;
  278.    * const _Tp* const == const _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
  279.    */
  280.   template<typename _Storage_policy>
  281.     class _Pointer_adapter : public _Storage_policy
  282.     {
  283.     public:
  284.       typedef typename _Storage_policy::element_type element_type;
  285.  
  286.       // These are needed for iterator_traits
  287.       typedef std::random_access_iterator_tag                iterator_category;
  288.       typedef typename _Unqualified_type<element_type>::type value_type;
  289.       typedef std::ptrdiff_t                                 difference_type;
  290.       typedef _Pointer_adapter                               pointer;
  291.       typedef typename _Reference_type<element_type>::reference  reference;
  292.  
  293.       // Reminder: 'const' methods mean that the method is valid when the
  294.       // pointer is immutable, and has nothing to do with whether the
  295.       // 'pointee' is const.
  296.  
  297.       // Default Constructor (Convert from element_type*)
  298.       _Pointer_adapter(element_type* __arg = 0)
  299.       { _Storage_policy::set(__arg); }
  300.  
  301.       // Copy constructor from _Pointer_adapter of same type.
  302.       _Pointer_adapter(const _Pointer_adapter& __arg)
  303.       { _Storage_policy::set(__arg.get()); }
  304.  
  305.       // Convert from _Up* if conversion to element_type* is valid.
  306.       template<typename _Up>
  307.         _Pointer_adapter(_Up* __arg)
  308.         { _Storage_policy::set(__arg); }
  309.  
  310.       // Conversion from another _Pointer_adapter if _Up if static cast is
  311.       // valid.
  312.       template<typename _Up>
  313.         _Pointer_adapter(const _Pointer_adapter<_Up>& __arg)
  314.         { _Storage_policy::set(__arg.get()); }
  315.  
  316.       // Destructor
  317.       ~_Pointer_adapter() { }
  318.  
  319.       // Assignment operator
  320.       _Pointer_adapter&
  321.       operator=(const _Pointer_adapter& __arg)
  322.       {
  323.         _Storage_policy::set(__arg.get());
  324.         return *this;
  325.       }
  326.  
  327.       template<typename _Up>
  328.         _Pointer_adapter&
  329.         operator=(const _Pointer_adapter<_Up>& __arg)
  330.         {
  331.           _Storage_policy::set(__arg.get());
  332.           return *this;
  333.         }
  334.  
  335.       template<typename _Up>
  336.         _Pointer_adapter&
  337.         operator=(_Up* __arg)
  338.         {
  339.           _Storage_policy::set(__arg);
  340.           return *this;
  341.         }
  342.  
  343.       // Operator*, returns element_type&
  344.       inline reference
  345.       operator*() const
  346.       { return *(_Storage_policy::get()); }
  347.  
  348.       // Operator->, returns element_type*
  349.       inline element_type*
  350.       operator->() const
  351.       { return _Storage_policy::get(); }
  352.  
  353.       // Operator[], returns a element_type& to the item at that loc.
  354.       inline reference
  355.       operator[](std::ptrdiff_t __index) const
  356.       { return _Storage_policy::get()[__index]; }
  357.  
  358.       // To allow implicit conversion to "bool", for "if (ptr)..."
  359.     private:
  360.       typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const;
  361.  
  362.     public:
  363.       operator __unspecified_bool_type() const
  364.       {
  365.         return _Storage_policy::get() == 0 ? 0 :
  366.                          &_Pointer_adapter::operator->;
  367.       }
  368.  
  369.       // ! operator (for: if (!ptr)...)
  370.       inline bool
  371.       operator!() const
  372.       { return (_Storage_policy::get() == 0); }
  373.  
  374.       // Pointer differences
  375.       inline friend std::ptrdiff_t
  376.       operator-(const _Pointer_adapter& __lhs, element_type* __rhs)
  377.       { return (__lhs.get() - __rhs); }
  378.  
  379.       inline friend std::ptrdiff_t
  380.       operator-(element_type* __lhs, const _Pointer_adapter& __rhs)
  381.       { return (__lhs - __rhs.get()); }
  382.  
  383.       template<typename _Up>
  384.         inline friend std::ptrdiff_t
  385.         operator-(const _Pointer_adapter& __lhs, _Up* __rhs)
  386.         { return (__lhs.get() - __rhs); }
  387.    
  388.       template<typename _Up>
  389.         inline friend std::ptrdiff_t
  390.         operator-(_Up* __lhs, const _Pointer_adapter& __rhs)
  391.         { return (__lhs - __rhs.get()); }
  392.  
  393.       template<typename _Up>
  394.         inline std::ptrdiff_t
  395.         operator-(const _Pointer_adapter<_Up>& __rhs) const
  396.         { return (_Storage_policy::get() - __rhs.get()); }
  397.  
  398.       // Pointer math
  399.       // Note: There is a reason for all this overloading based on different
  400.       // integer types.  In some libstdc++-v3 test cases, a templated
  401.       // operator+ is declared which can match any types.  This operator
  402.       // tends to "steal" the recognition of _Pointer_adapter's own operator+
  403.       // unless the integer type matches perfectly.
  404.  
  405. #define _CXX_POINTER_ARITH_OPERATOR_SET(INT_TYPE) \
  406.       inline friend _Pointer_adapter \
  407.       operator+(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
  408.       { return _Pointer_adapter(__lhs.get() + __offset); } \
  409. \
  410.       inline friend _Pointer_adapter \
  411.       operator+(INT_TYPE __offset, const _Pointer_adapter& __rhs) \
  412.       { return _Pointer_adapter(__rhs.get() + __offset); } \
  413. \
  414.       inline friend _Pointer_adapter \
  415.       operator-(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
  416.       { return _Pointer_adapter(__lhs.get() - __offset); } \
  417. \
  418.       inline _Pointer_adapter& \
  419.       operator+=(INT_TYPE __offset) \
  420.       { \
  421.         _Storage_policy::set(_Storage_policy::get() + __offset); \
  422.         return *this; \
  423.       } \
  424. \
  425.       inline _Pointer_adapter& \
  426.       operator-=(INT_TYPE __offset) \
  427.       { \
  428.         _Storage_policy::set(_Storage_policy::get() - __offset); \
  429.         return *this; \
  430.       } \
  431. // END of _CXX_POINTER_ARITH_OPERATOR_SET macro
  432.  
  433.       // Expand into the various pointer arithmetic operators needed.
  434.       _CXX_POINTER_ARITH_OPERATOR_SET(short);
  435.       _CXX_POINTER_ARITH_OPERATOR_SET(unsigned short);
  436.       _CXX_POINTER_ARITH_OPERATOR_SET(int);
  437.       _CXX_POINTER_ARITH_OPERATOR_SET(unsigned int);
  438.       _CXX_POINTER_ARITH_OPERATOR_SET(long);
  439.       _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long);
  440.  
  441.       // Mathematical Manipulators
  442.       inline _Pointer_adapter&
  443.       operator++()
  444.       {
  445.         _Storage_policy::set(_Storage_policy::get() + 1);
  446.         return *this;
  447.       }
  448.  
  449.       inline _Pointer_adapter
  450.       operator++(int)
  451.       {
  452.         _Pointer_adapter tmp(*this);
  453.         _Storage_policy::set(_Storage_policy::get() + 1);
  454.         return tmp;
  455.       }
  456.  
  457.       inline _Pointer_adapter&
  458.       operator--()
  459.       {
  460.         _Storage_policy::set(_Storage_policy::get() - 1);
  461.         return *this;
  462.       }
  463.  
  464.       inline _Pointer_adapter
  465.       operator--(int)
  466.       {
  467.         _Pointer_adapter tmp(*this);
  468.         _Storage_policy::set(_Storage_policy::get() - 1);
  469.         return tmp;
  470.       }
  471.  
  472.     }; // class _Pointer_adapter
  473.  
  474.  
  475. #define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR) \
  476.   template<typename _Tp1, typename _Tp2> \
  477.     inline bool \
  478.     operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
  479.     { return __lhs.get() OPERATOR __rhs; } \
  480. \
  481.   template<typename _Tp1, typename _Tp2> \
  482.     inline bool \
  483.     operator OPERATOR(_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
  484.     { return __lhs OPERATOR __rhs.get(); } \
  485. \
  486.   template<typename _Tp1, typename _Tp2> \
  487.     inline bool \
  488.     operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, \
  489.                               const _Pointer_adapter<_Tp2>& __rhs) \
  490.     { return __lhs.get() OPERATOR __rhs.get(); } \
  491. \
  492. // End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro
  493.  
  494.   // Expand into the various comparison operators needed.
  495.   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==)
  496.   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=)
  497.   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<)
  498.   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=)
  499.   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>)
  500.   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=)
  501.  
  502.   // These are here for expressions like "ptr == 0", "ptr != 0"
  503.   template<typename _Tp>
  504.     inline bool
  505.     operator==(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
  506.     { return __lhs.get() == reinterpret_cast<void*>(__rhs); }
  507.  
  508.   template<typename _Tp>
  509.     inline bool
  510.     operator==(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
  511.     { return __rhs.get() == reinterpret_cast<void*>(__lhs); }
  512.  
  513.   template<typename _Tp>
  514.     inline bool
  515.     operator!=(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
  516.     { return __lhs.get() != reinterpret_cast<void*>(__rhs); }
  517.  
  518.   template<typename _Tp>
  519.     inline bool
  520.     operator!=(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
  521.     { return __rhs.get() != reinterpret_cast<void*>(__lhs); }
  522.  
  523.   /**
  524.    * Comparison operators for _Pointer_adapter defer to the base class'
  525.    * comparison operators, when possible.
  526.    */
  527.   template<typename _Tp>
  528.     inline bool
  529.     operator==(const _Pointer_adapter<_Tp>& __lhs,
  530.                const _Pointer_adapter<_Tp>& __rhs)
  531.     { return __lhs._Tp::operator==(__rhs); }
  532.  
  533.   template<typename _Tp>
  534.     inline bool
  535.     operator<=(const _Pointer_adapter<_Tp>& __lhs,
  536.                const _Pointer_adapter<_Tp>& __rhs)
  537.     { return __lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs); }
  538.  
  539.   template<typename _Tp>
  540.     inline bool
  541.     operator!=(const _Pointer_adapter<_Tp>& __lhs,
  542.                const _Pointer_adapter<_Tp>& __rhs)
  543.     { return !(__lhs._Tp::operator==(__rhs)); }
  544.  
  545.   template<typename _Tp>
  546.     inline bool
  547.     operator>(const _Pointer_adapter<_Tp>& __lhs,
  548.               const _Pointer_adapter<_Tp>& __rhs)
  549.     { return !(__lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs)); }
  550.  
  551.   template<typename _Tp>
  552.     inline bool
  553.     operator>=(const _Pointer_adapter<_Tp>& __lhs,
  554.                const _Pointer_adapter<_Tp>& __rhs)
  555.     { return !(__lhs._Tp::operator<(__rhs)); }
  556.  
  557.   template<typename _CharT, typename _Traits, typename _StoreT>
  558.     inline std::basic_ostream<_CharT, _Traits>&
  559.     operator<<(std::basic_ostream<_CharT, _Traits>& __os,
  560.                const _Pointer_adapter<_StoreT>& __p)
  561.     { return (__os << __p.get()); }
  562.  
  563. _GLIBCXX_END_NAMESPACE_VERSION
  564. } // namespace
  565.  
  566. #if __cplusplus >= 201103L
  567. namespace std _GLIBCXX_VISIBILITY(default)
  568. {
  569. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  570.  
  571.   template<typename _Storage_policy>
  572.     struct pointer_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>>
  573.     {
  574.       /// The pointer type
  575.       typedef __gnu_cxx::_Pointer_adapter<_Storage_policy>         pointer;
  576.       /// The type pointed to
  577.       typedef typename pointer::element_type            element_type;
  578.       /// Type used to represent the difference between two pointers
  579.       typedef typename pointer::difference_type         difference_type;
  580.  
  581.       template<typename _Up>
  582.         using rebind = typename __gnu_cxx::_Pointer_adapter<
  583.         typename pointer_traits<_Storage_policy>::rebind<_Up>>;
  584.  
  585.       static pointer pointer_to(typename pointer::reference __r) noexcept
  586.       { return pointer(std::addressof(__r)); }
  587.     };
  588.  
  589. _GLIBCXX_END_NAMESPACE_VERSION
  590. } // namespace
  591. #endif
  592.  
  593. #endif // _POINTER_H
  594.