Sign in to follow this  

Class template specialization

This topic is 4824 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
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
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

This topic is 4824 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this