Hi all,
The following (test) program is not working as I expected.
Note: The code is a bit long but is easy to understand: There is a
class Object implementing ref counting. A Ref<T> template (with a full
Ref<Object> specialization) that works like a smart pointer to the
Object-rooted hierarchy. The only way to create Object instances is
via a static factory that returns a Ref<Object> to a heap allocated
object.
#include <iostream>
//Macros.
#ifndef NULL
#define NULL 0
#endif
//Templates.
template<typename T>
class Ref {
public:
//Constructors.
explicit Ref(T* ptr) {
if (NULL == ptr) {
throw "NULL pointer.";
};
this->ptr = ptr;
ptr->incCount();
};
Ref(const Ref& ref) : ptr(ref.getPtr()) {
this->ptr->incCount();
};
//Destructor.
~Ref() {
this->ptr->decCount();
if (0 == this->ptr->getCount()) {
delete this->ptr;
};
this->ptr = NULL;
};
//Descriptors.
T* getPtr() const {
return this->ptr;
};
//Operator protocol.
T& operator*() const {
return *(this->ptr);
}
T* operator->() const {
return this->ptr;
};
private:
T* ptr;
};
//Forward declaration.
class Object;
//Full specialization.
template<>
class Ref<Object> {
public:
//Constructors.
explicit Ref(Object* ptr) {
if (NULL == ptr) {
throw "NULL pointer.";
};
this->ptr = ptr;
ptr->incCount();
};
Ref(const Ref& ref) : ptr(ref.getPtr()) {
this->ptr->incCount();
};
//Destructor.
~Ref() {
this->ptr->decCount();
if (0 == this->ptr->getCount()) {
delete this->ptr;
};
this->ptr = NULL;
};
//Descriptors.
Object* getPtr() const {
return this->ptr;
};
//Operator protocol.
Object& operator*() const {
return *(this->ptr);
}
Object* operator->() const {
return this->ptr;
};
private:
Object* ptr;
};
class Object {
public:
static Ref<Object> create() {
return Ref<Object>(new Object);
};
virtual ~Object() {};
//Reference count helpers.
long getCount() {
return this->count;
};
void incCount() {
this->count++;
};
void decCount() {
this->count--;
};
protected:
//Protect constructors.
Object() : count(0) {};
private:
long count;
//Disallow.
Object(const Object& obj);
Object& operator=(const Object& rhs);
};
int main() {
Ref<Object> ref = Object::create();
std::cout << "Object count: " << ref->getCount() << std::endl;
std::cout << "Object pointer: " << (long)ref.getPtr() <<
std::endl;
Ref<Object> ref1(ref);
std::cout << "Object count: " << ref1->getCount() <<
std::endl;
std::cout << "Object pointer: " << (long)ref1.getPtr() <<
std::endl;
};
Compiling and running is fine and dandy. I get:
Object count: 1
Object pointer: 3082872
Object count: 2
Object pointer: 3082872
But once I replace the copy-constructor in the full specialization
Ref<Object> by the template method
template<typename U>
Ref(const Ref<U>& ref) : ptr(ref.getPtr()) { //Upcast here.
this->ptr->incCount();
};
I get the output
Object count: 1
Object pointer: 3082872
Object count: 1
Object pointer: 3082872
The reference counter is not being updated - although the pointer is
getting assigned. Anyone knows what is wrong with the above template
method? Any ideas?
TIA, best regards,
G. Rodrigues