Jump to content
  • Advertisement
Sign in to follow this  
deks

Class template specialization

This topic is 5039 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to do class template specialization without success... here's some sample code:
template<class T> class ktScopedPtr
{
protected:
    T* m_pPtr;

public:
    ktScopedPtr() : m_pPtr(NULL) {}
    ktScopedPtr(T* pPtr) : m_pPtr(pPtr) {}
    ~ktScopedPtr() { if(m_pPtr) delete m_pPtr; }
    operator T*() { return m_pPtr; }
    T* operator->() { return m_pPtr; }
    void operator=(T* pPtr) { if(m_pPtr) delete m_pPtr; m_pPtr = pPtr; }
};

template<> class ktScopedPtr<kObject>
{
protected:
    kObject* m_pPtr;

public:
    ktScopedPtr() : m_pPtr(NULL) {}
    ktScopedPtr(kObject* pPtr) : m_pPtr(pPtr) {}
    ~ktScopedPtr() { if(m_pPtr) kObject::DeleteObject(m_pPtr); }
    operator kObject*() { return m_pPtr; }
    kObject* operator->() { return m_pPtr; }
    void operator=(kObject* pPtr) { if(m_pPtr) kObject::DeleteObject(m_pPtr); m_pPtr = pPtr; }
};

ktScopedPtr<kObject> WorksFine;
ktScopedPtr<kObjectDerived> DontWork;

Since my kObject class implement delete privatly, for the second declaration I get an error, because it seems to use the general class template instead of using the second. Is there a way to tell the compiler to use the specialized class for all kObject derived objects? Thanks, =[dEkS]=

Share this post


Link to post
Share on other sites
Advertisement
Instead of using a specialization, modify ktScopedPtr to call another function to delete objects:


template <class T>
inline void ScopedPtrDelete(T *ptr)
{
delete ptr;
}

template<class T> class ktScopedPtr
{
protected:
T* m_pPtr;

public:
ktScopedPtr() : m_pPtr(NULL) {}
ktScopedPtr(T* pPtr) : m_pPtr(pPtr) {}
~ktScopedPtr() { if(m_pPtr) ScopedPtrDelete(m_pPtr); }
operator T*() { return m_pPtr; }
T* operator->() { return m_pPtr; }
void operator=(T* pPtr) { if(m_pPtr) ScopedPtrDelete(m_pPtr); m_pPtr = pPtr; }
};


class kObject;

inline void ScopedPtrDelete(kObject *ptr)
{
kObject::DeleteObject(ptr);
}



This should be correctly called for subclasses of kObject, and will handle any other classes you need in the future.

Share this post


Link to post
Share on other sites
As was recommend, I also recommend using argument dependent lookup without specialization.

Another alternative is using SFINAE to include the specialization only when the type is kObject or derived from it. An example of that using boost:

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/mpl/or.hpp>

template< typename T
, typename Enabler = void
>
class ktScopedPtr
{
// Your default implementation
};

template< typename T >
class ktScopedPtr< T
, typename ::boost::enable_if< ::boost::mpl::or_< ::boost::is_same< T
, kObject
>
, ::boost::is_base_and_derived< kObject
, T
>
>
>::type
>
{
// Your specialization goes here
};



If you want only public bases you can use is_convertible with pointers instead of using is_base_and_derived and is_same (is_base_and_derived detects non-public bases as well as public bases).

Again, I still recommend using the other alternative instead of specialization here as it really is uneccessary since all you are doing is depending on a change in a way of deletion.

Share this post


Link to post
Share on other sites
Quote:
Original post by hh10k
Instead of using a specialization, modify ktScopedPtr to call another function to delete objects:

*** Source Snippet Removed ***

This should be correctly called for subclasses of kObject, and will handle any other classes you need in the future.


It still doesn't work. For kObject itself, it works fine, but for kObject derived classes, the compiler seems to fallback to ScopedPtrDelete(T *ptr) instead... Still don't know why.

=[dEkS]=

Share this post


Link to post
Share on other sites
This works fine:


inline void ktScopedPtrDelete(void* pPtr)
{
delete pPtr;
}

inline void ktScopedPtrDelete(kObject* pPtr)
{
ktObject::DeleteObject(pPtr);
}



Thanks all.
=[dEkS]=

Share this post


Link to post
Share on other sites
Quote:
Original post by deks
This works fine:

*** Source Snippet Removed ***

Thanks all.
=[dEkS]=


Nono!!! Don't do that!!! Deleting an object refered to via a void pointer has undefined results. "Best" case scenerio is your object's destructor won't be called. Worst case, your program will die a horrible death at runtime. On just about any compiler, you will never get the results you want.

So, again, remove that call to the void* delete when used with objects, otherwise bad things will happen.

Share this post


Link to post
Share on other sites
Quote:
Original post by Polymorphic OOP
Nono!!! Don't do that!!! Deleting an object refered to via a void pointer has undefined results. "Best" case scenerio is your object's destructor won't be called. Worst case, your program will die a horrible death at runtime. On just about any compiler, you will never get the results you want.

So, again, remove that call to the void* delete when used with objects, otherwise bad things will happen.

You're right, thanks. Any idea then why hh10k suggestion doesn't work?

=[dEkS]=

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!