469,963 Members | 1,317 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,963 developers. It's quick & easy.

template method question

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
Jul 22 '05 #1
6 1417
Gonçalo Rodrigues wrote in news:of********************************@4ax.com
in comp.lang.c++:
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();
};


Its called a converting constructor and it doesn't implement
the copy constructor, when the compiler need to copy it will
use the implicitly generated (memberwise) copy constructor.

Leave the copy constructor in place and *add* this converting
constructor.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #2
On 19 Nov 2004 19:12:21 GMT, Rob Williscroft <rt*@freenet.co.uk>
wrote:
Gonçalo Rodrigues wrote in news:of********************************@4ax.com
in comp.lang.c++:
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();
};

Its called a converting constructor and it doesn't implement
the copy constructor, when the compiler need to copy it will
use the implicitly generated (memberwise) copy constructor.


Ahhh... understood.
Leave the copy constructor in place and *add* this converting
constructor.


Thanks, adding the template method (instead of replacing) does make
the output right.

Another question: I'd assume that, since if not implemented the
compiler also synthesizes an operator assignment for you, then I have
to do the same thing, that is, implement an assignment operator then
add the template method operator=, right?

TIA, With my best regards,
G. Rodrigues

Jul 22 '05 #3
Gonçalo Rodrigues wrote in news:ih********************************@4ax.com
in comp.lang.c++:

Thanks, adding the template method (instead of replacing) does make
the output right.

Another question: I'd assume that, since if not implemented the
compiler also synthesizes an operator assignment for you, then I have
to do the same thing, that is, implement an assignment operator then
add the template method operator=, right?


Yep.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #4
I've looked through the code that the OP gave.
Now I've a question after trying the code.
Why is the specialisation needed at all?
Am I missing a vital reason for it?
Jul 22 '05 #5
On 22 Nov 2004 05:53:48 -0800, ve*********@hotmail.com (velthuijsen)
wrote:
I've looked through the code that the OP gave.
Now I've a question after trying the code.
Why is the specialisation needed at all?
Am I missing a vital reason for it?


I believe this is about a post of mine - but I am guessing here, you
should keep the quotes.

My answer: no you haven't missed nothing. I've pushed the
specialization code in Ref<Object> to the general template Ref<T> and
deleted the (full) specialization.

With my best regards,
G. Rodrigues
Jul 22 '05 #6
> >I've looked through the code that the OP gave.
Now I've a question after trying the code.
Why is the specialisation needed at all?
Am I missing a vital reason for it?


I believe this is about a post of mine - but I am guessing here, you
should keep the quotes.

My answer: no you haven't missed nothing. I've pushed the
specialization code in Ref<Object> to the general template Ref<T> and
deleted the (full) specialization.


Thank you.
It was (at least for me) not a wasted effort. I Learned a bit more
about how to work with templates from it.
Jul 22 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by Dave Rahardja | last post: by
3 posts views Thread by Yohan | last post: by
272 posts views Thread by Peter Olcott | last post: by
16 posts views Thread by Jeroen | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.