Good way of converting user-defined pointers



  • Let us imagine that I have a class which has pointer semantics:

    template<class T> class MyPointer
    { //This class differs from simple pointer by having someAdditionalData
    private:
      T *pointer;
      int someAdditionalData;
    public:
      inline MyPointer(void): pointer(NULL), someAdditionalData(0) {;} //Default constructor
      inline MyPointer(MyPointer<T> const &p): pointer(p.pointer), someAdditionalData(p.someAdditionalData) {;} //Copy constructor
      inline MyPointer(T *const p): pointer(p), someAdditionalData(0) {;} //Custom constructor
      inline MyPointer<T> *operator->(void) const {return pointer;} //Arrow operator
      inline MyPointer<T> &operator*(void) const {return *pointer;} //Dereference operator
      inline int &SomeAdditionalData(void) {return someAdditionalData;} //Really important method
    };
    

    I also have another class which this pointer points to:

    struct ClassToPointTo
    {
      int firstMember;
      int secondMember;
    };
    
    MyPointer<ClassToPointTo> GeneratePointer(void)
    {
      //Some code here which calculates pointer and its someAdditionalData
    }
    
    ...
    
    MyPointer<ClassToPointTo const> const p( GeneratePointer() ); //I really like to write "const" where I can
    

    The first problem is that MyPointer<ClassToPointTo> is not automatically converted into MyPointer<ClassToPointTo const> (I know why, but I don't know how to fix it), and the second, the main problem is following:

    I need to convert pointer p from " ClassToPointTo const " type into one that will point to the firstMember of *p object *without losing someAdditionalData *. I have function GeneratePointer() which will make pointer having someAdditionalData , but I need to work only with pointers to firstMember s of the objects:

    MyPointer<int const> const p( WhatINeedToWriteHere??? GeneratePointer() ??? );
    

    I need fast and good-looking way of doing such conversion.



  • SAn schrieb:

    The first problem is that MyPointer<ClassToPointTo> is not automatically converted into MyPointer<ClassToPointTo const> (I know why, but I don't know how to fix it)

    Maybe like this?

    template <typename T>
    class MyPointer;
    
    template <typename T>
    struct MyPointerConversion
    {
        operator MyPointer<const T>() const
        {
            // ...
        }
    };
    
    template <typename T>
    struct MyPointerConversion<const T>
    {
    };
    
    template <typename T>
    class MyPointer : public MyPointerConversion<T>
    {
        // ...
    };
    

    A conversion constructor doesn't work because you would have to write

    MyPointer(const MyPointer<typename remove_const<T>::type>& origin);
    

    which might have the same signature as the copy constructor ( remove_const is a metafunction that removes the const qualifier from a type).

    Concerning your second problem: Can't it be solved by using a conversion operator (or better a function, to avoid implicit conversions), too?


  • Mod

    Nexus schrieb:

    A conversion constructor doesn't work because you would have to write

    MyPointer(const MyPointer<typename remove_const<T>::type>& origin);
    

    which might have the same signature as the copy constructor ( remove_const is a metafunction that removes the const qualifier from a type).

    sfinae helps

    template <typename U>
    MyPointer(const MyPointer<U>& origin, typename enable_if< is_same< T, const U > >::type* = 0);
    

    A template constructor is never a copy constructor.
    with meta functions is_same and enable_if, which can be found in tr1 or boost.

    derivation could be used as well, T->const T would then involve intentional slicing

    template<class T> class MyPointer : public MyPointer< const T >
    {
    ...
    // hide any functions from base or overload with using, depending on whether constness is supposed to be transitive or not
    };
    
    template <class T> class MyPointer< const T >
    {
    ...
    };
    
    template<class T> class MyPointer
    {
    ...
    // eat any MyPointer and a corresponding pointer to member
        template <typename U, typename V>
        MyPointer(const MyPointer<U>& other, V U::* pm  )
            :  pointer( &( *other ).*pm ), someAdditionalData( other.SomeAdditionalData() )
        {}
    ...
    };
    
    MyPointer<ClassToPointTo const> const p( GeneratePointer(), &ClassToPointTo::firstMember );
    


  • camper schrieb:

    template<class T> class MyPointer
    {
    ...
    // eat any MyPointer and a corresponding pointer to member
        template <typename U, typename V>
        MyPointer(const MyPointer<U>& other, V U::* pm  )
            :  pointer( &( *other ).*pm ), someAdditionalData( other.SomeAdditionalData() )
        {}
    ...
    };
    
    MyPointer<ClassToPointTo const> const p( GeneratePointer(), &ClassToPointTo::firstMember );
    

    Last 2 weeks I trying to understand this but without any success.

    &ClassToPointTo::firstMember
    Such pointers are beyond my understanding.



  • I think this should be an ordinary memberfunction pointer:
    http://www.newty.de/fpt/callback.html#member


  • Mod

    drakon schrieb:

    I think this should be an ordinary memberfunction pointer:
    http://www.newty.de/fpt/callback.html#member

    It could be a pointer to member function if V is a function type, but that would be pointless with regards to the purpose of that class. I was thinking of a pointer to an ordinary non-function member.



  • SAn schrieb:

    I need to convert pointer p from " ClassToPointTo const " type into one that will point to the firstMember of *p object *without losing someAdditionalData *. I have function GeneratePointer() which will make pointer having someAdditionalData , but I need to work only with pointers to firstMember s of the objects:

    MyPointer<int const> const p( WhatINeedToWriteHere??? GeneratePointer() ??? );
    

    I need fast and good-looking way of doing such conversion.

    I'm afraid that particular pig won't fly. At least not without a global map, which again is problematic and/or slow in multi-threaded environments.

    If there were a "good" way (whether eays or not), I'm sure one of the smarter among the C++ community would already have found it, and integrated it into the boost::shared_ptr implementation. (As a way to get a shared_ptr from a raw-pointer, that shares ownership with other existing shared_ptrs.)



  • template<typename T>
    class pointer
    {
      T* ptr;
    public:
      explicit pointer(T* p=0) : ptr(p) {}
    
      T* get() const {return ptr;}
      T* operator->() const {return ptr;}
      T& operator*() const {return *ptr;}
    
      template<typename U>
      pointer(pointer<U> const& x,
        typename boost::enable_if<
          boost::is_convertible<U*,T*>
        >::type* =0)
      : ptr(x.get()) {}
    };
    

    (ungetestet)


Log in to reply