Andre Kostur wrote:
As outcome.
You are trying to declare auto_ptr as non-const in hope to warn user, that
auto_ptr has unexpected, hidden assignment to internal state. It is similar
to refusing from static type checking with the help of "void" - speaking "we
garantee nothing".
If assuming, that extraction from auto_ptr can occur only once (that is
garanteed by programmer because C++ can not do it), auto_ptr can be const
(and must be const if you want to disable explicit assignment -
"auto_ptr=" ).
The detailed consideration below:
Andre said:
As an example,
the intent of the auto_ptr class is to hold a pointer, and ensure that it
is deleted at the end of the life of the auto_ptr.
Exactly, but not complete.
There is other half of "the intent of the auto_ptr class" - ensure that it
(poniter) is moved (extracted from) to other auto_ptr or C-style pointer
_only once_, independent from lifetime of auto_ptr.
In other words, there is a piece of the auto_ptr life-time when the auto_ptr
has incorrect state and it is not error condition, it is predefined
(designed) condition.
We must demand last half of the auto_ptr state because the behaviour of the
auto_ptr is only useful and reliable among all other possible behaviours of
auto_ptr, because we do not want to introduce possible runtime errors
(especialy on such fundamental and low level as auto_ptr do) due to C++ does
not allow to control auto object, have destroyed befor object bacame
invisible and the memory of the object formally has returned into free
state.
Also we must demand last half of the auto_ptr state, because of behaviour of
the auto_ptr is not like behaviour of rvalue in expression, for example
auto_ptr a,b;
a=b;
is unrolled to
{
a=b:
tr, //ok
b=0; //error - unexpected assignment to rvalue from invisible
sourse
}
The same as "a=b", but correct expression is
//we do not expect here, that "b" will be unchanged
b.move(&a);
But we need auto_ptr to be able to be as rvalue and control memory
simultaneously.
It looks like "operator=" is wrong used here. We can introduce new C++
"operator<-" to reflect the fact of necessety to have "move-like" operations
(changing both rvalue and lvalue) for wrappers in C++
//we now can expect that state of "b" is changed
//we no need "non-const b" to warn user about
//the possible changes here
a<-b;
The "<-" excpression is busy by "<" and "-", so can be other variants: the
"=<" or "<--" looks ugly. Note that "<<" can not be used due to precedence
("=<" must have "=" priority) and due to rvalue of most C++ operators
expected as const. We need operator, rvalue of with is non-const by default.
New "operator<-" can help to programmer to understand what is going on, but
can not garantee at compile stage, that never will be double move (can not
garantee at compile stage, that any operation will not be applied to object
in incorrect state).
It is only way to do both goals safe - to have ability to tell to compiler
that from the point of "move" applied, auto_ptr de facto is destroyed, in
spite of the fact that formaly the auto_ptr is still exist and visible till
end of block.
The way to have ability to tell to compiler about is using "once", "ctor",
"dtor" and "after" keywords (mybe we need "befor" - to complete sequence).
The "state" of the
auto_ptr would be the contained pointer.
No, it is not. The "state" of the auto_ptr is not "contained pointer". It is
better to say that state of the auto_ptr is "stored pointer or incorrect",
state can not be divided. If assumig, that you will not use auto_ptr in
incorrect state, stored pointer can not be changed (excluding explicit
assignment new value to auto_ptr). Note, that non-const can not protect you
from usage of auto_ptr in incorrect state.
In the auto_ptr
example, it would be wrong to make the contained pointer mutable as it
contributes directly to the purpose of the class.
You are operating in wrong definition of "purpose of the auto_ptr".
Offhand I don't see how you could enforce your "once" keyword across
translation units at compile time. How would the system know that:
my_auto_ptr<Obj> ptr(new Obj);
fn(ptr);
ptr->get_pointer();
is legal or not? Remember that all the compiler knows is that fn() takes
a my_auto_ptr as a parameter, it doesn't know what its going to do with
it.
I have posted the example similar to this below:
We can see differences between boo(ptr) and woo(ptr). Compiler can support
even auto_ptr passed by reference but general solution for support testing
"across
translation units at compile time" - do not pass auto_ptr by reference - in
any case at least you will be warned by compiler that if you want the
reference you must take control of the usage of the auto_ptr.
1) Pass large structures: generally speaking, I agree.
2) Declare NULL of default value: depends on the function. Perhaps that
function may use NULL as an indication that the caller doesn't care about
the output buffer, so don't bother making one.
Agree, i have assumed bufer that will be used.
3) Still don't see why auto_ptr's should not be passed by reference.
Because you either can use the auto_ptr in external function (but can not
here), or can not use the auto_ptr in external function (but can here).
Passing the auto_ptr by reference allows you to use the auto_ptr in both
places, but that prohibited by auto_ptr declaration logic.
If you are not going to call "move" inside external function - pass ordinary
pointer, if you want to call "move" there - pass auto_ptr by value, because
you already will not be able to call "move" here (after extermal funtion
will return).
You can not distribute control of one part of memory into some separated
parts of unknown code without runtime tests and appearence of runtime
errors.
The useful limitation allows you to avoid usage hard shared_ptr instead of
easy auto_ptr.
Careful... remember that destructors are only called when the object is
ending its life.
The ordinary destructor yes, but like-destructor not duty. Object can be
into incorrect state befor ordinary destructor will be applied, but the
question is "can we tell to compiler about incorrect state of onject or can
not tell". The price of question is ability of compile time test instead of
runtime.
And thus you're confusing your potential users of your class. If I've
got a const object, I should be able to call const methods on it.
You can call const methods, it is independent from passing object by
reference. It can happend if C++ declares operators "to make reference for
function parameters" - the operators can be declared by user as protected
and you will be not able to compile code with function with references as
parameters due to "private in this context".
Again... how can the compiler enforce these across translation units?
See upper
That requires complete visibility of the object's lifespan.
No, compiler can do his best, and well-designed inplementations will be able
to use all advantages of compile time testing. The fact, that code can be
wrong structured must not disable useful compile time testing.
As for auto_ptr - the auto_ptr is local stuff - must be used inside one
scope and must not be passed to any other places, because its goal to do
memory management of new dynamic object passed to the scope (in fact to free
memory if function makes unexpected return).
Not easily
possible (as far as I know) due to the separate compilation of the
translation units.
If you want to give the control to any other places - make new auto_ptr.
So far I haven't seen a useful purpose to disallowing pass by reference
(and by extention, pass by pointer).
Yes, probably operator "reference" can control both reference and pointer,
not sure.
As outcome of your opinion - "you no need the property and the fact is
enough base, in order to refuse from include the property to language".
I think so:
- because you do not tell me how to solve the detecting troubles (to make
usage of auto_ptr safe), your main objection - "i have no any troubles";
- because you sometimes do not say no one convincing base of your decisions
(exclude your habits).
It is looks something like if we have fallen into dirt, then stood up and
said - there is no any dirt here
.