#ifndef GCC_EXT_POINTER_ #define GCC_EXT_POINTER_ 1 #include // forward declaration of the iterator tag namespace std { struct random_access_iterator_tag; }; _GLIBCXX_BEGIN_NAMESPACE(_gcc_cxx) // The following is the contract that a type must meet to work as the // pointer_impl type for the __pointer template below. Until C++0X, I'm // representing this concept by way of simple examples. template class std_pointer_impl { public: // the type this pointer points to. typedef T pointee; // A method to fetch the pointer value as a standard T* value; T* get() const { return value; } // A method to set the pointer value, from a standard T* value; void set( T* arg ) { value = arg; } private: T* value; }; // The following is a second example impl. This one stores the pointer // value as an ptr_diff value relative to 'this'. This is intended for // pointer within shared memory regions which might be mapped at different // addresses by different processes. template class relative_pointer_impl { public: typedef T pointee; T* get() const { if ( _diff == 1 ) return NULL; else return reinterpret_cast( const_cast(reinterpret_cast(this)) + _diff ); } void set( T* arg ) { if (arg == NULL) _diff = 1; else _diff = reinterpret_cast(arg) - reinterpret_cast(this); } private: ptrdiff_t _diff; }; // Relative_pointer_impl needs a specialization for const T. template class relative_pointer_impl { public: typedef const T pointee; const T* get() const { if ( _diff == 1 ) return NULL; else return reinterpret_cast((reinterpret_cast(this)) + _diff ); } void set( const T* arg ) { if (arg == NULL) _diff = 1; else _diff = reinterpret_cast(arg) - reinterpret_cast(this); } private: ptrdiff_t _diff; }; // The specialization on this type helps resolve the problem of // reference to void, and eliminates the need to specialize __pointer // for cases of void*, const void*, and so on. struct invalid_type { }; template struct reference_type { typedef T& reference; }; template <> struct reference_type { typedef invalid_type& reference; }; template <> struct reference_type { typedef const invalid_type& reference; }; template <> struct reference_type { typedef invalid_type& reference; }; template <> struct reference_type { typedef const invalid_type reference; }; // This structure accomodates the way in which std::iterator_traits<> // is normally specialized for const T*, so that value_type is still T. template struct unqualified_type { typedef T type; }; template struct unqualified_type { typedef T type; }; template struct unqualified_type { typedef volatile T type; }; template struct unqualified_type { typedef volatile T type; }; /** * The following type is a functioning 'alternative pointer' that works with libstdc++-v3 * containers when provided as the pointer typedef of the allocator passed to the container. * The pointer type used with the containers doesn't have to be this class, * but it will have to support the implicit conversions supported by this implementation * without additional ambiguities. Because of that, this pointer template was redesigned * to support an easier impl type, so that it becomes reusable for anyone who wants to * create a custom pointer type of their own. * * Note: The const qualifier works with this pointer type as follows: * * T* == pointer (pointer to mutable T) * const T* == pointer (pointer to immutable T) * T * const == const pointer (immutable pointer to mutable T) * const T * const == const pointer */ template class __pointer { public: typedef typename _pointer_impl::pointee T; // The iterator traits for // These are needed for iterator_traits (see ) typedef std::random_access_iterator_tag iterator_category; typedef typename unqualified_type::type value_type; typedef ptrdiff_t difference_type; typedef __pointer pointer; typedef typename reference_type::reference reference; // Reminder: 'const' methods mean that the method is valid when the pointer // is immutable, and has nothing to do with whether the 'pointee' is const. T* get() const { return _M_impl.get(); } // Default Constructor (Convert from T*) __pointer( T * arg = NULL ) { _M_impl.set( arg ); } // Copy constructor from __pointer of same type. __pointer( const __pointer& arg ) { _M_impl.set( arg.get() ); } // Convert from T2* if conversion to T* is valid. template __pointer( T2 *arg ) { _M_impl.set( static_cast(arg) ); } // Conversion from another __pointer if T2 if static cast is valid. template __pointer( const __pointer& arg ) { _M_impl.set( static_cast(arg.get()) ); } // Destructor ~__pointer() { } // Implicit conversion to T* operator T*() const { return _M_impl.get(); } // Implicit conversion to T2* when T2 is in the same class hierarchy template operator T2*() const { return static_cast( _M_impl.get() ); } // Operator*, returns T& reference operator*() const { return *(_M_impl.get()); } // Operator->, returns T* T* operator->() const { return _M_impl.get(); } // Operator[], returns a T& to the item at that loc. reference operator[](int index) const { return _M_impl.get()[index]; } // ! operator (for: if (!ptr)...) bool operator!() const { return (_M_impl.get()==NULL); } // Each comparison operator needs 3 forms. This is taken from the Loki // smart pointer implementation, with appropriate ambiguity buster. #define COMPARISON_OPERATION_SET(OPERATOR,BLANK) \ template \ inline friend bool operator OPERATOR##BLANK (const __pointer& lhs, T2* rhs) { \ return lhs.get() OPERATOR##BLANK rhs; \ } \ \ template \ inline friend bool operator OPERATOR##BLANK (T2* lhs, const __pointer& rhs) { \ return lhs OPERATOR##BLANK rhs.get(); \ } \ \ template \ inline bool operator OPERATOR##BLANK (const __pointer& rhs) const { \ return _M_impl.get() OPERATOR##BLANK rhs.get(); \ } \ // Expand into the various comparison operators needed. COMPARISON_OPERATION_SET(==,); COMPARISON_OPERATION_SET(!=,); COMPARISON_OPERATION_SET(<,); COMPARISON_OPERATION_SET(<=,); COMPARISON_OPERATION_SET(>,); COMPARISON_OPERATION_SET(>=,); // Pointer differences inline friend std::ptrdiff_t operator-(const __pointer& lhs, const T* rhs) { return (lhs.get() - rhs); } inline friend std::ptrdiff_t operator-(const T* lhs, const __pointer& rhs) { return (lhs - rhs.get()); } template inline friend std::ptrdiff_t operator-(const __pointer& lhs, const T2* rhs) { return (lhs.get() - rhs); } template inline friend std::ptrdiff_t operator-(const T2* lhs, const __pointer& rhs) { return (lhs - rhs.get()); } template inline std::ptrdiff_t operator-(const __pointer& rhs) const { return (_M_impl.get() - rhs.get()); } // Pointer math // Note: There is a reason for all this overloading based on different // integer types. In some libstdc++-v3 test cases, a templated // operator+ is declared which can match anything. This templated operator // tends to "steal" the recognition of these operator+ unless the integer // type matches perfectly. #define POINTER_ARITH_OPERATOR_SET(INT_TYPE) \ inline friend __pointer operator+ ( const __pointer& lhs, INT_TYPE offset) { \ return __pointer(lhs.get()+offset); \ } \ \ inline friend __pointer operator+ ( INT_TYPE offset, const __pointer& rhs) { \ return __pointer(rhs.get()+offset); \ } \ \ inline friend __pointer operator- ( const __pointer& lhs, INT_TYPE offset) { \ return __pointer(lhs.get()-offset); \ } \ \ inline friend __pointer operator- ( INT_TYPE offset, const __pointer& lhs) { \ return __pointer(lhs.get()-offset); \ } \ \ __pointer& operator+= ( INT_TYPE offset) { \ _M_impl.set( _M_impl.get() + offset ); \ return *this; \ } \ \ __pointer& operator-= ( INT_TYPE offset) { \ _M_impl.set( _M_impl.get() - offset ); \ return *this; \ } \ // Expand into the various pointer arithmatic operators needed. POINTER_ARITH_OPERATOR_SET(int); POINTER_ARITH_OPERATOR_SET(unsigned int); POINTER_ARITH_OPERATOR_SET(long); POINTER_ARITH_OPERATOR_SET(unsigned long); // Mathematical Manipulators __pointer& operator++ () { _M_impl.set( _M_impl.get() + 1 ); return *this; } __pointer& operator++ ( int n) { _M_impl.set( _M_impl.get() + n ); return *this; } __pointer& operator-- () { _M_impl.set( _M_impl.get() - 1 ); return *this; } __pointer& operator-- ( int n) { _M_impl.set( _M_impl.get() - n ); return *this; } private: _pointer_impl _M_impl; }; // class __pointer // specialization of cast_to for __pointer template class __cast_to< __pointer<_impl> > { typedef typename _impl::pointee T; typedef _gcc_cxx::__pointer<_impl> pointer; public: template static pointer using_static_cast(StdPtr s) { return pointer( static_cast(s)); } template static pointer using_static_cast(__pointer &s) { return pointer( static_cast(s.get()) ); } template static pointer using_reinterpret_cast(StdPtr s) { return pointer( reinterpret_cast(s) ); } template static pointer using_reinterpret_cast(__pointer &s) { return pointer( reinterpret_cast(s.get()) ); } template static pointer using_const_cast(StdPtr s) { return pointer( const_cast(s) ); } template static pointer using_const_cast(__pointer &s) { return pointer( const_cast( s.get() ) ); } template static pointer using_dynamic_cast(StdPtr s) { return pointer( dynamic_cast(s) ); } template static pointer using_dynamic_cast(__pointer &s) { return pointer( dynamic_cast(s.get()) ); } }; _GLIBCXX_END_NAMESPACE #endif /* GCC_EXT_POINTER_ */