On 2011-12-27 15:48:56 +0000, Andrei Alexandrescu
<seewebsiteforem...@erdani.org> said:
On 12/27/11 9:27 AM, Michel Fortin wrote:
It can't be a library feature because it requires the compiler to
implicitly add a "ref" to functions parameters when they are of a "ref
struct" type. That's pretty much all it does: add a flag to struct
types, implicitly add "ref" to parameters based on that flag.
Anyhow, I think a feature would need to be tremendously justified and
with a huge power/weight ratio.
This one I actually find ill-designed because now I can't look at the
body of a function to figure pass-by-value vs. pass-by-reference I also
need to look at the definition (what if it was a ref struct?). One more
non-modular thing to keep in mind. This is not going to fly.
I think the appeal is that it solves two common problems cleanly.
It can solve the passing of rvalue by reference so you wouldn't need to
add yet another parameter attribute for that (if the type is a ref
struct, this is done implicitly). And it solves the problem of passing
containers to functions (they'd be implicitly passed by ref).
Basically, it solves the general problem where you have to decide every
time you write a function accepting a struct whether it should be by
value or by reference. The designer of the type chooses one behaviour
and that behaviour is the same everywhere.
It's true that it blurs a little more the line between by-value and
by-ref. But note that the line is already quite blurry:
You already don't know by looking at a type name whether a type is an
alias or a class. Or even a struct that mimics reference semantics
through internal trickery (like RefCounted). And what about dynamic
arrays? or ranges? That whole pass-by-value vs. pass-by-reference
dichotomy isn't as black and white as we'd like to think. You can never
tell just by looking at the name what semantics the type has when
"copied".
One thing it does change is it makes function parameters a special case
where there was none before. But why do you think "const T &" is used
all over the place for parameters but almost none elsewhere in C++?
Simply because function parameters *are* a special case. Function
parameters need to be passed around efficiently (hence the "&"), and
they need to accept rvalues (hence the "const").
Everyone forget to write the "&" and the "const" once in a while in
C++, and like you I'd like to avoid this mess in D. I'd say just make
the best way the default: make types that should be passed by reference
passed by reference by default. Trying to force everyone to use
heap-allocated objects, reference counting, or other wrapping schemes
is adding also adding much complexity, probably more than what I'm
proposing.
For containers, the "ref struct" solution prevents fragmentation by
packaging because whatever packaging you use for your container (GC,
RefCounted, COW, or no packaging at all) the underlying implementation
can always be passed by "ref" to a function. And peeling the packaging
part also makes it easier to add const to the container (no mutable
reference counter to update).
If you can find a better idea to solve the fragmentation problem and
the const problem (and separately the rvalue problem), then go on. I'm
just pointing at what seems a good idea to me. You're still free to
find better solutions, even though I'm not convinced there are, at
least not without forcing a one-size-fit-all packaging to everyone.
- - -
Note that I still am in agreement with your current container prototype
design. One important criterion to me is whether I can use the "Impl"
part of it directly and pass it around by ref if I want. Seems like I
can.
--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/