Skip to main content
gamedev.net
🔒 Locked

Templated operator overloading.

Started by Kranar Jun 2, 2004 at 1:23 PM 8 replies 500+ views
Original Post
Kranar
Kranar
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?
snk_kid
snk_kid
Can you post us your full declaration of type Ptr
3dModelMan
3dModelMan
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]
Kranar
Kranar
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
Kranar
Kranar
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.
snk_kid
snk_kid
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]
Kranar
Kranar
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.
snk_kid
snk_kid
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]
Kranar
Kranar
I''m still getting that error. I''m using MSVC++ .NET, not 2003.

Could it be a problem with the compiler?
snk_kid
snk_kid
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]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.