Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old February 2nd, 2007, 01:55 PM
Andre Siqueira
Guest
 
Posts: n/a
Default auto_ptr

Hello all,

I have a member function like thist:

Query(const std::string & id, std::auto_ptr<Modifiermodif =
std::auto_ptr<Modifier>())

when a try to instantiate a Query like

Query("123");

my compiler (aCC on HP-UX) gives me an error teling that a can pass
an objectet std::auto_ptr<Modifier& em um objecto
std::auto_ptr<Modifier>

This is the Error:

Error 226: "AssociatedDataPersistente.cpp", line 36 # No appropriate
function found for call of 'auto_ptr::auto_ptr'. Last viable candidate
was

"std::auto_ptr<persistencia::impl::objectel::Modif icadorQuery>::auto_ptr(std::auto_ptr<persistencia: :impl::objectel::ModificadorQuery>
&)" ["/opt/aCC/include_std/memory", line 838]. Argument of type
'class auto_ptr<persistencia::impl::objectel::Modificador Query>' could
not be converted to
'std::auto_ptr<persistencia::impl::objectel::Modif icadorQuery&'.
Query q(type);
^
Warning: 1 future errors were detected and suppressed. Either
remove the '-w' option or add a '+p' option to detect and fix them
before they become fatal errors in a future release.
*** Error exit code 2


This problem started when a change the option -Aa to -AA on aCC.

Is the unique form to initialize an std::auto_ptr like that:
std::auto_ptr<Modifiertest (new Modifier);

thanks,

André Siqueira.

  #2  
Old February 2nd, 2007, 03:25 PM
Rolf Magnus
Guest
 
Posts: n/a
Default Re: auto_ptr

Andre Siqueira wrote:
Quote:
Hello all,
>
I have a member function like thist:
>
Query(const std::string & id, std::auto_ptr<Modifiermodif =
std::auto_ptr<Modifier>())
>
when a try to instantiate a Query like
>
Query("123");
>
my compiler (aCC on HP-UX) gives me an error teling that a can pass
an objectet std::auto_ptr<Modifier& em um objecto
std::auto_ptr<Modifier>
>
This is the Error:
>
Error 226: "AssociatedDataPersistente.cpp", line 36 # No appropriate
function found for call of 'auto_ptr::auto_ptr'. Last viable candidate
was
>
"std::auto_ptr<persistencia::impl::objectel::Modif icadorQuery>::auto_ptr(std::auto_ptr<persistencia: :impl::objectel::ModificadorQuery>
&)" ["/opt/aCC/include_std/memory", line 838]. Argument of type
'class auto_ptr<persistencia::impl::objectel::Modificador Query>' could
not be converted to
'std::auto_ptr<persistencia::impl::objectel::Modif icadorQuery&'.
Query q(type);
^
Warning: 1 future errors were detected and suppressed. Either
remove the '-w' option or add a '+p' option to detect and fix them
before they become fatal errors in a future release.
*** Error exit code 2
>
>
This problem started when a change the option -Aa to -AA on aCC.
>
Is the unique form to initialize an std::auto_ptr like that:
std::auto_ptr<Modifiertest (new Modifier);
Well, std::auto_ptr's copy constructor does modify the original, so its
argument is non-const. But that means you can't initialize it with a
temporary. Your default argument is a temporary.


  #3  
Old February 2nd, 2007, 03:35 PM
Pete C
Guest
 
Posts: n/a
Default Re: auto_ptr

On Feb 2, 3:10 pm, Rolf Magnus <ramag...@t-online.dewrote:
Quote:
>
Andre Siqueira wrote:
Quote:
Query(const std::string & id, std::auto_ptr<Modifiermodif =
std::auto_ptr<Modifier>())
>
Well, std::auto_ptr's copy constructor does modify the original, so its
argument is non-const. But that means you can't initialize it with a
temporary. Your default argument is a temporary.
That was about to be my answer, too, and it's what I would expect for
the reasons you give. But it seems that my g++ (4.1.2) and Comeau
online both accept this code. I'm trying to understand from the
standard (8.5 para 14 perhaps?) what makes this acceptible. Any help
appreciated.


  #4  
Old February 2nd, 2007, 04:15 PM
Pete C
Guest
 
Posts: n/a
Default Re: auto_ptr

On Feb 2, 3:10 pm, Rolf Magnus <ramag...@t-online.dewrote:
Quote:
Andre Siqueira wrote:
Quote:
Query(const std::string & id, std::auto_ptr<Modifiermodif =
std::auto_ptr<Modifier>())
>
Well, std::auto_ptr's copy constructor does modify the original, so its
argument is non-const. But that means you can't initialize it with a
temporary. Your default argument is a temporary.
OK, I get it now. The temporary auto_ptr has a cast operator to type
auto_ptr_ref. And auto_ptr has a constructor form which takes an
auto_ptr_ref object (*not* by reference). So the initialisation occurs
via in intermediate object.
Since the code is therefore OK, my guess is that the OP has done
something with command line switches to make the compiler non-
compliant.

  #5  
Old February 2nd, 2007, 04:35 PM
Kai-Uwe Bux
Guest
 
Posts: n/a
Default Re: auto_ptr

Pete C wrote:
Quote:
On Feb 2, 3:10 pm, Rolf Magnus <ramag...@t-online.dewrote:
Quote:
>>
>Andre Siqueira wrote:
Quote:
Query(const std::string & id, std::auto_ptr<Modifiermodif =
std::auto_ptr<Modifier>())
>>
>Well, std::auto_ptr's copy constructor does modify the original, so its
>argument is non-const. But that means you can't initialize it with a
>temporary. Your default argument is a temporary.
>
That was about to be my answer, too, and it's what I would expect for
the reasons you give. But it seems that my g++ (4.1.2) and Comeau
online both accept this code. I'm trying to understand from the
standard (8.5 para 14 perhaps?) what makes this acceptible. Any help
appreciated.
Consider:

#include <memory>

typedef std::auto_ptr<intip;

void f ( ip x = ip( new int (0)) ) {}

void g ( ip x ) {}

int main ( void ) {
f();
g( ip( new int (0)) );
}

I think, the use of temporaries in the above is fine because the conversion
to auto_ptr_ref kicks in. The constructor for auto_ptr that is used is:

auto_ptr ( auto_ptr_ref<X)

not

auto_ptr ( auto_ptr & )


Best

Kai-Uwe Bux

  #6  
Old February 2nd, 2007, 07:15 PM
Roland Pibinger
Guest
 
Posts: n/a
Default Re: auto_ptr

On 2 Feb 2007 05:46:19 -0800, "Andre Siqueira" wrote:
Quote:
>I have a member function like thist:
>
>Query(const std::string & id, std::auto_ptr<Modifiermodif =
>std::auto_ptr<Modifier>())
BTW, you should _never_ use an auto_ptr (or any other 'smart pointer')
as argument of a function. In your example the pointed to Modifier
object probably gets deleted in the Query function.

Best regards,
Roland Pibinger
  #7  
Old February 2nd, 2007, 07:25 PM
Clark S. Cox III
Guest
 
Posts: n/a
Default Re: auto_ptr

Roland Pibinger wrote:
Quote:
On 2 Feb 2007 05:46:19 -0800, "Andre Siqueira" wrote:
Quote:
>I have a member function like thist:
>>
>Query(const std::string & id, std::auto_ptr<Modifiermodif =
>std::auto_ptr<Modifier>())
>
BTW, you should _never_ use an auto_ptr (or any other 'smart pointer')
as argument of a function. In your example the pointed to Modifier
object probably gets deleted in the Query function.
That advice may apply to auto_ptr, but to extend it to all smart
pointers seems a bit excessive. For instance I see nothing wrong with a
function parameter being a boost or tr1 shared_ptr (how else would one
pass such a pointer around otherwise?).


--
Clark S. Cox III
clarkcox3@gmail.com
  #8  
Old February 2nd, 2007, 07:25 PM
Andre Kostur
Guest
 
Posts: n/a
Default Re: auto_ptr

"Clark S. Cox III" <clarkcox3@gmail.comwrote in
news:12s73gk93a2dpab@corp.supernews.com:
Quote:
Roland Pibinger wrote:
Quote:
>On 2 Feb 2007 05:46:19 -0800, "Andre Siqueira" wrote:
Quote:
>>I have a member function like thist:
>>>
>>Query(const std::string & id, std::auto_ptr<Modifiermodif =
>>std::auto_ptr<Modifier>())
>>
>BTW, you should _never_ use an auto_ptr (or any other 'smart pointer')
>as argument of a function. In your example the pointed to Modifier
>object probably gets deleted in the Query function.
>
That advice may apply to auto_ptr, but to extend it to all smart
pointers seems a bit excessive. For instance I see nothing wrong with a
function parameter being a boost or tr1 shared_ptr (how else would one
pass such a pointer around otherwise?).
Even for auto_ptr, this blanket prohibition goes too far. What if your
function is intended to be a sink for the auto_ptr?
  #9  
Old February 2nd, 2007, 09:15 PM
Roland Pibinger
Guest
 
Posts: n/a
Default Re: auto_ptr

On Fri, 02 Feb 2007 14:16:45 -0500, "Clark S. Cox III" wrote:
Quote:
>Roland Pibinger wrote:
Quote:
>BTW, you should _never_ use an auto_ptr (or any other 'smart pointer')
>as argument of a function. In your example the pointed to Modifier
>object probably gets deleted in the Query function.
>
>That advice may apply to auto_ptr, but to extend it to all smart
>pointers seems a bit excessive. For instance I see nothing wrong with a
>function parameter being a boost or tr1 shared_ptr (how else would one
>pass such a pointer around otherwise?).
The problem is that you force the client (the caller) to convert the
(real) pointer to your 'smart pointer' with all accompanying problems
for no real advantage. Your function becomes less reusable (restricted
to one 'smart pointer'). Besides that, e.g. a shared_ptr as agument
will just increase the ref-count on function entry and decrease it on
function exit.

Best regards,
Roland Pibinger
  #10  
Old February 2nd, 2007, 09:15 PM
Roland Pibinger
Guest
 
Posts: n/a
Default Re: auto_ptr

On Fri, 2 Feb 2007 19:18:48 +0000 (UTC), Andre Kostur wrote:
Quote:
>Even for auto_ptr, this blanket prohibition goes too far. What if your
>function is intended to be a sink for the auto_ptr?
I'd call that bad style when a called function deletes an object that
is passed via pointer. Maybe the rules for 'smart pointers' are
different, as 'anticipate anything'.

Best regards,
Roland Pibinger
  #11  
Old February 2nd, 2007, 09:35 PM
Andre Kostur
Guest
 
Posts: n/a
Default Re: auto_ptr

rpbg123@yahoo.com (Roland Pibinger) wrote in news:45c3a71d.7611184
@news.utanet.at:
Quote:
On Fri, 2 Feb 2007 19:18:48 +0000 (UTC), Andre Kostur wrote:
Quote:
>>Even for auto_ptr, this blanket prohibition goes too far. What if your
>>function is intended to be a sink for the auto_ptr?
>
I'd call that bad style when a called function deletes an object that
is passed via pointer. Maybe the rules for 'smart pointers' are
different, as 'anticipate anything'.
Technically, it hasn't been passed a pointer, it has been passed an
auto_ptr by value. And, by definition of what an auto_ptr does, it would
be expected that the contents of the auto_ptr will be destroyed by the end
of the function call. If this isn't what the programmer wanted, the
function would have been written to take a reference to auto_ptr.
  #12  
Old February 2nd, 2007, 10:05 PM
Kai-Uwe Bux
Guest
 
Posts: n/a
Default Re: auto_ptr

Roland Pibinger wrote:
Quote:
On Fri, 02 Feb 2007 14:16:45 -0500, "Clark S. Cox III" wrote:
Quote:
>>Roland Pibinger wrote:
Quote:
>>BTW, you should _never_ use an auto_ptr (or any other 'smart pointer')
>>as argument of a function. In your example the pointed to Modifier
>>object probably gets deleted in the Query function.
>>
>>That advice may apply to auto_ptr, but to extend it to all smart
>>pointers seems a bit excessive. For instance I see nothing wrong with a
>>function parameter being a boost or tr1 shared_ptr (how else would one
>>pass such a pointer around otherwise?).
>
The problem is that you force the client (the caller) to convert the
(real) pointer to your 'smart pointer' with all accompanying problems
for no real advantage. Your function becomes less reusable (restricted
to one 'smart pointer'). Besides that, e.g. a shared_ptr as agument
will just increase the ref-count on function entry and decrease it on
function exit.
If all the function does is to operate on the pointee, then it should take a
reference and you call it like

f ( *ptr );

and it would not matter what kind of smart or raw pointer you pass. However,
when a function takes a smart-pointer argument, my expectation would be
that it needs the smart-pointer and not the underlying raw pointer. For
instance:

template < typename T >
class Table {

std::map< unsigned int, tr1::shared_ptr<T data;
unsigned int count;

insert ( tr1::shared_ptr<Tptr ) {
data[ count ++ ] = ptr;
}

// ...

};

In this case, using the underlying pointer would create a shared_ptr with a
different reference count. That would be bad.


Best

Kai-Uwe Bux
  #13  
Old February 2nd, 2007, 10:35 PM
Roland Pibinger
Guest
 
Posts: n/a
Default Re: auto_ptr

On Fri, 2 Feb 2007 21:23:38 +0000 (UTC), Andre Kostur wrote:
Quote:
>rpbg123@yahoo.com (Roland Pibinger) wrote:
Quote:
>On Fri, 2 Feb 2007 19:18:48 +0000 (UTC), Andre Kostur wrote:
Quote:
>>>Even for auto_ptr, this blanket prohibition goes too far. What if your
>>>function is intended to be a sink for the auto_ptr?
>>
>I'd call that bad style when a called function deletes an object that
>is passed via pointer. Maybe the rules for 'smart pointers' are
>different, as 'anticipate anything'.
>
>Technically, it hasn't been passed a pointer, it has been passed an
>auto_ptr by value.
Yes, I know. 'Smart pointers' are neither smart nor pointers.
Quote:
And, by definition of what an auto_ptr does, it would
>be expected that the contents of the auto_ptr will be destroyed by the end
>of the function call.
.... unless the function calls .release().
Quote:
>If this isn't what the programmer wanted, the
>function would have been written to take a reference to auto_ptr.
reference to auto_ptr?? A part of the problem rather than a part of
the solution.

Best wishes,
Roland Pibinger
  #14  
Old February 3rd, 2007, 01:05 AM
Rolf Magnus
Guest
 
Posts: n/a
Default Re: auto_ptr

Roland Pibinger wrote:
Quote:
On Fri, 2 Feb 2007 21:23:38 +0000 (UTC), Andre Kostur wrote:
Quote:
>>rpbg123@yahoo.com (Roland Pibinger) wrote:
Quote:
>>On Fri, 2 Feb 2007 19:18:48 +0000 (UTC), Andre Kostur wrote:
>>>>Even for auto_ptr, this blanket prohibition goes too far. What if your
>>>>function is intended to be a sink for the auto_ptr?
>>>
>>I'd call that bad style when a called function deletes an object that
>>is passed via pointer. Maybe the rules for 'smart pointers' are
>>different, as 'anticipate anything'.
>>
>>Technically, it hasn't been passed a pointer, it has been passed an
>>auto_ptr by value.
>
Yes, I know. 'Smart pointers' are neither smart nor pointers.
Not sure what you want to say with that.
Quote:
Quote:
>And, by definition of what an auto_ptr does, it would
>>be expected that the contents of the auto_ptr will be destroyed by the end
>>of the function call.
>
... unless the function calls .release().
If it does, then there is no point in letting it take an auto_ptr instead of
a regular pointer for a parameter.
Quote:
Quote:
>>If this isn't what the programmer wanted, the function would have been
>>written to take a reference to auto_ptr.
>
reference to auto_ptr?? A part of the problem rather than a part of
the solution.
I don't see a point in using references to auto_ptr either.

  #15  
Old February 3rd, 2007, 01:05 AM
Rolf Magnus
Guest
 
Posts: n/a
Default Re: auto_ptr

Roland Pibinger wrote:
Quote:
On Fri, 02 Feb 2007 14:16:45 -0500, "Clark S. Cox III" wrote:
Quote:
>>Roland Pibinger wrote:
Quote:
>>BTW, you should _never_ use an auto_ptr (or any other 'smart pointer')
>>as argument of a function. In your example the pointed to Modifier
>>object probably gets deleted in the Query function.
>>
>>That advice may apply to auto_ptr, but to extend it to all smart
>>pointers seems a bit excessive. For instance I see nothing wrong with a
>>function parameter being a boost or tr1 shared_ptr (how else would one
>>pass such a pointer around otherwise?).
>
The problem is that you force the client (the caller) to convert the
(real) pointer to your 'smart pointer' with all accompanying problems
for no real advantage. Your function becomes less reusable (restricted
to one 'smart pointer'). Besides that, e.g. a shared_ptr as agument
will just increase the ref-count on function entry and decrease it on
function exit.
Unless it's a function that e.g. adds the smart pointer to a container.

  #16  
Old February 3rd, 2007, 10:55 AM
Grizlyk
Guest
 
Posts: n/a
Default Re: auto_ptr

Roland Pibinger wrote:
Quote:
On Fri, 2 Feb 2007 19:18:48 +0000 (UTC), Andre Kostur wrote:
Quote:
>>Even for auto_ptr, this blanket prohibition goes too far. What if your
>>function is intended to be a sink for the auto_ptr?
>
I'd call that bad style when a called function deletes an object that
is passed via pointer. Maybe the rules for 'smart pointers' are
different, as 'anticipate anything'.
1.
C-style pointer has no enough information about how to work with pointer,
what is why programmer must support the C-style pointer usage by own
conventions, implemented, for example, as comments, look at the following
example

//return "new[]", must be "delete[]" by external
int* get_data1();

//return "new", must be "delete" by external
int* get_data2();

//return static, do not delete outside the class
int* get_data3();

For language without garbage collecting (as C++ does) it is too raw
behaviour, it is danger by possible memory leak or double delete, because
compiler do not control the pointer usage.

2.
The auto_ptr<Tobjis not just pointer, it is !_logical_ pair of two values:

//pointer
Tobj* ptr;
//flag "how to work with pointer"
char is_delete_by_dtor;

and some functions auto_ptr<Tobj>::??? to work with the values.

The auto_ptr<Tobjis RAII wrapper for memory, so it is very useful as
parameter of functions.

3.
As for concrete std::auto_ptr<Tobj>, it is not clear to me why
std::auto_ptr<Tobjmust be non-const to work.

If assuming, that auto_ptr<Tobjhas method "move" to pass stored pointer
value outside the auto_ptr<Tobjscope, the methos can and must be const.
Consider the following example:

//let's work only with object
//created by "new my_auto_ptr"
template<class Tobj>
class my_auto_ptr
{
//pointer
mutable Tobj* ptr;
/*
what mutable here?
"*" is prefix operator!
by the way, it is bad (irregular) C++ syntax
Tobj *mutable ptr; //much better and clear
*/

public:
Tobj* move()const
{
Tobj *const tmp=ptr;
ptr=0;
return tmp;
}

// danger design in return here - can store one
// pointer more than once and will get runtime
// error
Tobj* operator= (Tobj *const p)
{
if( p != ptr )
{
if(ptr)delete ptr;
ptr=p;
}
return p;
}

public:
// C-style danger here - we can pass not only new Tobj
// and will get runtime error
my_auto_ptr(Tobj *const p=0):ptr(p){}

~my_auto_ptr(){ delete ptr; }

my_auto_ptr(const my_auto_ptr& obj):ptr(obj.move()){}
my_auto_ptr& operator=(const my_auto_ptr& obj)
{
if( &obj != this)
{
if(ptr)delete ptr;
ptr=obj.move();
}
return *this;
}
};

It is work fine for exceptions of "dangers" and "const my_auto_ptr<Tobj>"
passed by value is protecting you implementation from wrong assignment to
const value.

Class "auto_ptr<Tobj>" can be example of "free-standing" class - no overhead
in comparison with POD-style data (as naked pointer).

Often the behaviour of "auto_ptr<Tobjstyle" object can be used instead of
more complex in implementation "shared_ptr<Tobjstyle" object.

4.
By the way, I think, that C++ must extend C-style pointer definitions, and
allow to explicit declare memory type with the halp of keywords like this

//!not C++
Tobj *heap ptr; //by new Tobj
Tobj *heap[] ptr; //by new Tobj[]
Tobj *static ptr; //writeable static memory
Tobj *code ptr; //readonly static memory
Tobj *auto ptr; //stack memory
Tobj * ptr; //indefinite memory suitable for all

Note, "Tobj *code" is not he same as "const Tobj *static" because of
different memory segment. Probably we need a "writeonly" memory pointers. We
can introduce "disable write" and "disable read" signs to pointer (abcent by
default) and write like this

Tobj *static writeonly ptr;
Tobj *static readonly ptr;

--
Maksim A Polyanin


  #17  
Old February 3rd, 2007, 02:25 PM
Grizlyk
Guest
 
Posts: n/a
Default Re: auto_ptr

some changes
Quote:
2.
The auto_ptr<Tobjis RAII wrapper for memory, so it is very useful as
parameter of functions.
So auto_ptr<Tobjis not C-style pointer and we must do not excpect that
rules for POD pointers must be applied to auto_ptr<Tobjcompletely.
Quote:
3.
As for concrete std::auto_ptr<Tobj>, it is not clear to me why
std::auto_ptr<Tobjmust be non-const to work.
>
If assuming, that auto_ptr<Tobjhas method "move" to pass stored pointer
value outside the auto_ptr<Tobjscope, the methos can and must be const.
Means 'the method "move" can and must be "const" '.
Quote:
>
//let's work only with object
//created by "new my_auto_ptr"
template<class Tobj>
class my_auto_ptr
Means created by "new Tobj"
Quote:
>
It is work fine for exceptions of "dangers" and "const my_auto_ptr<Tobj>"
passed by value is protecting you implementation from wrong assignment to
const value.
Means "protecting your implementation"

--
Maksim A Polyanin


  #18  
Old February 3rd, 2007, 10:55 PM
Andre Kostur
Guest
 
Posts: n/a
Default Re: auto_ptr

"Grizlyk" <grizlyk1@yandex.ruwrote in news:eq1p6d$svs$1@aioe.org:
Quote:
3.
As for concrete std::auto_ptr<Tobj>, it is not clear to me why
std::auto_ptr<Tobjmust be non-const to work.
>
If assuming, that auto_ptr<Tobjhas method "move" to pass stored
pointer value outside the auto_ptr<Tobjscope, the methos can and
must be const. Consider the following example:
>
//let's work only with object
//created by "new my_auto_ptr"
template<class Tobj>
class my_auto_ptr
{
//pointer
mutable Tobj* ptr;
/*
what mutable here?
"*" is prefix operator!
by the way, it is bad (irregular) C++ syntax
Tobj *mutable ptr; //much better and clear
*/
>
public:
Tobj* move()const
{
Tobj *const tmp=ptr;
ptr=0;
return tmp;
}
>
// danger design in return here - can store one
// pointer more than once and will get runtime
// error
Tobj* operator= (Tobj *const p)
{
if( p != ptr )
{
if(ptr)delete ptr;
ptr=p;
}
return p;
}
>
public:
// C-style danger here - we can pass not only new Tobj
// and will get runtime error
my_auto_ptr(Tobj *const p=0):ptr(p){}
>
~my_auto_ptr(){ delete ptr; }
>
my_auto_ptr(const my_auto_ptr& obj):ptr(obj.move()){}
my_auto_ptr& operator=(const my_auto_ptr& obj)
{
if( &obj != this)
{
if(ptr)delete ptr;
ptr=obj.move();
}
return *this;
}
};
>
It is work fine for exceptions of "dangers" and "const
my_auto_ptr<Tobj>" passed by value is protecting you implementation
from wrong assignment to const value.
EVIL! By that reasoning, why don't we just make every member of every
class mutable?

The move() method semantically changes the "state" of the object, as a
result it logically must not be const. Otherwise the programmer will get
confused when he passed one of these objects by const-ref into a
function, and the object gets changed inside that function. Or phrased
differently, if I'm passing a smart pointer into a function by const-ref,
I'm not expecting it to come back out as a NULL pointer. I passed it in
as const. It's not supposed to change.
  #19  
Old February 4th, 2007, 09:55 AM
Grizlyk
Guest
 
Posts: n/a
Default Re: auto_ptr

Andre Kostur wrote:
Quote:
Quote:
>>
>It is work fine for exceptions of "dangers" and "const
>my_auto_ptr<Tobj>" passed by value is protecting you implementation
>from wrong assignment to const value.
>
EVIL! By that reasoning, why don't we just make every member of every
class mutable?
>
The move() method semantically changes the "state" of the object, as a
result it logically must not be const.
1.
Can be const, of course. The "const state" does not mean "const each member"
and appearence in C++ keyword "mutable" just proves it. Consider

my_auto_ptr<Tobj a(new Tobj); //1
my_auto_ptr<Tobj b(a); //2

At the point 2 we are moving "new Tobj" to "b". Is it C-style pointer
behaviour? I think not. But fortunately my_auto_ptr<Tobjis not pointer, so
we must not duty to think, that the moving "new Tobj" from "a" violates "a"
constness.
Quote:
if I'm passing a smart pointer into a function by const-ref,
I'm not expecting it to come back out as a NULL pointer.
You just must not expect from my_auto_ptr<Tobjany return, because it is
not pointer, it is special memory wrapper with complex behaviour.

The goal of my_auto_ptr<Tobj>
1. to hold dynamic data for parameter of function
2. to delete the data on return from the function (if the data was not
used by the function) or to pass the data to user

That is why operation move() is just a kind of operation, that must be
applyed to my_auto_ptr<Tobjonly once insted to be non-const!

You can not protect yourself from double move() with the help of non-const
modifier, but as opposite, const my_auto_ptr<Tobjcan protect your
implementation from wrong assignment to my_auto_ptr<Tobj>.

Consider

void foo(const my_auto_ptr<Tobjptr)
{
Tobj *const a=ptr.move(); //ok
Tobj *const b=ptr.move(); //error, const do not protect
ptr=new Tobj; //error, but const will protect
}

void foo(my_auto_ptr<Tobjptr)
{
Tobj *const a=ptr.move(); //ok
Tobj *const b=ptr.move(); //error, non-const do not protect
ptr=new Tobj; //error, non-const do not protect
}

2.
By the way, I see now, C++ can support keyword "once", to control that the
method "move" will be called only once during lifetime of object. Very
useful, thanks to Andre Kostur.

The keyword "once" can not garantee compile time control, but at least it
can produce warnings.

void foo(const my_auto_ptr<Tobjptr)
{
if(::is_ok){ptr.move();}

//warning - possible double move();
//if "::is_ok" is not synced with "lib::all_ok()"
if(!lib::all_ok()){ptr.move();}
}

to avoid the warning you need write like this

void foo(const my_auto_ptr<Tobjptr, const int is_ok)
{
if(is_ok){ptr.move();}
else
{
if(!lib::all_ok()){ptr.move();}
}
}

Can the keyword "once" make differences for overloading?

//!not C++
//ok
Tobj *const /*once*/ move()const once;
//i think error - redeclaration of "move()const"
Tobj *const move()const;

//maybe ok together with "move()const once"
Tobj *once move()once;
//i think error - redeclaration of "move()"
Tobj * move();

--
Maksim A Polyanin


  #20  
Old February 4th, 2007, 03:05 PM
Grizlyk
Guest
 
Posts: n/a
Default Re: auto_ptr

4.
Quote:
By the way, I think, that C++ must extend C-style pointer definitions, and
allow to explicit declare memory type with the halp of keywords like this
>
//!not C++
Tobj *heap ptr; //by new Tobj
Tobj *heap[] ptr; //by new Tobj[]
Tobj *static ptr; //writeable static memory
Tobj *code ptr; //readonly static memory
Tobj *auto ptr; //stack memory
Tobj * ptr; //indefinite memory suitable for all
>

No, i think i was wrong, maybe better will switch like this:

Tobj heap *ptr; //by new Tobj
Tobj heap[] *ptr; //by new Tobj[]

- left side of "*" must describe memory of object and object, pointer point
to
- right side of "*" must describe memory of pointer and pointer itself

Tobj heap is the same as Tobj
Tobj heap* is _not_ the same as Tobj*

Tobj heap* is the same as Tobj heap *heap
Tobj heap* is _not_ the same as Tobj *heap
Quote:
Tobj *static ptr; //writeable static memory
And static keyword has other meaning, maybe using "dseg"?

Tobj dseg *ptr;

Or maybe "dseg" by default, but for "indefinite memory suitable for all" use
"indefinite"?

--
Maksim A Polyanin


  #21  
Old February 4th, 2007, 06:15 PM
Andre Kostur
Guest
 
Posts: n/a
Default Re: auto_ptr

"Grizlyk" <grizlyk1@yandex.ruwrote in news:eq4a0i$8uv$1@aioe.org:
Quote:
Andre Kostur wrote:
Quote:
Quote:
>>>
>>It is work fine for exceptions of "dangers" and "const
>>my_auto_ptr<Tobj>" passed by value is protecting you implementation
>>from wrong assignment to const value.
>>
>EVIL! By that reasoning, why don't we just make every member of
>every class mutable?
>>
>The move() method semantically changes the "state" of the object, as
>a result it logically must not be const.
>
1.
Can be const, of course. The "const state" does not mean "const each
member" and appearence in C++ keyword "mutable" just proves it.
You also have const_cast too. But that doesn't mean that you should use
it in that manner. Mutable has its uses. It's not intended to allow you
to violate the "semantic constness" of the object. Remember, C++ tends
to try to protect programmers from accident, not maliciousness. You can
break C++'s type safety in many, many ways. The designers had realized
that there are certain cases where the object may be const, but certain
members may need to be modified, even on const objects. Let's assume we
have some sort of object that when a certain const member is called, it
causes a complex calculation to occur. Perhaps this class can take
advantage of caching the result so that future calls to that member
(without any other intervening non-const calls) could return the cached
value instead of having to recalculate it. This is a good candidate for
mutable. The cached value being populated isn't changing the semantic
state the object.
Quote:
Consider
>
my_auto_ptr<Tobj a(new Tobj); //1
my_auto_ptr<Tobj b(a); //2
>
At the point 2 we are moving "new Tobj" to "b". Is it C-style pointer
behaviour? I think not. But fortunately my_auto_ptr<Tobjis not
pointer, so we must not duty to think, that the moving "new Tobj" from
"a" violates "a" constness.
No const in sight there. However, given:

const my_auto_ptr<Tobja(new Tobj);
my_auto_ptr<Tobjb(a);

I would be very surprised to find out that a now no longer holds the data
that I had given it.
Quote:
Quote:
>if I'm passing a smart pointer into a function by const-ref,
>I'm not expecting it to come back out as a NULL pointer.
>
You just must not expect from my_auto_ptr<Tobjany return, because it
is not pointer, it is special memory wrapper with complex behaviour.
>
The goal of my_auto_ptr<Tobj>
1. to hold dynamic data for parameter of function
2. to delete the data on return from the function (if the data was
not
used by the function) or to pass the data to user
>
That is why operation move() is just a kind of operation, that must be
applyed to my_auto_ptr<Tobjonly once insted to be non-const!
The problem here is that operation move() isn't a logically const
operation. It changes the "semantic" state of the object.
Quote:
You can not protect yourself from double move() with the help of
non-const modifier, but as opposite, const my_auto_ptr<Tobjcan
protect your implementation from wrong assignment to
my_auto_ptr<Tobj>.
>
Consider
>
void foo(const my_auto_ptr<Tobjptr)
{
Tobj *const a=ptr.move(); //ok
Tobj *const b=ptr.move(); //error, const do not protect
ptr=new Tobj; //error, but const will protect
}
Um, you're passing an object by const value. The specific argument I'm
attempting to make:


// Function somewhere else. Contents unknown,
// function is defined in a different translation
// unit.
void fn(const my_auto_ptr<Tobj& aptr);

{
my_auto_ptr<Tobjptr(new Tobj);

fn(ptr);

ptr->DoSomethingOnPtr();
}

I would expect that to have useful behaviour, and specifically, I
wouldn't expect the pointer to become NULL.

  #22  
Old February 5th, 2007, 11:15 AM
Grizlyk
Guest
 
Posts: n/a
Default Re: auto_ptr


Andre Kostur wrote:
Quote:
Quote:
>>
>Grizlyk wrote:
Quote:
>>>
>>The move() method semantically changes the "state" of the object, as
>>a result it logically must not be const.
>>
>1.
>Can be const, of course. The "const state" does not mean "const each
>member" and appearence in C++ keyword "mutable" just proves it.
>
You also have const_cast too. But that doesn't mean that you should use
it in that manner. Mutable has its uses. It's not intended to allow you
to violate the "semantic constness" of the object.
You are right about constness, but not right for concrete my_auto_ptr<Tobj>,
because "semantic constness" of my_auto_ptr<Tobjis not the same as
"semantic constness" of a C-style pointer, because my_auto_ptr<Tobjis not
a C-style pointer. However, in some limited cases the behaviour of
my_auto_ptr<Tobjcan looks like behaviour of C-style pointer, else we can
not use my_auto_ptr<Tobjto hold memory adsress.
Quote:
Quote:
>Consider
>>
>my_auto_ptr<Tobj a(new Tobj); //1
>my_auto_ptr<Tobj b(a); //2
>>
>At the point 2 we are moving "new Tobj" to "b". Is it C-style pointer
>behaviour? I think not. But fortunately my_auto_ptr<Tobjis not
>pointer, so we must not duty to think, that the moving "new Tobj" from
>"a" violates "a" constness.
>
No const in sight there. However, given:
>
const my_auto_ptr<Tobja(new Tobj);
my_auto_ptr<Tobjb(a);
Yes, even both are const

const my_auto_ptr<Tobja(new Tobj);
const my_auto_ptr<Tobjb(a);
Quote:
I would be very surprised to find out that a now no longer holds the data
that I had given it.
You must not be surprised, because "b(a)" is really "once" operation
(operation that can be applied to "my_auto_ptr<Tobj>" only once) instead of
"const" operation. And you must _not_ do like this

{
const my_auto_ptr<Tobja(new Tobj);
const my_auto_ptr<Tobjb(a);
a.get_pointer(); //error
}

There are many other cases, when we must keep strict sequence of operations
applied to, for example

{
const char *ptr="test";
ptr=0;
strlen(ptr);//runtime error - access to memory NULL
}
Quote:
>
Quote:
Quote:
>>if I'm passing a smart pointer into a function by const-ref,
>>I'm not expecting it to come back out as a NULL pointer.
Aby _auto_ ponter passed by const-ref is nonsence, really, has no reasons to
do it, if you no need to control memory allocation at the point just pass
ordinary C-style pointer instead of _auto_ ponter, external code, where
_auto_ ponter was created, will control memory allocation.

Note, _auto_ ponter passed by value gives no overhead in comparison with
_auto_ ponter passed by const-ref.
Quote:
Quote:
>That is why operation move() is just a kind of operation, that must be
>applyed to my_auto_ptr<Tobjonly once insted to be non-const!
>
The problem here is that operation move() isn't a logically const
operation. It changes the "semantic" state of the object.
I have said about my_auto_ptr<Tobj"semantic state" upper.
Quote:
Quote:
>You can not protect yourself from double move() with the help of
>non-const modifier, but as opposite, const my_auto_ptr<Tobjcan
>protect your implementation from wrong assignment to
>my_auto_ptr<Tobj>.
>>
>Consider
>>
>void foo(const my_auto_ptr<Tobjptr)
>{
>Tobj *const a=ptr.move(); //ok
>Tobj *const b=ptr.move(); //error, const do not protect
> ptr=new Tobj; //error, but const will protect
>}
>
Um, you're passing an object by const value. The specific argument I'm
attempting to make:
>
// Function somewhere else. Contents unknown,
// function is defined in a different translation
// unit.
void fn(const my_auto_ptr<Tobj& aptr);
error, do not pass my_auto_ptr<Tobjby ref
Quote:
>
{
my_auto_ptr<Tobjptr(new Tobj);
>
fn(ptr);
>
ptr->DoSomethingOnPtr();
error you must not reuse my_auto_ptr<Tobjafter fn(ptr) due to
my_auto_ptr<Tobjlogic.
Quote:
}
Returning to "once" usage.
It is evidently, we can make runtime tests of my_auto_ptr<Tobjusage, but
we want compile time testing.

I think twice about "once", and see, that it is not enough. Assuming
my_auto_ptr<Tobjhas in addition member get_ptr:

//!not C++
Tobj* my_auto_ptr<Tobj>::get_ptr()const {return ptr;}
Tobj* my_auto_ptr<Tobj>::move()const once
{
Tobj *const tmp=ptr;
ptr=0;
return tmp;
}

const my_auto_ptr<Tobj a(new Tobj);
a.move();
a.move(); //ok - error detected
a.get_ptr(); //wrong - error _not_ detected

I think, we need to tell to compiler that
- if "move()" has executed, "get_ptr()" must not be executed,
- if "move()" has not executed, "get_ptr()" can be executed by conditions of
get_ptr "oneceness".

Let's think, that if "move" has executed, it looks like my_auto_ptr<Tobj>
was logically deleted, no one "returning state" operation can be aplied,
only assignment or destructor.

In fact "move" logically is desructor with name and can return value. So we
need instead of "once" to mark "move" as "dtor", "get_ptr" as "returning
state" and "replace" as "ctor", assuming "returning state" as default value
we will get:

//!not C++
Tobj auto*
my_auto_ptr<Tobj>::get_ptr()const
{return ptr;}

//can "const dtor" pair be applied ot not?
//i think yes, because dtor can destroy const objects
Tobj heap*
my_auto_ptr<Tobj>::move()const dtor
{
Tobj heap *const tmp=ptr;
ptr=0;
return tmp;
}


//can "const ctor" pair be applied ot not?
//i think no, because ctor can not re-create const objects
my_auto_ptr<Tobj>&
my_auto_ptr<Tobj>::
replace(Tobj heap *const new_obj)ctor
{
if(ptr)delete ptr;
ptr=new_obj;
return *this;
}

Now nearly exelent:

{
const my_auto_ptr<Tobj a(new Tobj);
a.get_ptr(); //ok - get
a.get_ptr(); //ok - get
delete a.get_ptr(); //ok - compile time error detected
delete a.move(); //ok - destroy
a.move(); //ok - compile time error detected
a.get_ptr(); //ok - compile time error detected
a.replace(new Tobj); //ok - compile time error detected

const my_auto_ptr<Tobj b(new Tobj);
b.replace(new Tobj); //ok - new value
b.replace(new Tobj); //ok - new value
b.move(); //ok - destroy
b.move(); //ok - compile time error detected
b.get_ptr(); //ok - compile time error detected
b.replace(new Tobj); //ok - new value

Tobj tmp;
b.replace(&tmp); //ok - compile time error detected
}

But exist new problem - we can try extract unassigned value

my_auto_ptr<Tobj a;
a.get_ptr(); //wrong - error _not_ detected

We must tell to compiler, that a variable must be assigned befor usage, but
we can not have "unassigned values" after default ctors. For example, we can
create functions to user access and mark the function sequence calls

protected:
void
my_auto_ptr<Tobj>::
set_ptr_value
(Tobj heap *const new_adr)
{ptr=new_adr;}

Tobj auto*
my_auto_ptr<Tobj>::
get_ptr_value()
const
after set_ptr_value
{return ptr;}

public:
Tobj auto*
my_auto_ptr<Tobj>::get_ptr()const
{return get_ptr_value();}

//"ctor" and "dtor" reset "after" sequence
my_auto_ptr<Tobj>&
my_auto_ptr<Tobj>::
replace(Tobj heap *const new_obj)
ctor
{
if(ptr)delete ptr;
ptr=set_ptr_value(new_obj);
return *this;
}

well, now much beter
my_auto_ptr<Tobj a;
a.get_ptr(); //ok - compile time error detected
a.replace(new Tobj); //ok - new value
a.get_ptr(); //ok - get

--
Maksim A Polyanin

"In thi world of fairy tales rolls are liked olso"
/Gnume/


  #23  
Old February 5th, 2007, 11:25 AM
Rolf Magnus
Guest
 
Posts: n/a
Default Re: auto_ptr

Grizlyk wrote:
Quote:
Andre Kostur wrote:
Quote:
Quote:
>>>
>>It is work fine for exceptions of "dangers" and "const
>>my_auto_ptr<Tobj>" passed by value is protecting you implementation
>>from wrong assignment to const value.
>>
>EVIL! By that reasoning, why don't we just make every member of every
>class mutable?
>>
>The move() method semantically changes the "state" of the object, as a
>result it logically must not be const.
>
1.
Can be const, of course.
Should definitely be.
Quote:
The "const state" does not mean "const each member" and appearence in C++
keyword "mutable" just proves it.
Right. But the mere existance of the mutable keyword doesn't mean you _have_
to use it.
Quote:
Consider
>
my_auto_ptr<Tobj a(new Tobj); //1
my_auto_ptr<Tobj b(a); //2
>
At the point 2 we are moving "new Tobj" to "b".
Yes, and it changes both a and b.
Quote:
Is it C-style pointer behaviour? I think not.
That's right. If it would be have like a C-style pointer, making the copy
constructor's argument const would be just the right thing to do.
Quote:
But fortunately my_auto_ptr<Tobjis not pointer, so we must not duty to
think, that the moving "new Tobj" from "a" violates "a" constness.
Well, there is a concept often called "logical constness", which is more a
design than a language concept. It means that if the object as it appears
to its user is changed by one of its member functions, that member function
should not be const. The mutable keyword is only for internal state that
gets changed without the object's user noticing (an example would be some
cache to speed up multiple reads from a slow source).
Quote:
Quote:
>if I'm passing a smart pointer into a function by const-ref,
>I'm not expecting it to come back out as a NULL pointer.
>
You just must not expect from my_auto_ptr<Tobjany return, because it is
not pointer, it is special memory wrapper with complex behaviour.
Yes, but that behavior should not go on behind my back. If something is
const, I assume it doesn't change. That's why it's const in the first
place. If you make classes that are changed in const member function, you
basically render the whole idea of constness useless.
Quote:
The goal of my_auto_ptr<Tobj>
1. to hold dynamic data for parameter of function
2. to delete the data on return from the function (if the data was not
used by the function) or to pass the data to user
Then you don't need to go through all the dynamic allocation and auto_ptr
stuff. Just make a local varible in the caller, and give a normal pointer
(or reference) to that to the function. auto_ptr doesn't give you any
advantage over that. Even if you must use dynamic allocation, use an
auto_ptr in the caller, but just pass a regular pointer to the function you
are calling. There is no need to pass an auto_ptr.
Quote:
That is why operation move() is just a kind of operation, that must be
applyed to my_auto_ptr<Tobjonly once insted to be non-const!
Not a good idea.
Quote:
You can not protect yourself from double move() with the help of non-const
modifier, but as opposite, const my_auto_ptr<Tobjcan protect your
implementation from wrong assignment to my_auto_ptr<Tobj>.
Your move() function changes the object just like the assignment operator
does. It seems inconsequent to make one of them const and the other not.
Quote:
Consider
>
void foo(const my_auto_ptr<Tobjptr)
{
Tobj *const a=ptr.move(); //ok
Tobj *const b=ptr.move(); //error, const do not protect
ptr=new Tobj; //error, but const will protect
}
>
void foo(my_auto_ptr<Tobjptr)
{
Tobj *const a=ptr.move(); //ok
Tobj *const b=ptr.move(); //error, non-const do not protect
ptr=new Tobj; //error, non-const do not protect
}
How about simply not spending it an assignment operator that takes a regular
pointer as argument?

  #24  
Old February 5th, 2007, 03:15 PM
Andre Kostur
Guest
 
Posts: n/a
Default Re: auto_ptr

"Grizlyk" <grizlyk1@yandex.ruwrote in news:eq7392$d22$1@aioe.org:
Quote:
>
Andre Kostur wrote:
Quote:
Quote:
>>>
>>Grizlyk wrote:
>>>>
>>>The move() method semantically changes the "state" of the object,
>>>as a result it logically must not be const.
>>>
>>1.
>>Can be const, of course. The "const state" does not mean "const each
>>member" and appearence in C++ keyword "mutable" just proves it.
>>
>You also have const_cast too. But that doesn't mean that you should
>use it in that manner. Mutable has its uses. It's not intended to
>allow you to violate the "semantic constness" of the object.
>
You are right about constness, but not right for concrete
my_auto_ptr<Tobj>, because "semantic constness" of my_auto_ptr<Tobj>
is not the same as "semantic constness" of a C-style pointer, because
my_auto_ptr<Tobjis not a C-style pointer. However, in some limited
cases the behaviour of my_auto_ptr<Tobjcan looks like behaviour of
C-style pointer, else we can not use my_auto_ptr<Tobjto hold memory
adsress.
You are still violating the "semantic constness" of the object. Or at
least as it is commonly understood. You are far better off not using
const anywhere (and with no const-methods, makes a const instance of your
class unusable anyway), and enforcing your rules in program logic. Far
better than surprising _every_ potential user of the class by having
"const" instances which can change.

Upon copy-constructing the object, you are very significantly changing
the state of the object. Offhand I can't think of any object where after
calling a const method, suddenly there's a whole bunch of other methods
that I am now no longer allowed to call.

If one insists on designing a class in such a manner, I know I wouldn't
ever use that class.
Quote:
Quote:
Quote:
>>Consider
>>>
>>my_auto_ptr<Tobj a(new Tobj); //1
>>my_auto_ptr<Tobj b(a); //2
>>>
>>At the point 2 we are moving "new Tobj" to "b". Is it C-style
>>pointer behaviour? I think not. But fortunately my_auto_ptr<Tobjis
>>not pointer, so we must not duty to think, that the moving "new
>>Tobj" from "a" violates "a" constness.
>>
>No const in sight there. However, given:
>>
>const my_auto_ptr<Tobja(new Tobj);
>my_auto_ptr<Tobjb(a);
>
Yes, even both are const
>
const my_auto_ptr<Tobja(new Tobj);
const my_auto_ptr<Tobjb(a);
>
Quote:
>I would be very surprised to find out that a now no longer holds the
>data that I had given it.
>
You must not be surprised, because "b(a)" is really "once" operation
(operation that can be applied to "my_auto_ptr<Tobj>" only once)
instead of "const" operation. And you must _not_ do like this
It doesn't matter how many times you can call it. The first time is bad
enough. If it's const, it must not change. If it doesn, I can no longer
trust the const mechanisms of the language. I will not use such a class.
Quote:
{
const my_auto_ptr<Tobja(new Tobj);
const my_auto_ptr<Tobjb(a);
a.get_pointer(); //error
}
That's simple (assuming you drop the consts). The copy constructor of b
also sets a boolean in a as to whether it currently holds a "valid"
pointer. When get_pointer is called, that variable is checked, and if a
doesn't hold a "valid" pointer, throw an exception.
Quote:
There are many other cases, when we must keep strict sequence of
operations applied to, for example
>
{
const char *ptr="test";
ptr=0;
strlen(ptr);//runtime error - access to memory NULL
}
This is already covered as a precondition of strlen, such that strlen
only takes C-style strings. A NULL pointer is not a C-style string, thus
the programmer is improperly using his tools.
Quote:
Quote:
Quote:
>>>if I'm passing a smart pointer into a function by const-ref,
>>>I'm not expecting it to come back out as a NULL pointer.
>
Aby _auto_ ponter passed by const-ref is nonsence, really, has no
reasons to do it, if you no need to control memory allocation at the
point just pass ordinary C-style pointer instead of _auto_ ponter,
external code, where _auto_ ponter was created, will control memory
allocation.
Sure... but is there any reason to actively prevent someone from passing
around a const-ref to it? Under normal circumstances, there's no problem
(beyond requiring users to pass in a smart pointer, naked pointers aren't
allowed). The problem with your description of your class, a const
version of it isn't really const. It might change.
Quote:
Note, _auto_ ponter passed by value gives no overhead in comparison
with _auto_ ponter passed by const-ref.
Yes it does.. the auto_ptr by value needs to transfer ownership of the
pointer into the function parameter. Passing by const-ref does not.
Quote:
Quote:
Quote:
>>That is why operation move() is just a kind of operation, that must
>>be applyed to my_auto_ptr<Tobjonly once insted to be non-const!
>>
>The problem here is that operation move() isn't a logically const
>operation. It changes the "semantic" state of the object.
>
I have said about my_auto_ptr<Tobj"semantic state" upper.
>
Quote:
Quote:
>>You can not protect yourself from double move() with the help of
>>non-const modifier, but as opposite, const my_auto_ptr<Tobjcan
>>protect your implementation from wrong assignment to
>>my_auto_ptr<Tobj>.
>>>
>>Consider
>>>
>>void foo(const my_auto_ptr<Tobjptr)
>>{
>>Tobj *const a=ptr.move(); //ok
>>Tobj *const b=ptr.move(); //error, const do not protect
>> ptr=new Tobj; //error, but const will protect
>>}
>>
>Um, you're passing an object by const value. The specific argument
>I'm attempting to make:
>>
>// Function somewhere else. Contents unknown,
>// function is defined in a different translation
>// unit.
>void fn(const my_auto_ptr<Tobj& aptr);
>
error, do not pass my_auto_ptr<Tobjby ref
Again, another thing that will make me not use a class desgined in such a
manner. The only way that this makes any sense is if the class doesn't
have any const methods, thus there's nothing useful that I can do with a
const instance of the class.
Quote:
Quote:
>{
> my_auto_ptr<Tobjptr(new Tobj);
>>
> fn(ptr);
>>
> ptr->DoSomethingOnPtr();
>
error you must not reuse my_auto_ptr<Tobjafter fn(ptr) due to
my_auto_ptr<Tobjlogic.
That's the problem with your class. You don't know whether you can do
anything with ptr or not. You have the potential that fn() might have
changed the contents of ptr. You don't know. You don't have access to
fn()'s implementation. Even if the documentation for fn() mentions that
it _might_ move the contents of ptr, you still don't know if ptr is valid
or not upon return of fn(). You've made the const system useless within
the context of this class. I'm not going to use it.
Quote:
Quote:
>}
>
Returning to "once" usage.
You can stick a boolean into your class to record whether it is in some
sort of valid state or not. In any method that cares, it can check
and/or set that variable, and throw exceptions where necessary to enforce
it.


Say... here's another usage thought. Given your class, how can I express
that I have an instance of the class such that one is never allowed to
transfer ownership away from it? Normally I would:

const auto_ptr ptr(new Obj);

This would be sufficient to prevent constructs such as:

auto_ptr ptr2(ptr); // Fails at compile time
// ptr2 needs a non-const ref to work

However, if we replaced auto_ptr with your my_auto_ptr, this construct
would compile perfectly fine.

  #