By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,006 Members | 1,137 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,006 IT Pros & Developers. It's quick & easy.

template method question

P: n/a
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
Share this Question
Share on Google+
6 Replies


P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
> >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.