Re: setter for deleter in boost::shared_ptr (and alike)
* Kai-Uwe Bux:
Alf P. Steinbach wrote:
However, whether the client code can assign is independent of the
guarantees. shared_ptr does not prevent assignment. By your own
argument that client code can prevent assignment, it can also enable
assignment, thus, you can always assign.
The _always_ does not follow. You can assign if and only if you did not
disable it.
Argh, I'm tired (it's late at night). You can enter your own car's
unsafe motor compartment only if you didn't so much desire to not be
able to enter that you manufactured a fitting key (none provided by the
manufacturer) and locked the non-unlockable-when-locked door. Yes, nice
rhetoric, but what about when your desire /is/ to enter the car's motor
compartment, which after all, presumably, would be the case if you
wanted to enter it? Does the design then prevent you from entering?
No, it does not, and there's no "may" about it.
The point is that the design of shared_ptr<> allows you to make
guarantees at initialization
shared_ptr x_ptr ( new ..., some_deleter );
that cannot be subverted later.
There is no "may" about it.
Right, and if I recall correct, I never claimed there is.
Sorry, you recall incorrectly: you followed up and disputed an argument
against the word "may".
[snip]
Then I face a very uphill battle in trying to convince you. It
reminds me of some debates about
int a[1000];
memset( a, 0, 1000*sizeof(int) );
versus
int a[1000] = {0};
The first few engagements with the opponent usually goes fine: OK, it
actually is possible, OK, it doesn't generate that bad machine code, OK,
it might even generate nearly as good code as the treasured memset. But
then comes the problem that calling memset is perceived as "freedom",
including the freedom to just copy and paste memset-using code, and
restricting oneself to C++ initialization etc. as a -- restriction.
Convincing someone that a restriction can be Good is almost hopeless.
I don't think I've ever succeeded in that.
I fail to see the relation between your example and the question at hand.
Yep, definitely an uphill battle... ;-)
The main purpose of shared_ptr is not convenience, it's safety and
guaranteed behavior.
The main criterion to apply when evaluating the design is therefore
safety and guaranteed behavior.
memset does its thing in a potentially unsafe way. You /can/ use it in
safe ways, by always using it correctly. But it's unsafe because it
makes no guarantees: it's very easy to inadvertently use it incorrectly.
C++ initialization, on the other hand, does its thing (a subset of the
functionality) in a generally completely safe way. It has a limited
"interface" just in order to provide safety and guaranteed behavior.
So, this is the first direct connection: the difference between a
completely safe, but restricted, functionality, and not-so-safe but more
permissive functionality. In that connection, recall the purpose of
shared_ptr that I related above. Namely, safety, guaranteed behavior.
The other connection is one of perceived efficiency, that a little
unsafety is regarded as a price well worth paying for "more efficient"
execution. memset advocates refer to its fantastic efficiency, ignoring
all evidence to the contrary, like the vegetarian maintaining that a cow
is a plant, <url: http://www.youtube.com/watch?v=UgEHZQg7BCw>. You
yourself presented a use case you found convincing seemingly solely
because it allowed a perceived run-time efficient solution to the
problem of dynamically associating clean-up actions with a pointer.
And a third connection is one of perceived simplicity. memset is so
simple, compared to fancy C++ initialization. Assigning to a
shared_ptr's deleter is so simple, compared to creating it with the
correct deleter in the first place. OK, maybe only one out of a
thousand programmers would maintain that. But it's IMO enough.
Have you seriously suggested a change to the standard that would make it
ill-formed to use memset() ?
No, because memset is intentionally a low-level, unsafe facility.
whereas shared_ptr is intended to be a high-level safe facility. The
ability to assign to the deleter is like an intrusion of memset-like
freedom to do whatever you want, any violence, into C++ initialization.
A change to make
MyClass x = x;
ill-formed, guaranteeing a diagnostic, would be a better example than a
change to make use of memset ill-formed. Then we could discuss
real-world examples where this is used (I remember that there was one
ingenious usage), and how the higher level goals could be supported in
more safe ways. The Campaign To Make Initialization Utterly Safe(TM).
For we /expect/ C++ initialization to be safe, yet the above leaves x
with an indeterminate value and involves UB for a non-empty class: it's
an intrusion of memset-like freedom into what we thought was really safe
territory where nothing could hurt, where we could try to do anything
safely (for the nice compiler would stop us if we did unsafe things).
[snipped all the rest, because above is enough]
Cheers, & hth.,
- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]