Inspired by the recent discussion about iterator structs/classes I wanted to
ask - what's the design rationale behind having both structs and classes? In
C++ the necessity was given by backwards compatibility but that doesn't apply
to D of course.
The only principal differences I can see (I'm not a D programmer (yet), so
please correct me if I'm wrong) are a) that structs don't contain run-time meta
information (a pointer to a vtable or however that works) and b) that struct
variables are statically allocated as opposed to class variables which always
seem to be pointers into dynamic memory.
Somehow this looks really unorthogonal to me. Especially b) I find strange, can
somebody explain the reason for this?
cheers
Martin

Inspired by the recent discussion about iterator structs/classes I wanted to
ask - what's the design rationale behind having both structs and classes? In
C++ the necessity was given by backwards compatibility but that doesn't apply
to D of course.
The only principal differences I can see (I'm not a D programmer (yet), so
please correct me if I'm wrong) are a) that structs don't contain run-time meta
information (a pointer to a vtable or however that works) and b) that struct
variables are statically allocated as opposed to class variables which always
seem to be pointers into dynamic memory.
Somehow this looks really unorthogonal to me. Especially b) I find strange,
can somebody explain the reason for this?
cheers
Martin

Firstly, your assertion about C++ is incorrect. C++ doesn't have both,
classes are just structs that are private by default, structs are just
classes that are public by default. A C struct like this:
struct Foo {
int a, b;
}
is 100% equivalent (and passable as) a C++ class like this:
class Bar {
public:
int a, b;
}
Structs in D are very light-weight. A struct is just a conglomeration of
data. Passing a struct which contains two ints is exactly like passing
the two ints, but syntactically less gross. Functions defined within a
struct are basically syntactic sugar around functions that are defined
taking the struct as the first argument.
Classes are properly object oriented: They have hierarchies, methods are
virtual, etc. As such, they're (comparably to structs) heavyweight: They
have classinfo, are allocated on the heap, method calls require looking
in a vtable, etc.
Your 'b' statement is incorrect. In both cases, the data is allocated
where the struct/class is allocated. Just classes are usually on the
heap, structs are generally on the stack.
- Gregor Richards

Inspired by the recent discussion about iterator structs/classes I wanted
to ask - what's the design rationale behind having both structs and classes?
[...]

The most important difference is that structs have value semantics and
classes have reference semantics. There are very good reasons to have
both, and unifying them would be as wrong as taking away pointers or
taking away stack objects.
Dave

Inspired by the recent discussion about iterator structs/classes I wanted
to ask - what's the design rationale behind having both structs and classes?
[...]

The most important difference is that structs have value semantics and
classes have reference semantics. There are very good reasons to have
both, and unifying them would be as wrong as taking away pointers or
taking away stack objects.

I totally agree that both are needed, but is it necessary to tie the difference
to the difference between structs and classes? It would be nice if I could
decide on the spot (i.e. when declaring a variable) in which way to use my type.

Inspired by the recent discussion about iterator structs/classes I wanted
to ask - what's the design rationale behind having both structs and classes?
[...]

classes have reference semantics. There are very good reasons to have
both, and unifying them would be as wrong as taking away pointers or
taking away stack objects.

I totally agree that both are needed, but is it necessary to tie the
difference to the difference between structs and classes? It would be
nice if I could decide on the spot (i.e. when declaring a variable)
in which way to use my type.

Unfortunately, you can't decide "on the spot" whether to use
polymorphism or dynamic dispatch (nor can you make this choice on a
per-instance basis in any other language I know of). The best you can
do is get reference semantics for your structs by using 'ref'. But you
will never get exact value semantics for classes because that could lead
to slicing, which is why classes/structs in C++ are dangerous. However,
you can simulate polymorphic value types by creating invariant classes.
If you want to create both struct and class versions of your type and
select them on a per-instance basis, you can create a template, but that
doesn't make a whole lot of sense to me, so I'm not sure when or why you
would do that.
Dave

Inspired by the recent discussion about iterator structs/classes I wanted
to ask - what's the design rationale behind having both structs and classes?
[...]

classes have reference semantics. There are very good reasons to have
both, and unifying them would be as wrong as taking away pointers or
taking away stack objects.

I totally agree that both are needed, but is it necessary to tie the
difference to the difference between structs and classes? It would be
nice if I could decide on the spot (i.e. when declaring a variable)
in which way to use my type.

Unfortunately, you can't decide "on the spot" whether to use
polymorphism or dynamic dispatch (nor can you make this choice on a
per-instance basis in any other language I know of). The best you can
do is get reference semantics for your structs by using 'ref'. But you
will never get exact value semantics for classes because that could lead
to slicing, which is why classes/structs in C++ are dangerous. However,
you can simulate polymorphic value types by creating invariant classes.
If you want to create both struct and class versions of your type and
select them on a per-instance basis, you can create a template, but that
doesn't make a whole lot of sense to me, so I'm not sure when or why you
would do that.
Dave

But if I understand it correctly the only points where problems can occur are
in casts. This means that it should be possible to implement safeguards since
for a value the type has to be known at compile time anyways whereas a
reference will have RTTI. In both cases it's possible (either for the compiler
or the run-time) to determine whether the cast is valid. The only reason why
C++ fails miserably in this is that per default it just doesn't care about
run-time stuff so every check for validity is up to the (potentially lazy)
programmer. In D it would be perfectly possible to make a hybrid
reference/value system failsafe.
So, you could take a struct value and convert it into a class reference
(probably by internally creating an object and filling it with values from the
struct) and vice versa. Of course you wouldn't call it struct and class but
just values and references of the same type. Note that there would be no reason
to abandon the PODness of structs, when making a struct value from a class
reference you'd just abandon the meta-info.
I think that would simplify matters considerably. I might be totally off here
but from what I've read in the docs and on the mailing list it looked to me as
if the implementations of structs and classes in the compiler are at least to
some degree a parallel effort. In any case, from the user's perspective I find
the differences and the resulting restrictions on structs quite unintuitive and
arbitrary.

[...]
But if I understand it correctly the only points where problems can occur
are in casts. This means that it should be possible to implement safeguards
since for a value the type has to be known at compile time anyways whereas
a reference will have RTTI.
[...]

I guess my problem is lack of motivation. I'm just not seeing the use
cases you are, so I don't see this part of the design space as lacking.
Can you show us where you would like to use this feature and how it is
better than the way things are now?
Dave