improvement request - enabling by-value-containers

Jonathan M Davis jmdavisProg at gmx.com
Wed Dec 8 14:45:35 PST 2010


On Wednesday, December 08, 2010 14:14:57 Simon Buerger wrote:
> For Every lib its a design descision if containers should be value- or
> reference-types. In C++ STL they are value-types (i.e. the
> copy-constructor does a real copy), while in tango and phobos the
> descision was to go for reference-types afaik, but I would like to be
> able to write value-types too, which isn't possible (in a really good
> way) currently. Following points would need some love (by-value
> containers are probably not the only area, where these could be useful)

It's extremely rare in my experience that it makes any sense to copy a container 
on a regular basis. Having an easy means of creating a deep copy of a container 
or copying the elements from one container to another efficiently would be good, 
but having containers be value types is almost always a bad idea. It's just not 
a typical need to need to copy containers - certainly not enough to have them be 
copied just because you passed them to a function or returned them from one. I 
think that reference types for containers is very much the correct decision. 
There should be good ways to copy containers, but copying shouldn't be the 
default for much of anything in the way of containers.

> (1) Allow default-constructors for structs
> I don't see a reason, why "this(int foo)" is allowed, but "this()" is
> not. There might be some useful non-trivial init to do for complex
> structs.

It has to do with the init property. It has to be known at compile-time for all 
types. For classes, that's easy because it's null, but for structs, that's what 
all of their member variables are directly initialized to. If you add a default 
constructor, then it would have to be to whatever that constructed them to, 
which would shift it from compile time to runtime. It should be possible to have 
default constructors which are definitely limited in a number of ways (like 
having to be nothrow and possibly pure), but that hasn't been sorted out, and 
even if it is, plenty of cases where people want default constructors still 
wouldn't likely work. It just doesn't work to have default constructors which 
can run completely arbitrary code. You could get exceptions thrown in weird 
places and a variety of other problems which we can't have in situations where 
init is used. Hopefully, we'll get limited default constructors at some point, 
but it hasn't happened yet (and probably won't without a good proposal that 
deals with all of the potentiall issues), and regardless, it will never be as 
flexible as what C++ does. It's primarily a side effect of insisting that all 
variables be default initialized if they're not directly initialized.

> (2) const parameters by reference
> If a parameter to a function is read-only, the right notion depends on
> the type of that parameter. I.e. "in" for simple stuff like ints, and
> "ref const" for big structures. Using "in" for big data implies a
> whole copy, even though it's constant, and using "ref const" for
> simple types is a useless indirection. This is a problem for generic
> code, when the type is templated, because there is now way to switch
> between "in" and "ref const" with compile-time-reflection.
> 
> Solution one: make "ref" a real type-constructor, so you could do the
> following (this is possible in C++):
> 
> static if(is(T == struct))
> 	alias ref const T const_type;
> else
> 	alias const scope T const_type;
> // "const scope" is (currently) equivalent to "in"
> void foo(const_type x)
> 
> Solution two: let "in" decide wheather to pass by reference or value,
> depending on the type. Probably the better solution cause the
> programmer dont need to care of the descision himself anymore.

I think that auto ref is supposed to deal with some of this, but it's buggy at 
the moment, and I'm not sure exactly what it's supposed to do. There was some 
discussion on this one in a recent thread.

> (3) make foreach parameters constant
> when you do "foreach(x;a)" the x value gets copied in each iteration,
> once again, that matters for big types especially when you have a
> copy-constructor. Current work-around is prepending "ref": nothing
> gets copied, but the compiler wont know it is meant to be read-only.
> Solution: either allow "ref const" or "in" in foreach. Or you could
> even make x default to constant if not stated as "ref" explicitly.
> Last alternative seems logical to me, but it may break existing code.

I'd hate to see foreach variables be const by default. That would be overly 
limiting and would definitely break a lot of code. Making ref const work properly 
would be good (I think that it works in at least some cases) for structs that 
you don't want to be copied but wouldn't be all that useful otherwise. Nothing 
in D is const by default, and I think that making anything const by default 
would clash with the rest of the language. Particularly since then how would you 
make it mutable? No, it should be possible to have const refs to structs for 
foreach variables, but it shouldn't be the default. The language as a whole just 
does not support that.

- Jonathan M Davis


More information about the Digitalmars-d mailing list