Learning auto_ptr_ref role in auto_ptr implementation

D

dragoncoder

Hi all,

I am trying to understand the auto_ptr_ref role in the implementation
of auto_ptr<>. I read the information on net but still not 100% sure of
it. My plan is as follows.

1. To see the behaviour of std::auto_ptr.
2. To implement a pkt::auto_ptr without auto_ptr_ref.
3. Check out the limitations of pkt::auto_ptr as compared to
std::auto_ptr (using steps 1 and 2).
4. Try to relate the concept of auto_ptr_ref to fill the gaps found in
step 3.

NOTE: Any siggestions on this are welcome.

As the first step I have written the following program.

=> cat example.cxx
#include <iostream>
#include <memory>

using namespace std;

template <typename T>
auto_ptr <T> source ( T a )
{
return auto_ptr <T> ( new T ( a ) );
}

template <typename T>
void print ( /* const */ auto_ptr <T>& p )
{
cout << "In print(): " << *p << endl;
}

int main()
{
print ( source ( 5 ) );
return 0;
}

z852378@premier:/home/z852378/rnd/pkt
=> g++ example.cxx
example.cxx: In function `int main()':
example.cxx:20: could not convert `source(T) [with T = int]()' to `
std::auto_ptr<int>&'
example.cxx:14: in passing argument 1 of `void print(std::auto_ptr<T>&)
[with T
= int]'

Uncommenting the 'const' in print() definition compiles the code fine
and the output is also fine. Based on my current knowledge, this is
because the return value of source() is a temporary and therefore can
not be bound to a non-const reference. Is my understanding correct ?
 
D

dasjotre

dragoncoder said:
Hi all,

I am trying to understand the auto_ptr_ref role in the implementation
of auto_ptr<>. I read the information on net but still not 100% sure of
it. My plan is as follows.

1. To see the behaviour of std::auto_ptr.
2. To implement a pkt::auto_ptr without auto_ptr_ref.
3. Check out the limitations of pkt::auto_ptr as compared to
std::auto_ptr (using steps 1 and 2).
4. Try to relate the concept of auto_ptr_ref to fill the gaps found in
step 3.

NOTE: Any siggestions on this are welcome.

As the first step I have written the following program.

=> cat example.cxx
#include <iostream>
#include <memory>

using namespace std;

template <typename T>
auto_ptr <T> source ( T a )
{
return auto_ptr <T> ( new T ( a ) );
}

template <typename T>
void print ( /* const */ auto_ptr <T>& p )
{
cout << "In print(): " << *p << endl;
}

int main()
{
print ( source ( 5 ) );
return 0;
}

z852378@premier:/home/z852378/rnd/pkt
=> g++ example.cxx
example.cxx: In function `int main()':
example.cxx:20: could not convert `source(T) [with T = int]()' to `
std::auto_ptr<int>&'
example.cxx:14: in passing argument 1 of `void print(std::auto_ptr<T>&)
[with T
= int]'

Uncommenting the 'const' in print() definition compiles the code fine
and the output is also fine. Based on my current knowledge, this is
because the return value of source() is a temporary and therefore can
not be bound to a non-const reference. Is my understanding correct ?

yes.
 
R

rani_sharoni

dragoncoder said:
Hi all,

I am trying to understand the auto_ptr_ref role in the implementation
of auto_ptr<>. I read the information on net but still not 100% sure of
it. My plan is as follows.

Here is the original suggestion for the current auto_ptr:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1997/N1128.pdf

Carefully read the "Analysis of Conversion operations" section.

The following defect report on auto_ptr explains why the current
auto_ptr is partially broken and suggests a fully working auto_ptr:
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#463

Another interesting insight about auto_ptr, written by the most
authorized C++ core expert:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2000/n1232.pdf

Although I wrote defect report #463 I personally prefer to avoid
auto_ptr and to use policy based smart class *without* the copy w/
transfer of ownership semantics.

Rani
 
D

dragoncoder

Here is the original suggestion for the current auto_ptr:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1997/N1128.pdf

Carefully read the "Analysis of Conversion operations" section.

The following defect report on auto_ptr explains why the current
auto_ptr is partially broken and suggests a fully working auto_ptr:
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#463

Another interesting insight about auto_ptr, written by the most
authorized C++ core expert:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2000/n1232.pdf

Although I wrote defect report #463 I personally prefer to avoid
auto_ptr and to use policy based smart class *without* the copy w/
transfer of ownership semantics.

Rani

Thanks a lot for the references and it seems to me that these document
will answer my questions. But I would really love to have a look at the
changes done to auto_ptr since the beginning. I mean I want to know the
reason of the change in auto_ptr from CD-1 to CD-2. Could you please
give me some references on that ?

Thanks in advance.
 
D

dragoncoder

Thanks everyone for the replies, I really appreciate it.

I have the following piece of text from "The C++ Standard Library" by
Nicolai Josuttis.

....
The rest of the class auto_ptr (auxiliary type auto_ptr_ref and
functions using it) consists of rather tricky conversions that enable
you to use copy and assignment operations for nonconstant auto_ptrs but
not for constant auto_ptrs...

I hope they are talking about the auto_ptr_ref trick here, correct me
if I am wrong. Anyways, this means it (the trick) enables me to use
copy and assignment operators for non-const std::auto_ptr (with the
help of auto_ptr_ref) but not for const auto_ptr. Now please look at
the following code.

// File pkt.h
#ifndef _PKT_H
#define _PKT_H

namespace pkt
{

template <typename T>
class auto_ptr
{
private:
// member which points to the allocated memory
T* ap;
public:
typedef T element_type;

// parameterized constructor
explicit auto_ptr ( T* p = 0 ) throw () : ap ( p ) { }

// default copy constructor
auto_ptr ( auto_ptr & a ) throw () : ap ( a.release() ) { }

// copy constructor with implicit conversion
template <typename X> auto_ptr ( auto_ptr <X>& a ) throw () : ap (
a.release() ) { }

// default assignment operator
auto_ptr& operator= ( auto_ptr & a ) throw ()
{
reset ( a.release() );
return *this;
}

// assignment operator with implicit conversion
template <typename X> T& operator= ( auto_ptr <X>& a ) throw ()
{
reset ( a.release() );
return *this;
}

// destructor
~auto_ptr () throw ()
{
delete this->ap;
}

// returns the holder pointer
T* get () const throw ()
{
return this->ap;
}

// returns the object as an lvalue
T& operator* () const
{
return *(this->ap);
}

// returns the holder pointer
T* operator-> () const
{
return this->ap;
}
// returns the holder pointer after deleting it
T* release () throw ()
{
T* tmp ( ap );
ap = 0;
return tmp;
}

// resets to the newly allocated memory
void reset ( T* a = 0 ) throw ()
{
if ( ap != a )
{
delete this->ap;
this->ap = a;
}
}

}; // end class auto_ptr
} // end namespace pkt

#endif // end #ifndef

// File pkt.cxx
#include <iostream>
#include <memory>
#include "pkt.h"

using std::cout;
using std::endl;
using pkt::auto_ptr;

template <typename T>
auto_ptr<T> source ( T a )
{
return auto_ptr<T> ( new T ( ) );
}

template <typename T>
void print ( auto_ptr<T>& a )
{
cout << "Inside print(): value passed is: " << *a << endl;
}

int main()
{
auto_ptr<int> pi1 ( new int ( 10 ) );
print ( pi1 ) ;
const auto_ptr<int> pi2 ( new int ( 20 ) );
print ( pi2 );
}

=> g++ pkt.cxx
pkt.cxx: In function `int main()':
pkt.cxx:26: no matching function for call to `print(const
pkt::auto_ptr<int>&)'

My point is that pkt::auto_ptr does not have any auto_ptr_ref trick but
then also it is allowing me to use the copy and assignment operator for
a non-const auto_ptr but not for const auto_ptr.

My question is what was the problem which was being tried to solve
using the auto_ptr_ref trick. An example would be much appreciated.

Thanks in advance.
 
D

dragoncoder

I am totally lost with the readings that I have been doing, please help
me out. I thought auto_ptr_ref was introduces so that its possible to
return an std::auto_ptr from a function and copying it into another
std::auto_ptr. This is the code I tried.

=> cat example.cxx
#include <iostream>
#include <memory>

using namespace std;

template <typename T>
auto_ptr <T> source ( const T &a )
{
return auto_ptr <T> ( new T ( a ) );
}

int main()
{
auto_ptr <int> pi2;
pi2 = source ( 5 );
return 0;
}

=> g++ pkt.cxx
pkt.cxx: In function `int main()':
pkt.cxx:27: no matching function for call to
`pkt::auto_ptr<int>::auto_ptr(
pkt::auto_ptr<int>)'
pkt.h:23: candidates are: pkt::auto_ptr<T>::auto_ptr(pkt::auto_ptr<X>&)
[with X
= int, T = int]
pkt.h:20: pkt::auto_ptr<T>::auto_ptr(pkt::auto_ptr<T>&)
[with T
= int]
pkt.h:17: pkt::auto_ptr<T>::auto_ptr(T* = 0) [with T =
int]
pkt.cxx: In function `pkt::auto_ptr<T> source(const T&) [with T =
int]':
pkt.cxx:27: instantiated from here
pkt.cxx:12: no matching function for call to
`pkt::auto_ptr<int>::auto_ptr(
pkt::auto_ptr<int>)'
pkt.h:23: candidates are: pkt::auto_ptr<T>::auto_ptr(pkt::auto_ptr<X>&)
[with X
= int, T = int]
pkt.h:20: pkt::auto_ptr<T>::auto_ptr(pkt::auto_ptr<T>&)
[with T
= int]

Based on what I have read, I expect the above code to get compiled. Can
someone please explain if I am missing somerhing ?

Thanks
 
A

Alf P. Steinbach

* dragoncoder:
I am totally lost with the readings that I have been doing, please help
me out. I thought auto_ptr_ref was introduces so that its possible to
return an std::auto_ptr from a function and copying it into another
std::auto_ptr. This is the code I tried.

The error messages + your earlier postings indicate that it's absolutely
/not/ the code you tried.

[snip]

- Alf
 
D

dragoncoder

Alf said:
* dragoncoder:

The error messages + your earlier postings indicate that it's absolutely
/not/ the code you tried.

I am extremely sorry, I seem to have lost my senses while trying to
understand this beast. But I think I have pretty much got the idea.
This is the code which compiles fine with std::auto_ptr but not with
pkt::auto_ptr, which shows the missing link between these 2, which I
think is auto_ptr_ref.

=> cat example.cxx
#include <iostream>
#include <memory>

using namespace std;

template <typename T>
auto_ptr <T> source ( const T &a )
{
return auto_ptr <T> ( new T ( a ) );
}

template <typename T>
void print ( auto_ptr <T>& p )
{
cout << "In print(): " << *p << endl;
}

int main()
{
auto_ptr <int> pi2;
pi2 = source ( 5 );
print ( pi2 );
auto_ptr <int> pi1 ( source ( 10 ) );
return 0;
}

I am really surprised how pi2 = source ( 5 ) working with the help of
auto_ptr_ref ( or for that matter auto_ptr <int> pi1 ( source ( 5 ) )
). Can someone please explain what is happening behind the scene ?

Thanks very much.
 
R

rani_sharoni

dragoncoder said:
I am really surprised how pi2 = source ( 5 ) working with the help of
auto_ptr_ref ( or for that matter auto_ptr <int> pi1 ( source ( 5 ) )
). Can someone please explain what is happening behind the scene ?

1) pi2 = source ( 5 );
The code compiles because of operator=(auto_ptr_ref<T>) that was added
to allow usage like the one that you mentioned.

This assignment operator was a late addition for auto_ptr that has been
accepted to TC1:
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#127

2) const auto_ptr<int>& r = source(5)
The current standard requires a viable copy constructor in order to
bind a class rvalue (e.g. return value from function) to a const
reference since additional temporary might be involved.

The future standard will probably relax this (frustrating) requirement
to only allow direct binding, see:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#391

My suggestion (DR #462) for fixing auto_ptr actually seems to allow
this case with many highly compliant compliers.

Notice that the copy semantics in C++ can be extremely subtle and there
are several simple examples for which even highly compliant compliers
completely disagree (sometimes even inconsistent them self).

Personally, I prefer regulate the code with facilities that have "less"
subtleties, are more syntactically/semantically robust and easier to
understand.

Rani
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top