www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - byval keyword to make objects act as value types

reply BC <NOTmi_emayl_adrez hotmail.com.remove.not> writes:
so that 'byval MyClass' is a new type that acts like MyClass in all ways=
  =

(ie. is polymorphic) except that it gets dupped on non-const assignment =
 =

 from other byval MyClasses and normal MyClasses. possibly also on  =

assignment to normal MyClasses. this would require that it *has* a dup  =

method, or maybe a copy constructor

byval Base b =3D new Derived;

despite the name 'byval' b actually holds a reference to a copy of  =

Derived, so slicing is avoided.
or, if that's too inefficient perhaps the linker can figure out the size=
  =

of the largest class derived from Base and allocate that much on the  =

stack/inside a containing class.

myFunction(ref Base arg)
{
    ++arg;
}

myFunction(b)

i'm thinking it should be overridable so that the above function *does* =
 =

change the value of b
question: are calls to final class member functions non-virtual?

i notice the tango iterators are classes. surely we want to use iterator=
s  =

as value types... this way, we can.

alternatively, since scope objects are a bit like value types already,  =

perhaps we can just add the functionality to that.

then, we just need to return refs from functions, and it's goodbye C++!
Dec 22 2007
next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
BC wrote:
 so that 'byval MyClass' is a new type that acts like MyClass in all ways 
 (ie. is polymorphic) except that it gets dupped on non-const assignment 
 from other byval MyClasses and normal MyClasses. possibly also on 
 assignment to normal MyClasses. this would require that it *has* a dup 
 method, or maybe a copy constructor
Perhaps this would be better as a class declaration modifier? byval class Foo {} // acts like a struct Or: valueclass Foo {} It would be simpler, at least: an opAssign overload.
 byval Base b = new Derived;
 
 despite the name 'byval' b actually holds a reference to a copy of 
 Derived, so slicing is avoided.
 or, if that's too inefficient perhaps the linker can figure out the size 
 of the largest class derived from Base and allocate that much on the 
 stack/inside a containing class.
If we get this, I'm going to ask for virtual template methods in classes again. It's not happening.
 myFunction(ref Base arg)
 {
    ++arg;
 }
 
 myFunction(b)
 
 i'm thinking it should be overridable so that the above function *does* 
 change the value of b
Besides which, arg isn't assigned to... void func(ref ValueClass arg) { arg = new ValueClass(); }
 question: are calls to final class member functions non-virtual?
Well, yes. But do you mean, are they found in the vtbl? You could check: class Foo { final void a(){} final void b(){} final void c(){} } assert (Foo.classinfo.vtbl.length == Object.classinfo.vtbl.length);
 i notice the tango iterators are classes. surely we want to use 
 iterators as value types... this way, we can.
 
 alternatively, since scope objects are a bit like value types already, 
 perhaps we can just add the functionality to that.
Ugh. No.
 then, we just need to return refs from functions, and it's goodbye C++!
Dec 22 2007
parent reply BC <NOTmi_emayl_adrez hotmail.com.remove.not> writes:
On Sun, 23 Dec 2007 04:01:30 -0000, Christopher Wright  =

<dhasenan gmail.com> wrote:

 BC wrote:
 so that 'byval MyClass' is a new type that acts like MyClass in all  =
 ways (ie. is polymorphic) except that it gets dupped on non-const  =
 assignment from other byval MyClasses and normal MyClasses. possibly =
=
 also on assignment to normal MyClasses. this would require that it  =
 *has* a dup method, or maybe a copy constructor
Perhaps this would be better as a class declaration modifier? byval class Foo {} // acts like a struct Or: valueclass Foo {} It would be simpler, at least: an opAssign overload.
true, it's just that I don't buy that classes are always either value or= reference types, I think flexibility is desirable. you could still do class Foo{} alias byval Foo VFoo;
 byval Base b =3D new Derived;
  despite the name 'byval' b actually holds a reference to a copy of  =
 Derived, so slicing is avoided.
 or, if that's too inefficient perhaps the linker can figure out the  =
 size of the largest class derived from Base and allocate that much on=
=
 the stack/inside a containing class.
If we get this, I'm going to ask for virtual template methods in class=
es =
 again. It's not happening.
no, i'm not holding my breath. it could for final classes though.
 myFunction(ref Base arg)
 {
    ++arg;
 }
  myFunction(b)
  i'm thinking it should be overridable so that the above function  =
 *does* change the value of b
Besides which, arg isn't assigned to... void func(ref ValueClass arg) { arg =3D new ValueClass(); }
 question: are calls to final class member functions non-virtual?
Well, yes. But do you mean, are they found in the vtbl? You could chec=
k:
 class Foo {
     final void a(){}
     final void b(){}
     final void c(){}
 }

 assert (Foo.classinfo.vtbl.length =3D=3D Object.classinfo.vtbl.length)=
;

i should have said 'member functions of final classes'. both are found
in the vtbl. i was wondering how close to struct behaviour we can bring
classes.

 i notice the tango iterators are classes. surely we want to use  =
 iterators as value types... this way, we can.
  alternatively, since scope objects are a bit like value types alread=
y, =
 perhaps we can just add the functionality to that.
Ugh. No.
no? currently the spec says you can't assign to them (although i see now= that you can), so i thought that might be the plan.
 then, we just need to return refs from functions, and it's goodbye C+=
+!
Dec 22 2007
next sibling parent reply BC <NOTmi_emayl_adrez hotmail.com.remove.not> writes:
On Sun, 23 Dec 2007 05:09:43 -0000, BC  =

<NOTmi_emayl_adrez hotmail.com.remove.not> wrote:

 On Sun, 23 Dec 2007 04:01:30 -0000, Christopher Wright  =
 <dhasenan gmail.com> wrote:

 BC wrote:
 so that 'byval MyClass' is a new type that acts like MyClass in all =
=
 ways (ie. is polymorphic) except that it gets dupped on non-const  =
 assignment from other byval MyClasses and normal MyClasses. possibly=
=
 also on assignment to normal MyClasses. this would require that it  =
 *has* a dup method, or maybe a copy constructor
Perhaps this would be better as a class declaration modifier? byval class Foo {} // acts like a struct Or: valueclass Foo {} It would be simpler, at least: an opAssign overload.
true, it's just that I don't buy that classes are always either value =
or
 reference types, I think flexibility is desirable. you could still do

 class Foo{}
 alias byval Foo VFoo;

 byval Base b =3D new Derived;
  despite the name 'byval' b actually holds a reference to a copy of =
=
 Derived, so slicing is avoided.
 or, if that's too inefficient perhaps the linker can figure out the =
=
 size of the largest class derived from Base and allocate that much o=
n =
 the stack/inside a containing class.
If we get this, I'm going to ask for virtual template methods in =
 classes again. It's not happening.
no, i'm not holding my breath. it could for final classes though.
 myFunction(ref Base arg)
 {
    ++arg;
 }
  myFunction(b)
  i'm thinking it should be overridable so that the above function  =
 *does* change the value of b
Besides which, arg isn't assigned to... void func(ref ValueClass arg) { arg =3D new ValueClass(); }
i didn't realise you could have a reference to a reference
 question: are calls to final class member functions non-virtual?
Well, yes. But do you mean, are they found in the vtbl? You could che=
ck:
 class Foo {
     final void a(){}
     final void b(){}
     final void c(){}
 }

 assert (Foo.classinfo.vtbl.length =3D=3D Object.classinfo.vtbl.length=
);

 i should have said 'member functions of final classes'. both are found=
 in the vtbl. i was wondering how close to struct behaviour we can brin=
g
 classes.

 i notice the tango iterators are classes. surely we want to use  =
 iterators as value types... this way, we can.
  alternatively, since scope objects are a bit like value types  =
 already, perhaps we can just add the functionality to that.
Ugh. No.
no? currently the spec says you can't assign to them (although i see n=
ow
 that you can, if you like access violations), so i thought that might =
be
 the plan.
don't forget that if you assign it to something else such as a scope obj= ect inside another class, you get a copy, which won't get destroyed, so they could then outlast the function scope and be just like a value type as far as i can see.
 then, we just need to return refs from functions, and it's goodbye C=
++!

Dec 22 2007
parent BC <NOTmi_emayl_adrez hotmail.com.remove.not> writes:
On Sun, 23 Dec 2007 05:40:34 -0000, BC  =

<NOTmi_emayl_adrez hotmail.com.remove.not> wrote:

 On Sun, 23 Dec 2007 05:09:43 -0000, BC  =
 <NOTmi_emayl_adrez hotmail.com.remove.not> wrote:

 On Sun, 23 Dec 2007 04:01:30 -0000, Christopher Wright  =
 <dhasenan gmail.com> wrote:

 BC wrote:
 so that 'byval MyClass' is a new type that acts like MyClass in all=
=
 ways (ie. is polymorphic) except that it gets dupped on non-const  =
 assignment from other byval MyClasses and normal MyClasses. possibl=
y =
 also on assignment to normal MyClasses. this would require that it =
=
 *has* a dup method, or maybe a copy constructor
Perhaps this would be better as a class declaration modifier? byval class Foo {} // acts like a struct Or: valueclass Foo {} It would be simpler, at least: an opAssign overload.
true, it's just that I don't buy that classes are always either value=
or
 reference types, I think flexibility is desirable. you could still do=
 class Foo{}
 alias byval Foo VFoo;

 byval Base b =3D new Derived;
  despite the name 'byval' b actually holds a reference to a copy of=
=
 Derived, so slicing is avoided.
 or, if that's too inefficient perhaps the linker can figure out the=
=
 size of the largest class derived from Base and allocate that much =
on =
 the stack/inside a containing class.
If we get this, I'm going to ask for virtual template methods in =
 classes again. It's not happening.
no, i'm not holding my breath. it could for final classes though.
 myFunction(ref Base arg)
 {
    ++arg;
 }
  myFunction(b)
  i'm thinking it should be overridable so that the above function  =
 *does* change the value of b
Besides which, arg isn't assigned to... void func(ref ValueClass arg) { arg =3D new ValueClass(); }
i didn't realise you could have a reference to a reference
 question: are calls to final class member functions non-virtual?
Well, yes. But do you mean, are they found in the vtbl? You could =
 check:
 class Foo {
     final void a(){}
     final void b(){}
     final void c(){}
 }

 assert (Foo.classinfo.vtbl.length =3D=3D Object.classinfo.vtbl.lengt=
h);

 i should have said 'member functions of final classes'. both are foun=
d
 in the vtbl. i was wondering how close to struct behaviour we can bri=
ng
 classes.
arrghh. only in the vtbl if overriding a base class function, as they ha= ve to be really. but not called virtually from references to the final clas= s/ class in which they are final.
 i notice the tango iterators are classes. surely we want to use  =
 iterators as value types... this way, we can.
  alternatively, since scope objects are a bit like value types  =
 already, perhaps we can just add the functionality to that.
Ugh. No.
no? currently the spec says you can't assign to them (although i see =
now
 that you can, if you like access violations), so i thought that might=
be
 the plan.
don't forget that if you assign it to something else such as a scope =
 object
 inside another class, you get a copy, which won't get destroyed,
 so they could then outlast the function scope and be just like a value=
 type as far as i can see.

 then, we just need to return refs from functions, and it's goodbye =
=
 C++!
Dec 22 2007
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
BC wrote:
 true, it's just that I don't buy that classes are always either value or
 reference types, I think flexibility is desirable. you could still do
 
 class Foo{}
 alias byval Foo VFoo;
byval class VFoo {} alias VFoo* Foo; Close enough.
 i notice the tango iterators are classes. surely we want to use 
 iterators as value types... this way, we can.
  alternatively, since scope objects are a bit like value types 
 already, perhaps we can just add the functionality to that.
Ugh. No.
no? currently the spec says you can't assign to them (although i see now that you can), so i thought that might be the plan.
Unless you can get the functionality while maintaining the current behavior of the scope storage class, I'm against it. You'd never get an unambiguous rule to determine which is to be used in the current case.
Dec 23 2007
prev sibling parent reply "Craig Black" <craigblack2 cox.net> writes:
so that 'byval MyClass' is a new type that acts like MyClass in all ways 
(ie. is polymorphic) except that it gets dupped on non-const assignment 
from other byval MyClasses and normal MyClasses. possibly also on 
assignment to normal MyClasses. this would require that it *has* a dup 
method, or maybe a copy constructor

byval Base b = new Derived;
I'm not really "getting" your proposal, but maybe I missed something. What's the novelty here? Why not just add copy semantics to structs? Then you don't need the byval keyword anymore.
i notice the tango iterators are classes. surely we want to use iterators 
as value types... this way, we can.
I wholeheartedly agree, but why not use structs? -Craig
Dec 22 2007
parent reply BC <notmi_emayl_adreznot hotmail.com.remove.not> writes:
On Sun, 23 Dec 2007 06:22:49 -0000, Craig Black <craigblack2 cox.net>  =

wrote:

 so that 'byval MyClass' is a new type that acts like MyClass in all  =
 ways (ie. is polymorphic) except that it gets dupped on non-const  =
 assignment from other byval MyClasses and normal MyClasses. possibly =
=
 also on assignment to normal MyClasses. this would require that it  =
 *has* a dup method, or maybe a copy constructor

 byval Base b =3D new Derived;
I'm not really "getting" your proposal, but maybe I missed something. =
=
 What's the novelty here?  Why not just add copy semantics to structs? =
=
 Then you don't need the byval keyword anymore.

 i notice the tango iterators are classes. surely we want to use  =
 iterators as value types... this way, we can.
I wholeheartedly agree, but why not use structs? -Craig
well, there's inheritance. polymorphism. also there's not always a = definitive answer to whether a given data structure should be a value or reference type. this way, they can be both.
Dec 22 2007
parent reply BC <notmi_emayl_adreznot hotmail.com.remove.not> writes:
On Sun, 23 Dec 2007 07:52:06 -0000, BC  =

<notmi_emayl_adreznot hotmail.com.remove.not> wrote:

 On Sun, 23 Dec 2007 06:22:49 -0000, Craig Black <craigblack2 cox.net> =
=
 wrote:

 so that 'byval MyClass' is a new type that acts like MyClass in all =
=
 ways (ie. is polymorphic) except that it gets dupped on non-const  =
 assignment from other byval MyClasses and normal MyClasses. possibly=
=
 also on assignment to normal MyClasses. this would require that it  =
 *has* a dup method, or maybe a copy constructor

 byval Base b =3D new Derived;
I'm not really "getting" your proposal, but maybe I missed something.=
=
 What's the novelty here?  Why not just add copy semantics to structs?=
=
 Then you don't need the byval keyword anymore.

 i notice the tango iterators are classes. surely we want to use  =
 iterators as value types... this way, we can.
I wholeheartedly agree, but why not use structs? -Craig
well, there's inheritance. polymorphism. also there's not always a =
 definitive
 answer to whether a given data structure should be a value or referenc=
e
 type. this way, they can be both.
although adding those things and ctors/dtors to structs like you said would be just as good really. i got the impression that option was off the table though. should struct member functions & dtors be virtual by default?
Dec 23 2007
parent "Craig Black" <craigblack2 cox.net> writes:
although adding those things and ctors/dtors to structs like you said
would be just as good really. i got the impression that option was off
the table though.
should struct member functions & dtors be virtual by default?
Good question. Here's my philosophy about virtual by default. I am a performance-oriented guy, and I prefer the compiler to NOT make functions virtual when I don't explicitly say "virtual". For me, virtual by default means I need to be more careful about overriding so something doesn't become virtual accidentally. Further, virtual by default prevents non-virtual overriding, which can be used for high-performance compile-time polymorphism using templates. That said, if this happens at all, Walter would probably use virtual by default for consistency sake. Oh well, I guess it's not that big a deal. If polymorphism is added to structs, it should be optional. I would have a problem if the vtable pointer was included in structs that didn't have any polymorphism. It should work like C++ structs and classes, where there is no overhead for non-polymorphic types. As for virtual destructors, I agree that they should be virtual by default, but only if a type is polymorphic. Forgetting to make a destructor virtual in C++ can cause subtle and annoying bugs. It's good that most C++ compilers issue warnings when a polymorphic type has a non-virtual destructor. However, I would rather the compiler make it virtual for me. -Craig
Dec 23 2007