Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Kranar

Templated operator overloading.

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

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?

Share this post


Link to post
Share on other sites
Advertisement
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]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
I''m still getting that error. I''m using MSVC++ .NET, not 2003.

Could it be a problem with the compiler?

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites

  • 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!