View mode: basic / threaded / horizontal-split · Log in · Help
December 13, 2007
Re: what was wrong with struct & class in C++?
Russell Lewis wrote:
> Hear, hear!  Good arguments, all!  It still doesn't answer why we left 
> out the little star on class-reference variable assignments.  As I've 
> argued before, the question of syntax is orthogonal to the question of 
> legal operations.  Make value-style operations illegal for classes, and 
> keep the star there, IMHO.

It would make writing generic code unnecessarily difficult.
December 14, 2007
Re: what was wrong with struct & class in C++?
Walter Bright wrote:
> Russell Lewis wrote:
>> Hear, hear!  Good arguments, all!  It still doesn't answer why we left 
>> out the little star on class-reference variable assignments.  As I've 
>> argued before, the question of syntax is orthogonal to the question of 
>> legal operations.  Make value-style operations illegal for classes, 
>> and keep the star there, IMHO.
> 
> It would make writing generic code unnecessarily difficult.

????  I thought that one of the key arguments for putting the syntax 
back to the C++ way was that it would make generic code easier to write. 
 Right now, when we perform an assignment, generic code can't know 
(without specialization) whether it is assigning a value or a reference 
type.
December 14, 2007
Re: what was wrong with struct & class in C++?
On Thu, 13 Dec 2007 00:59:33 -0000, BC  
<NOTmi_emayl_adrez@hotmail.com.remove.not> wrote:

>
> I don't see how C++ is forcing anything. C++ is the one that gives you
> the choice. If I want two closely related types to be viewed through a
> common interface or to share implementation in D, I have to accept
> reference semantics as well, everywhere. If you have an aversion to
> by-value objects you can always stick to pointers in C++. Use an alias.
> We're not trying to take anything away, it's an addition.
>

I think the problem with C++ (problem may be too harsh) is you are forced  
to choose between
pass by reference and pass by value semantics. Though in practice you  
rarely choose value semantics.
There seems to be a lot of toing and froing over which is best.
In my opinion there should be one default calling convention and the  
compiler decides
whether to pass by reference or value as it ought to know best which will  
be more efficient.
As programmer you just want to get on and code.
Note the ought though. I think there should be an option to choose one or  
the other when you
as programmer have good reason to believe one will perform better than the  
other. I'm not sure that
D makes this easy.
The important part of the contract is whether the object passed is mutable  
or not and this is why we need const.

Regards,

Bruce. (drunk and sleepy)
December 14, 2007
Re: what was wrong with struct & class in C++?
Russell Lewis wrote:
> Walter Bright wrote:
>> Russell Lewis wrote:
>>> Hear, hear!  Good arguments, all!  It still doesn't answer why we 
>>> left out the little star on class-reference variable assignments.  As 
>>> I've argued before, the question of syntax is orthogonal to the 
>>> question of legal operations.  Make value-style operations illegal 
>>> for classes, and keep the star there, IMHO.
>>
>> It would make writing generic code unnecessarily difficult.
> 
> ????  I thought that one of the key arguments for putting the syntax 
> back to the C++ way was that it would make generic code easier to write. 
>  Right now, when we perform an assignment, generic code can't know 
> (without specialization) whether it is assigning a value or a reference 
> type.

Because if I replace a struct with a class, then I have to go through 
every use of the struct and add a *.
December 14, 2007
Re: what was wrong with struct & class in C++?
"Walter Bright" <newshound1@digitalmars.com> wrote in message 
news:fjs7dt$2civ$1@digitalmars.com...
>>
>> oops, typo, i meant reference counting, obviously.
>> would it be possible to have a way of changing the behaviour of a struct
>> slightly without having to forward all the calls?
>
> The current ideas on doing reference counting in D involve having a struct 
> wrap a class reference. Please note that current C++ reference counting 
> designs do the same thing - C++ offers no efficiency advantage.

Why not have ref counting built in (but optional) for classes, like 'scope' 
is. If the class is defined as such, or the declared as such, then it 
becomes a ref counted object. The ref count could follow the vtable pointer, 
and if it is < 0 then the object is not ref counted, if >= 0 then it is. 
Then any (de)assignments, become a matter of checking the class ref count, 
and a locked inc / dec it if it is a counted class.

Or have ref counted objects as only assignable to ref count referances. Eg..

Foo a;
counted Foo b;
counted Foo c = new Foo();

a = b; // error
b = c; // Ok
c = a; // error

I guess it wouldnt be popular if it added too much overhead to assignments. 
But it can be optimized for the non ref counted situation, the ref counted 
situation would require a lock instruction to be thread safe, and they are 
expensive anyway.

Can the wrapping of a class referance in a struct decrease the ref count on 
scope exit? Eg..

if (somthing)
{
    counted Foo f = this.getFoo();  <- Inc ref count
   // ...
} <-- can the struct wrapping class dec ref count here as f goes out of 
scope?
December 14, 2007
Re: what was wrong with struct & class in C++?
On Thu, 13 Dec 2007 21:13:43 -0000, Walter Bright  
<newshound1@digitalmars.com> wrote:

> BC wrote:
>>> I admit I exaggerated in the original post (or was completely wrong. D  
>>> isn't
>>> broken) Perhaps we could consider all this as just thinking out loud.
>>> I have to say I've never really had a problem with slicing (well, maybe
>>> when I was first learning.) Assigning related value types to each  
>>> other is
>>> conversion, not polymorphism, if you accept that you're ok. You could
>>> make things more interesting though (or a complete hack). You could  
>>> make
>>> all your container types descend from one,
>>> with all virtual functions. In C++ you could then use them as value  
>>> types,
>>> and all the functions get called non-virtually or as a reference and
>>> they're all virtual. Admittedly this rules out the non-virtual case if
>>> using null pointers to save memory for empty containers.
>
> Yes, in C++ you can do all that. The issue is that when both value and  
> reference semantics are mixed together in one class is that it's almost  
> certainly a broken class design. Complicating the problem is the users  
> of a class have to be careful to only use it as a value type, or only  
> use it as a reference type, per the class implementation. I propose that  
> this is an unnecessary burden on both the class designer and the class  
> user, and certainly C++ code is susceptible to many insidious bugs  
> because of it that are very hard to protect against.
>
>
>>> You could
>>> possibly imagine a third way where a reference (giving you  
>>> polymorphism)
>>> simulates value semantics by dupping on every assignment (so you don't
>>> have to worry if two share data).
>>  oops, typo, i meant reference counting, obviously.
>> would it be possible to have a way of changing the behaviour of a struct
>> slightly without having to forward all the calls?
>
> The current ideas on doing reference counting in D involve having a  
> struct wrap a class reference. Please note that current C++ reference  
> counting designs do the same thing - C++ offers no efficiency advantage.

I guess wrapping has most of the same effect as inheritance with  
non-virtual calls. Does that mean it will be possible to overload struct  
T.opAssign(T) to make the counting more robust?

PS. Will dmc++0x be out early due to already implementing most of it once?
December 14, 2007
Re: what was wrong with struct & class in C++?
Walter Bright wrote:
> Yigal Chripun wrote:
>> for me, the distinction between PODs and "objects" should be the 
>> polymorphic behavior, not the size of it (maybe i didn't explain 
>> myself properly). Am i completely wrong here?
> 
> You're right. Any object designed for inheritance or polymorphism should 
> properly be a reference type.

Is this because it is too difficult to implement polymorphism for value 
types safely and efficiently right now?

There's the slicing problem, of course, but there should be ways around 
that: worst case, you could rebuild the current stack frame each time 
you assign a polymorphic struct, but the effects on performance would be 
unpleasant. More happily, you could handle polymorphic structs like 
classes, but copy on (non-const) assignment.

That would be allowed in D, if you could overload T.opAssign(T).
December 15, 2007
Re: what was wrong with struct & class in C++?
Christopher Wright wrote:
> That would be allowed in D, if you could overload T.opAssign(T).

C++ still has well-known slicing problems, even with overloading assignment.

The question is not "can this be done", it's more "is there a compelling 
reason to support such behavior". I think the answer is no. Do you 
really want a language where a class designer feels compelled to define 
an opassign overload, then make it private to prevent people from using 
the class as a value type? Where the base class designer needs to know 
what the derived classes are doing so he can make the destructor virtual 
or not? Where you cannot have arrays of base classes?
December 16, 2007
Re: what was wrong with struct & class in C++?
Walter Bright wrote:
> Christopher Wright wrote:
>> That would be allowed in D, if you could overload T.opAssign(T).
> 
> C++ still has well-known slicing problems, even with overloading 
> assignment.
> 
> The question is not "can this be done", it's more "is there a compelling 
> reason to support such behavior". I think the answer is no. Do you 
> really want a language where a class designer feels compelled to define 
> an opassign overload, then make it private to prevent people from using 
> the class as a value type? Where the base class designer needs to know 
> what the derived classes are doing so he can make the destructor virtual 
> or not? Where you cannot have arrays of base classes?

At least C++ lets you control copying behavior completely in all 
circumstances.  And documents what you are supposed to do clearly. 
Right now D gives you the choice of

1) [structs] copy by value only, with no option to customize or 
intercept copy operations
2) [classes] no defined copy behavior whatsoever

1) makes interesting ref counting wrappers etc impossible, but I think 
you're planning to fix that one.

I think 2) is a problem also.  It means that developers will each come 
up with their own way to copy objects because there's no clear way to do 
it.  I think some particular scheme should be crowned, like any class 
that wants to be copyable should provide a the pair of methods dup(), 
and copy(ThisType).  And maybe there should be something in Object to 
this effect also, even if they don't do much of anything.  Looks like 
java implements a clone() method in the base Object class.  But it looks 
like that just makes it so you get a runtime exception if the class 
you're trying to clone doesn't support cloning.  That doesn't seem like 
an improvement over a compile time error.

So I'm not really sure what should be done, but I definitely think 
something should be done to specify "the D way" to polymorphically copy 
objects.  Built-ins mostly have .dup properties, but I don't think the 
spec actually says anywhere that user classes that want to be copyable 
should have a .dup.  But even specifying a .dup is not enough I think, 
because if I derive from some class A, I have to create my derived 
class, then get class A to copy the A parts of the new object somehow, 
say via a method like A.copy(A copy_from).

C++ may have problems regarding copying classes, but D's solution is 
effectively to just remove the C++ functionality good and bad.  Ok the 
slicing problem is gone, but so is copying.  There should be one obvious 
way to make classes in D copyable, whether it be enforced by the 
language, compiler, or simply the spec and D community.

--bb
December 16, 2007
Re: what was wrong with struct & class in C++?
Bill Baxter wrote:
> Walter Bright wrote:
>> Christopher Wright wrote:
>>> That would be allowed in D, if you could overload T.opAssign(T).
>>
>> C++ still has well-known slicing problems, even with overloading 
>> assignment.
>>
>> The question is not "can this be done", it's more "is there a 
>> compelling reason to support such behavior". I think the answer is no. 
>> Do you really want a language where a class designer feels compelled 
>> to define an opassign overload, then make it private to prevent people 
>> from using the class as a value type? Where the base class designer 
>> needs to know what the derived classes are doing so he can make the 
>> destructor virtual or not? Where you cannot have arrays of base classes?
> 
> At least C++ lets you control copying behavior completely in all 
> circumstances.  And documents what you are supposed to do clearly. Right 
> now D gives you the choice of
> 
> 1) [structs] copy by value only, with no option to customize or 
> intercept copy operations
> 2) [classes] no defined copy behavior whatsoever
> 
> 1) makes interesting ref counting wrappers etc impossible, but I think 
> you're planning to fix that one.
> 
> I think 2) is a problem also.  It means that developers will each come 
> up with their own way to copy objects because there's no clear way to do 
> it.  I think some particular scheme should be crowned, like any class 
> that wants to be copyable should provide a the pair of methods dup(), 
> and copy(ThisType).  And maybe there should be something in Object to 
> this effect also, even if they don't do much of anything.  Looks like 
> java implements a clone() method in the base Object class.  But it looks 
> like that just makes it so you get a runtime exception if the class 
> you're trying to clone doesn't support cloning.  That doesn't seem like 
> an improvement over a compile time error.
> 
> So I'm not really sure what should be done, but I definitely think 
> something should be done to specify "the D way" to polymorphically copy 
> objects.  Built-ins mostly have .dup properties, but I don't think the 
> spec actually says anywhere that user classes that want to be copyable 
> should have a .dup.  But even specifying a .dup is not enough I think, 
> because if I derive from some class A, I have to create my derived 
> class, then get class A to copy the A parts of the new object somehow, 
> say via a method like A.copy(A copy_from).
> 
> C++ may have problems regarding copying classes, but D's solution is 
> effectively to just remove the C++ functionality good and bad.  Ok the 
> slicing problem is gone, but so is copying.  There should be one obvious 
> way to make classes in D copyable, whether it be enforced by the 
> language, compiler, or simply the spec and D community.
> 
> --bb

In java you also need to implement a clonable interface which is a 
marker interface.
I think that adding a clonable interface to the standard library should 
be enough. something like:
---
interface clonable {
	object dup();
}
---
now you need to implement it to support copying. I don't think a dup 
method should be added to object. as you said, it isn't really an 
improvement, and usually Java experts recommend avoiding clone().
also, i don't see why a copy method is required.
for example, check the following code:
---
class Base : clonable {
    Base dup() {
       auto ret = cast(Base) this.classinfo.create;
       ret.x = this.x;
       ret.y = this.y;
       return ret;
    }
    int x = 6;
    double y = 8;
}

class DerivedA : Base {
    override DerivedA dup() {
       auto ret = cast(DerivedA) super.dup;
       ret.w = this.w;
       return ret;
    }
    long w = 42;
}
1 2 3 4
Top | Discussion index | About this forum | D home