0

Requisite explanation: I have to use C++98, no choice, yes I have asked my chip vendor for an updated toochain, no I will not be getting C++11 anytime soon (cry).

Problem: I have implemented my own shared pointer (queue rants on why I should not do that) based on this. However, I am having trouble implementing my own dynamic_pointer_cast function, or, at least, I am having trouble getting my implementation to link properly.

Here is my code (in a header file) implementation:

#ifndef __SMART_POINTER_HEADER__
#define __SMART_POINTER_HEADER__

class RC
{
    private:
        int count; // Reference count

    public:
        void AddRef()
        {
            // Increment the reference count
            __sync_add_and_fetch( &count, 1 );
        }

        int Release()
        {
            // Decrement the reference count and
            // return the reference count.
            return __sync_sub_and_fetch( &count, 1 );
        }
};

template < typename T > class SmartPointer
{
    private:
        T* pData;       // pointer
        RC* reference; // Reference count

    public:
        SmartPointer() : pData( 0 ), reference( 0 )
        {
            // Create a new reference
            reference = new RC();
            // Increment the reference count
            reference->AddRef();
        }

        SmartPointer( T* pValue ) : pData( pValue ), reference( 0 )
        {
            // Create a new reference
            reference = new RC();
            // Increment the reference count
            reference->AddRef();
        }

        SmartPointer( const SmartPointer<T>& sp ) : pData( sp.pData ), reference( sp.reference )
        {
            // Copy constructor
            // Copy the data and reference pointer
            // and increment the reference count
            reference->AddRef();
        }

        ~SmartPointer()
        {
            // Destructor
            // Decrement the reference count
            // if reference become zero delete the data
            if ( reference->Release() == 0 )
            {
                delete pData;
                delete reference;
            }
        }

        T& operator* ()
        {
            return *pData;
        }

        T* operator-> ()
        {
            return pData;
        }

        SmartPointer<T>& operator = ( const SmartPointer<T>& sp )
        {
            // Assignment operator
            if ( this != &sp ) // Avoid self assignment
            {
                // Decrement the old reference count
                // if reference become zero delete the old data
                if ( reference->Release() == 0 )
                {
                    delete pData;
                    delete reference;
                }

                // Copy the data and reference pointer
                // and increment the reference count
                pData = sp.pData;
                reference = sp.reference;
                reference->AddRef();
            }

            return *this;
        }

        bool operator ! () const
        {
            return ( NULL != reference );
        }

        bool operator == ( const SmartPointer<T>& other )
        {
            return( reference == other.reference );
        }

        bool operator == ( void * other )
        {
            return( reference == other );
        }

        bool operator != ( const SmartPointer<T>& other )
        {
            return( reference != other.reference );
        }

        bool operator != ( void * other )
        {
            return( reference != other );
        }

        template <class Y, class U> friend SmartPointer<Y> dynamic_smart_pointer_cast( const SmartPointer<U>& sp );
};

template <class T, class U> SmartPointer<T> dynamic_smart_pointer_cast ( const SmartPointer<U *>& sp )
{
    SmartPointer<T> new_sp;
    new_sp.pData = dynamic_cast<T*>( sp.pData );

    if( NULL != new_sp.pData )
    {
        delete new_sp.pData;
        delete new_sp.reference;
        sp.reference->addRef();
        new_sp.pData = sp.pData;
        new_sp.reference = sp.reference;
    }

    return new_sp;
}

#endif

Please let me know if you see any issues in the SmartPointer, I basically copied it from here and added the missing functions I needed.

My problem is that when I call dynamic_smart_pointer_cast with:

dynamic_smart_pointer_cast< BaseClass >( DerivedClassInstance )

The linker outputs:

undefined reference to `SmartPointer<BaseClass> dynamic_smart_pointer_cast<BaseClass, DerivedClass>(SmartPointer<DerivedClass> const&)'

I have put the definition for the template function in the included header file so I am not sure why I would be getting this linker error. Does anyone know what my problem might be?

Also feel free to review my dynamic_smart_pointer_cast code as I am fairly sure it can be improved and likely has issues.

user4581301
  • 33,082
  • 7
  • 33
  • 54
Nathan Owen
  • 155
  • 10
  • I think you could compile C++1x to Plain C via LLVM or something. https://stackoverflow.com/questions/1833484/c-frontend-only-compiler-convert-c-to-c – Minor Threat Jan 13 '18 at 00:10
  • 1
    Any identifier with double underscores is reserved for the standard library. It's unlikely that you'll feel the sting of breaking this rule, but when you do, holy smurf are the errors bizarre. More details here: https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – user4581301 Jan 13 '18 at 00:11
  • I am aware user4581301, the code base I write in is very old and uses double underscores for all header guards, probably something we should change but it would need to be removed in about 300 files which are 5+ years old. We are sticking to the old format for consistency at this point. – Nathan Owen Jan 13 '18 at 01:10

1 Answers1

2

In:

dynamic_smart_pointer_cast ( const SmartPointer<U *>& sp )

get rid of the * inside the <>

SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23