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/

Reply via email to