Templated operator overloading.

Started by
8 comments, last by Kranar 19 years, 10 months ago
Basically I''m working on a pointer wrapper template with parameter T, but I want to be able to convert from the template to a pointer. So I overloaded the operator T* () and it works fine when converting to a pointer of the same type, but when converting to a pointer of another type, obviously it won''t work because no conversion operator is defined. So I decided to overload the () operator using a template as follows:

template<class cType> operator cType* () {
   return (cType*)(ptr);
}
But now my compiler doesn''t seem to be using it. For example this won''t work:

Ptr<void> x(new int());
int* y = (int*)(x);
Any ideas on how to get it to do what I want?
Advertisement
Can you post us your full declaration of type Ptr
It looks like you're creating the wrong operator *

Since you want it to return the templated type (T) then it should be;

template  T & operator * (){  return *ptr; // since ptr is probably a T * right?} 


So your code works the same way as a normal pointer;

Ptr x;*x = 25;int t = *ptr; 



[edited by - matibee on June 2, 2004 2:47:26 PM]
Here it is, the Ptr void is a specialization of the Ptr template and is at the bottom.

#pragma once#ifndef _PTR_#define _PTR_#define NULL 0#include <conio.h>#include <iostream>using namespace std;struct Counter {	void*   ptr;    int		count;	Counter(const void* p, int c = 1) : count(c) {		ptr = (void*)(p);	}};template<class T> class Ptr {public:	Ptr(T* p = NULL) : counter(NULL) {		if(p != NULL) {			counter = new Counter(p);		}	}	Ptr(const Ptr<T>& r) {		setPtr(r.counter);	}	~Ptr(void) {		release();	}	int getCount() const {		if(counter == NULL) {			return 0;		} else {			return counter->count;		}	}	void release() {		if(counter != NULL) {			(counter->count)--;			if(counter->count == 0) {				delete counter->ptr;				delete counter;			}			counter = NULL;		}	}	Counter* getCounter() const {		return counter;	}		void setPtr(Counter* c) {		counter = c;		if(c != NULL) {			c->count++;		}	}	T& operator*() const {		if(counter != NULL) {			return *((T*)(counter->ptr));		} else {			return *((T*)(NULL));		}	}	T* operator->() const {		return (T*)(counter->ptr);	}	bool operator==(const T* rhs) const {		if(counter == NULL) {			return rhs == NULL;		} else {			return counter->ptr == (void*)(rhs);		}	}	template<class cType> operator cType* () {		if(counter == NULL) {			return NULL;		} else {			return (cType*)(counter->ptr);		}	}	bool operator!=(const T* rhs) const {		return !(*this == rhs);	}		template<class convertType> bool operator==(const Ptr<convertType> rhs) const {		if(counter == NULL) {			return rhs.getCounter() == NULL || rhs.getCounter()->ptr == NULL;		} else {			return rhs.getCounter() != NULL && counter->ptr == rhs.getCounter()->ptr;		}	}	template<class convertType> bool operator!=(const Ptr<convertType> rhs) const {		return !(*this == rhs);	}	Ptr& operator=(const Ptr<T>& rhs) {	    if(this != &rhs) {			release();			setPtr(rhs.getCounter());	    }	    return *this;	}	template<class convertType>	Ptr& operator=(const Ptr<convertType>& rhs) {	    if((void*)(this) != (void*)(&rhs)) {			release();			setPtr(rhs.getCounter());	    }	    return *this;	}	Ptr& operator=(const T* rhs) {		release();		if(rhs != NULL) {			counter = new Counter(rhs);		}		return *this;	}private:	Counter*	counter;};template<> class Ptr<void> {public:	Ptr(void* p = NULL) : counter(NULL) {		if(p != NULL) {			counter = new Counter(p);		}	}		Ptr(const Ptr<void>& r) {		setPtr(r.counter);	}	~Ptr(void) {		release();	}	int getCount() const {		if(counter == NULL) {			return 0;		} else {			return counter->count;		}	}	void release() {		if(counter != NULL) {			(counter->count)--;			if(counter->count == 0) {				delete counter->ptr;				delete counter;			}			counter = NULL;	    }	}	Counter* getCounter() const {		return counter;	}	void setPtr(Counter* c) {		counter = c;		if(c != NULL) {			c->count++;		}	}	template<class cType> operator cType* () {		if(counter == NULL) {			return NULL;		} else {			return (cType*)(counter->ptr);		}	}	bool operator==(const void* rhs) const {		if(counter == NULL) {			return rhs == NULL;		} else {			return counter->ptr == rhs;		}	}	bool operator!=(const void* rhs) const {		return !(*this == rhs);	}		template<class convertType> bool operator==(const Ptr<convertType> rhs) const {		if(counter == NULL) {			return rhs.getCounter() == NULL || rhs.getCounter()->ptr == NULL;		} else {			return rhs.getCounter() != NULL && counter->ptr == rhs.getCounter()->ptr;		}	}	template<class convertType> bool operator!=(const Ptr<convertType> rhs) const {		return !(*this == rhs);	}	Ptr& operator=(const Ptr<T>& rhs) {	    if(this != &rhs) {			release();			setPtr(rhs.getCounter());	    }	    return *this;	}	template<class convertType>	Ptr& operator=(const Ptr<convertType>& rhs) {	    if((void*)(this) != (void*)(&rhs)) {			release();			setPtr(rhs.getCounter());	    }	    return *this;	}	Ptr& operator=(const void* rhs) {		release();		if(rhs != NULL) {			counter = new Counter(rhs);		}		return *this;	}private:	Counter*	counter;};template<class T, class U> Ptr<T> cast(Ptr<U>& c) {	Ptr<T> rVal;	rVal.setPtr(c.getCounter());	return rVal;}#endif
quote:Original post by matibee
It looks like you''re creating the wrong operator *

Since you want it to return the templated type (T) then it should be;

template  T * operator * (){  return ptr; // since ptr is probably a T * right?}    


No, not nessecarily. Your code is what I initially used, but then my pointer wrapper won''t have any support for polymorphism, making it all but useless.
Okay i've fixed your code:

ptr.hpp
#ifndef _PTR_#define _PTR_#include <cstdlib>template<class T>struct Counter {	T* ptr;    int count;    	Counter(const T* p, const int c = 1) : count(c), ptr(const_cast< T* >(p)) {}};template<class T> class Ptr {public:    Ptr(const T* p = NULL) : counter(NULL) {        if(p != NULL) {            counter = new Counter<T>(p);		}	}    Ptr(const Ptr<T>& r) {        setPtr(r.counter);	}    ~Ptr() {        release();    }    int getCount() const {        if(counter == NULL) {            return 0;        } else {            return counter->count;		}	}    void release() {        if(counter != NULL) {            (counter->count)--;            if(counter->count == 0) {                delete counter->ptr;                delete counter;            }            			counter = NULL;		}	}    const Counter<T>* getCounter() const {        return counter;	}	Counter<T>* getCounter() {		return counter;	}    void setPtr(Counter<T>* c) {        counter = c;        if(c != NULL) {            c->count++;		}	}    const T& operator*() const {        if(counter != NULL) {            return *(reinterpret_cast<const T*>(counter->ptr));		} else {            return *(reinterpret_cast<const T*>(NULL));		}	}	T& operator*() {        if(counter != NULL) {            return *(reinterpret_cast<T*>(counter->ptr));		} else {            return *(reinterpret_cast<T*>(NULL));		}	}    const T* operator->() const {        return reinterpret_cast<const T*>(counter->ptr);	}	T* operator->() const {        return reinterpret_cast<T*>(counter->ptr);	}    const bool operator==(const T* rhs) const {        if(counter == NULL) {            return rhs == NULL;        } else {            return counter->ptr == reinterpret_cast<void*>(rhs);		}	}    template<class cType> operator cType* () {        if(counter == NULL) {            return NULL;        } else {            return reinterpret_cast<cType*>(counter->ptr);		}	}	template<class cType> operator const cType* () const {        if(counter == NULL) {            return NULL;        } else {            return reinterpret_cast<const cType*>(counter->ptr);		}	}    const bool operator!=(const T* rhs) const {        return !(*this == rhs);	}    template<class convertType> bool operator==(const Ptr<convertType> rhs) const {        if(counter == NULL) {            return rhs.getCounter() == NULL || rhs.getCounter()->ptr == NULL;        } else {            return rhs.getCounter() != NULL && counter->ptr == rhs.getCounter()->ptr;		}	}    template<class convertType> bool operator!=(const Ptr<convertType> rhs) const {        return !(*this == rhs);    }    Ptr& operator=(const Ptr<T>& rhs) {        if(this != &rhs) {            release();            setPtr(rhs.getCounter());		}        return *this;	}		template<class convertType> Ptr& operator=(const Ptr<convertType>& rhs) {        if(reinterpret_cast<void*>(this) != reinterpret_cast<void*>(&rhs)) {            release();            setPtr(rhs.getCounter());		}        return *this;	}    Ptr& operator=(const T* rhs) {        release();        if(rhs != NULL) {            counter = new Counter<T>(rhs);		}        return *this;	}    private:    Counter<T>* counter;};template<> class Ptr<void> {public:    Ptr(void* p = NULL) : counter(NULL) {        if(p != NULL) {            counter = new Counter<void>(p);		}	}		Ptr(const Ptr<void>& r) {        setPtr(r.counter);	}    ~Ptr() {        release();	}    int getCount() const {        if(counter == NULL) {            return 0;        } else {            return counter->count;		}	}    void release() {        if(counter != NULL) {            (counter->count)--;             if(counter->count == 0) {                 delete counter->ptr;                 delete counter;              }             counter = NULL;		}	}    const Counter<void>* getCounter() const {        return counter;	}	Counter<void>* getCounter() {        return counter;	}    void setPtr(Counter<void>* c) {        counter = c;        if(c != NULL) {            c->count++;		}	}    	template<class cType> operator const cType* () const {        if(counter == NULL) {            return NULL;		} else {            return reinterpret_cast<const cType*>(counter->ptr);		}	}	template<class cType> operator cType* () {        if(counter == NULL) {            return NULL;		} else {            return reinterpret_cast<cType*>(counter->ptr);;		}	}    const bool operator==(const void* rhs) const {        if(counter == NULL) {            return rhs == NULL;        } else {            return counter->ptr == rhs;		}	}    const bool operator!=(const void* rhs) const {        return !(*this == rhs);	}    template<class convertType> bool operator==(const Ptr<convertType> rhs) const {        if(counter == NULL) {            return rhs.getCounter() == NULL || rhs.getCounter()->ptr == NULL;        } else {            return rhs.getCounter() != NULL && counter->ptr == rhs.getCounter()->ptr;		}	}    template<class convertType> bool operator!=(const Ptr<convertType> rhs) const {        return !(*this == rhs);	}    Ptr& operator=(const Ptr<void>& rhs) {        if(this != &rhs) {            release();            setPtr(const_cast< Counter<void>* >(rhs.getCounter()));		}		return *this;	}    template<class convertType> Ptr& operator=(const Ptr<convertType>& rhs) {        if(reinterpret_cast<void*>(this) != reinterpret_cast<void*>(&rhs)) {            release();            setPtr(rhs.getCounter());		}        return *this;	}    Ptr& operator=(const void* rhs) {        release();        if(rhs != NULL) {            counter = new Counter<void>(rhs);		}        return *this;	}private:    Counter<void>* counter;};template<class T, class U> Ptr<T> cast(Ptr<U>& c) {    Ptr<T> rVal;    rVal.setPtr(c.getCounter());    return rVal;}#endif


main.cpp
#include "ptr.h"#include <cstdlib>#include <iostream>int main() {	Ptr<void> x(new int(55));	int* y = x;	std::cout << *y << std::endl;	return EXIT_SUCCESS;}

I just wonted to mentioned a thew things also, in Counter you don't need to use void pointer your already using templates you can use the parameter. Also if you declare a method as constant one you stating your not modifing the state of the object but your returning non constant reference/pointers of members which will modifiy the state outside.

what you normally do is provide overloaded constant and non constant versions of a method like so:

template<class cType> operator const cType*() const {        return reinterpret_cast<const cType*>(ptr);}template<class cType> operator cType*() {        return reinterpret_cast<cType*>(ptr);}


Also if your using C++ you should try to avoid using C style casts at all costs, use the 4 c++ cast operators like i've done in the above.

[edited by - snk_kid on June 2, 2004 3:55:07 PM]
Thanks very much for your tips.

I copied and pasted your code exactly as is into MSVC .NET and unfortunately I''m getting the same error as before:

c:\Generation-X\Smart Pointer\main.cpp(12): error C2440: ''static_cast'' : cannot convert from ''Ptr'' to ''int *''
with
[
T=void
]

I don''t understand why.
Sorry i made a couple of little mistakes, for one, once you've defined a cast operator you shouldn't need to use an explicit cast, i just updated the all of the code above, i compiled it on VC++ .NET 2003 and on GCC 3.4. VC++ .NET 2003 gives me no errors or warnings but GCC gives me a 1 warning about in your specialization but compiles and runs fine, please re-copy paste try again and post your results.

[edited by - snk_kid on June 2, 2004 3:59:03 PM]
I''m still getting that error. I''m using MSVC++ .NET, not 2003.

Could it be a problem with the compiler?
Most probably, there was some problems with that version VS and they never provided any service packs and went straight to 2003. You can download the VC++ .NET 2003 compiler for free but no IDE, so you might be able to download that and use it with VC++ .NET IDE.

[edited by - snk_kid on June 2, 2004 4:20:22 PM]

This topic is closed to new replies.

Advertisement