help understand source code in charpter 14.4 of accelerated C++

B

baumann@pan

hi all,

i couldn't understand why code 1) can solve the problem of code 2) has.

code 1)
template<class T> T* clone(const T* tp)
{
return tp->clone();
}
and change our make_unique member to call it

template<class T>
void Ptr<T>::make_unique()
{
if (*refptr != 1) {
--*refptr;
refptr = new size_t(1);
p = p ? clone(p): 0; // call the global (not member) version
of clone
}
}














code 2)

template<class T>
void Ptr<T>::make_unique()
{
if (*refptr != 1) {
--*refptr;
refptr = new size_t(1);
p = p ? p->clone() : 0; // here is the problem
}
}
Look at the call to p->clone. Because we are using a Ptr said:
, this call will try to call the clone function that is a member of
vector<char>. Unfortunately, no such function exists!




template<class T> T* clone(const T* tp)
{
return tp->clone();
}

i think tp-clone() would has the same sematics of p->clone() since both
p and tp are of same type.


so I couldn't understand the difference. how it can solve the problem
of calls undefined member function?


thanks in advance.

baumann@pan
 
A

Alf P. Steinbach

* baumann@pan:
i couldn't understand why code 1) can solve the problem of code 2) has.

code 1)
template<class T> T* clone(const T* tp)
{
return tp->clone();
}
and change our make_unique member to call it

template<class T>
void Ptr<T>::make_unique()
{
if (*refptr != 1) {
--*refptr;
refptr = new size_t(1);
p = p ? clone(p): 0; // call the global (not member) version
of clone
}
}
code 2)

template<class T>
void Ptr<T>::make_unique()
{
if (*refptr != 1) {
--*refptr;
refptr = new size_t(1);
p = p ? p->clone() : 0; // here is the problem
}
}

vector<char>. Unfortunately, no such function exists!

template<class T> T* clone(const T* tp)
{
return tp->clone();
}

i think tp-clone() would has the same sematics of p->clone() since both
p and tp are of same type.
Correct.


so I couldn't understand the difference. how it can solve the problem
of calls undefined member function?

The global template function can be specialized for the type T in
question, e.g.

typedef std::vector<char> CharVector;

template<> CharVector* clone( CharVector const* p )
{
return new CharVector( *p );
}

But I don't have the book and haven't read it, so it's impossible for
me to know whether I've understood correctly what the "problem" is, and
if so, whether the above was the authors' intention.

I think of such things as design: what mechanism, if any, should be used to
support non-intrusive cloning? The "problem" is then to choose between e.g.
a template function, as above, or an interface, or whatever. That's more of
a real "problem" because the solution space is infinite, and experience
says that your chances of first choosing an UnGood solution are 99.5%...

Another real "problem" is to know when to stop generalizing a solution and
adapting it for future reuse that maybe never will occur.

Much of that work _will_ be for nothing, and some of it may even be counter-
productive (e.g. higher complexity, lower flexibility) and the "problem" is
to strike a balance so that the work that does pay off pays enough to cover
also for the work that doesn't.
 
B

baumann@pan

baumann@pan said:
hi all,

i couldn't understand why code 1) can solve the problem of code 2) has.

code 1)
template<class T> T* clone(const T* tp)
{
return tp->clone();
}
and change our make_unique member to call it

template<class T>
void Ptr<T>::make_unique()
{
if (*refptr != 1) {
--*refptr;
refptr = new size_t(1);
p = p ? clone(p): 0; // call the global (not member) version
of clone
}
}














code 2)

template<class T>
void Ptr<T>::make_unique()
{
if (*refptr != 1) {
--*refptr;
refptr = new size_t(1);
p = p ? p->clone() : 0; // here is the problem
}
}
Look at the call to p->clone. Because we are using a Ptr<
vector<char>. Unfortunately, no such function exists!




template<class T> T* clone(const T* tp)
{
return tp->clone();
}

i think tp-clone() would has the same sematics of p->clone() since both
p and tp are of same type.


so I couldn't understand the difference. how it can solve the problem
of calls undefined member function?


thanks in advance.

baumann@pan


my question is the global template clone also depends on object tp of
const T*, which means T should have member function clone.

is it right?


if right, i don't see any difference between the 2 codes .
 
R

Rapscallion

baumann@pan said:
code 1)
template<class T> T* clone(const T* tp)
{
return tp->clone();
}

BTW, using clone() functions is bad style anyway because it makes the
caller responsible to release (delete) the resource (object).

R.C.
 
B

Bronek Kozicki

baumann@pan said:
so I couldn't understand the difference. how it can solve the problem
of calls undefined member function?

through overloading or specialization (former should be preferred) of
non-member function named "clone". Code presented in 2) does not have
any area for extension (e.g. you won't be able to provide clone
semantics for vector), while call to separate function allows you to
overload it for selected classes (e.g. vector), providing desired effect
for classes that do not have "clone" member function (or that have
"Clone" or something else instead).


B.
 
B

baumann@pan

Bronek said:
through overloading or specialization (former should be preferred) of
non-member function named "clone". Code presented in 2) does not have
any area for extension (e.g. you won't be able to provide clone
semantics for vector), while call to separate function allows you to
overload it for selected classes (e.g. vector), providing desired effect
for classes that do not have "clone" member function (or that have
"Clone" or something else instead).


how to overload it for the classes which don't have clone member
function?
 
B

Bronek Kozicki

baumann@pan said:
how to overload it for the classes which don't have clone member
function?

// class has some other function providing similar functionality
Baz* clone(const Baz* tp)
{
std::auto_ptr<Baz> p = tp->MakeCopy();
return p.release();
}

// no clone functionality at all, class is not polymorphic
template <typename T>
std::vector<T>* clone(const std::vector<T>* tp)
{
return new std::vector<T>(*tp);
}

If class is polymorphic and does not provide anything similar to clone,
then such class is "not cloneable". Although one could write some
"clone" overload using copy constructor (as demonstrated above for
std::vector), it would not do the right thing - it would just slice.
Thus it is best not to define such overload for class that do not
provide this functionality and is polymorphic (i.e. cctor is not
applicable).


B.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top