digitalmars.D - Classes in D and C++
- Andy Little (74/74) Mar 04 2007 Hi all,
- Lionello Lunesu (19/47) Mar 04 2007 Why don't you use "struct" instead? A struct can have functions,
- Bill Baxter (8/61) Mar 04 2007 I don't think that quite works as you wrote.
- Lionello Lunesu (5/69) Mar 05 2007 Actually, I was surprised myself, but it did work. And come to think of
- Sean Kelly (3/7) Mar 05 2007 I must have missed the comment. Glad to hear it!
- Frits van Bommel (25/51) Mar 05 2007 Actually, with a slight modification that compiles just fine:
- Lionello Lunesu (3/9) Mar 05 2007 Ah you found it! I didn't know it was pre-1.0 :)
- Bill Baxter (3/14) Mar 05 2007 Ah, ok. I do remember those vague lines in the changelog now.
- Andy Little (32/35) Mar 05 2007 OK, To explain why I don't want to allow this syntax I need to explain s...
- BCS (4/16) Mar 05 2007 Take a look at this lib. It does most of what I see your lib doing and
- Andy Little (5/23) Mar 05 2007 Hey, that looks interesting, certainly a lot leaner than my Quan library...
- Andy Little (33/49) Mar 05 2007 Aha. If I chnge struct to class I am getting something close to what I w...
- Jarrett Billingsley (3/17) Mar 05 2007 ^^^ Don't forget to 'new' the instance of X here!
- Uno (1/8) Mar 05 2007 Yep, I don't like that syntax too. Everywhere news.. And although D has ...
- Walter Bright (4/14) Mar 05 2007 You can do:
- Daniel Keep (10/28) Mar 05 2007 Surely you mean
- Max Samukha (35/58) Mar 05 2007 I think he means structs:
- Max Samukha (3/66) Mar 05 2007 Correction: surely not classes are allocated but objects.
- Kyle Furlong (1/26) Mar 05 2007 http://www.digitalmars.com/d/memory.html#stackclass
- Daniel Keep (10/38) Mar 05 2007 Yes, yes; I'm a dimwit. Just ignore me :P With all this talk about
- Lionello Lunesu (5/23) Mar 05 2007 Uh, I think this one should go on the eater-eggs list!?
- Lionello Lunesu (3/27) Mar 05 2007 Uhm I think you'll still need a struct + static opCall for this to work.
- Uno (1/6) Mar 05 2007 I didn't know that shortcut.. thanks! Now it looks much better and it's ...
- Sean Kelly (7/14) Mar 05 2007 The problem with the C++ form is that it's semantically identical to a
Hi all, I have been evaluating D over the last day in comparison to C++. The template metaprogramming stuff is great and I think its a real improvement over C++. Sadly though theshowstopper for me is user defined types ( classes). I was hoping that I could port my physical quantities library to D, but the killer is the difference between classes in D and C++. In C++ it is possible to create classes that act pretty much like inbuilt types. I used this to good effect in my quan library. Unfortunately in D although you can do: class X{ this( int n_in){...} } Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3); Following is a cut down example of useage of my C++ Quan library, which I hope shows why this requirement on class types is (though possible) highly impractical for what I wanted to do. The physical quanties here are all UDT's (e.g classes) rather than double typedefs FWIW and are compile time checked to conform to dimensional analysis rules. I sincerely hope that this post is seen in the right spirit. I am not attempting to be a troll, but just trying to explain where I am at in relation to D, and just kind of disappointed right now that D doesnt allow the flexibility with classes that I have in C++. e.g create classes with constructors on the stack, arbitrary temporaries etc, which may be syntactic sugar to an extent but is IMO very useful and satisfying to code. Of course I may have this all wrong ...? regards Andy Little // C++ code. compute chord and angle of wind turbine blade sections // using my quan library chord_omega RotorDialog::getChordOmega(quan::length::m const& r)const { using quan::length; using quan::velocity; using quan::mass_flow; using quan::force; using quan::pow; using quan::constant; using quan::angle; length::m const tip_r = this->m_outer_dia / 2.0; if (r > tip_r){ throw std::out_of_range("getChordOmega Input radius is out of range"); } velocity::m_per_s const Vin_y = this->m_vw; length::m const dr = get_section_spacing(); velocity::m_per_s const Vout_y = Vin_y * ( (r < tip_r) ? 1.0 - ((2.0 / 3.0) * (1.0 - this->m_ellipticality) + (this->m_ellipticality * sqrt(1.0 - pow<2>(r / tip_r) ))) : 1.0 - (2.0/3.0)*(1.0 - this->m_ellipticality) ); velocity::m_per_s const Vb_y = (Vin_y + Vout_y) / 2.0; mass_flow::kg_per_s const air_mass_flow = Vb_y * 2 * constant::pi * r * m_rho_air * dr; force::N const Fb_y = air_mass_flow * (Vin_y - Vout_y) ; double const cl = this->m_cl; double const drag_coeff = this->m_cd / cl; velocity::m_per_s const epsilon = 0.0001 * abs(Vin_y); velocity::m_per_s const Vin_x = Vin_y * this->m_tsr * (r / tip_r); velocity::m_per_s Vout_x(0); velocity::m_per_s oldVout_x(0); for (int i = 0 ;i < 1000 ; ++i){ velocity::m_per_s const Vb_x = Vout_x / 2.0 + Vin_x; angle::rad const beta = atan2(Vb_y,Vb_x); double const cos_beta = quan::cos(beta); double const sin_beta = quan::sin(beta); force::N const Lift = Fb_y /(cos_beta + drag_coeff * sin_beta); force::N const Fb_x = Lift * (sin_beta - drag_coeff * cos_beta); oldVout_x = Vout_x; Vout_x = Fb_x / air_mass_flow; if (compare(Vout_x,oldVout_x,epsilon) == 0 ){ length::m const chord = Lift / ( (quan::pow<2>(Vb_x) + quan::pow<2>(Vb_y) ) * 0.5 * this->m_rho_air * cl * dr * this->m_numblades ); return chord_omega(chord,beta ); } }//fail return chord_omega(length::mm(0.0),angle::rad(0.0)); }
Mar 04 2007
Andy Little wrote:Hi all, I have been evaluating D over the last day in comparison to C++. The template metaprogramming stuff is great and I think its a real improvement over C++. Sadly though theshowstopper for me is user defined types ( classes). I was hoping that I could port my physical quantities library to D, but the killer is the difference between classes in D and C++. In C++ it is possible to create classes that act pretty much like inbuilt types. I used this to good effect in my quan library. Unfortunately in D although you can do: class X{ this( int n_in){...} } Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Why don't you use "struct" instead? A struct can have functions, operator overloads, just no constructor/destructor/virtuals, but for simple types these shouldn't be needed. For custom types that behave as value types, you should be using a "struct" instead of a class. Instead of a constructor, create a "static opCall". opCall is the overload for "(..)" so you can instantiate your type similar to C++: struct SomeType { int member = 0;// default initializer here static SomeType opCall( int whatever ) { SomeType st; st.member = whatever;//custom initialize return st; } //... } SomeType st = 2;//construction No need for constructors ;) L.
Mar 04 2007
Lionello Lunesu wrote:Andy Little wrote:I don't think that quite works as you wrote. I think it needs to be SomeType st = SomeType(2); or auto st = SomeType(2); if you want to avoid repeating your repeat-avoiding self repeatedly. --bbHi all, I have been evaluating D over the last day in comparison to C++. The template metaprogramming stuff is great and I think its> a real improvement over C++.Sadly though theshowstopper for me is user defined types> ( classes). I was hoping that I could port my physical quantities > library to D, but the killer is the difference between classes in > D and C++.In C++ it is possible to create classes that act pretty much like> inbuilt types. I used this to good effect in my quan library.Unfortunately in D although you can do: class X{ this( int n_in){...} } Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Why don't you use "struct" instead? A struct can have functions, operator overloads, just no constructor/destructor/virtuals, but for simple types these shouldn't be needed. For custom types that behave as value types, you should be using a "struct" instead of a class. Instead of a constructor, create a "static opCall". opCall is the overload for "(..)" so you can instantiate your type similar to C++: struct SomeType { int member = 0;// default initializer here static SomeType opCall( int whatever ) { SomeType st; st.member = whatever;//custom initialize return st; } //... } SomeType st = 2;//construction No need for constructors ;) L.
Mar 04 2007
Bill Baxter wrote:Lionello Lunesu wrote:Actually, I was surprised myself, but it did work. And come to think of it, I remember Walter mentioning that he made it work, but I can't seem to find any reference to this in the changelog... L.Andy Little wrote:I don't think that quite works as you wrote. I think it needs to be SomeType st = SomeType(2); or auto st = SomeType(2); if you want to avoid repeating your repeat-avoiding self repeatedly. --bbHi all, I have been evaluating D over the last day in comparison to C++. The template metaprogramming stuff is great and I think its> a real improvement over C++.Sadly though theshowstopper for me is user defined types> ( classes). I was hoping that I could port my physical quantities > library to D, but the killer is the difference between classes in > D and C++.In C++ it is possible to create classes that act pretty much like> inbuilt types. I used this to good effect in my quan library.Unfortunately in D although you can do: class X{ this( int n_in){...} } Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Why don't you use "struct" instead? A struct can have functions, operator overloads, just no constructor/destructor/virtuals, but for simple types these shouldn't be needed. For custom types that behave as value types, you should be using a "struct" instead of a class. Instead of a constructor, create a "static opCall". opCall is the overload for "(..)" so you can instantiate your type similar to C++: struct SomeType { int member = 0;// default initializer here static SomeType opCall( int whatever ) { SomeType st; st.member = whatever;//custom initialize return st; } //... } SomeType st = 2;//construction No need for constructors ;) L.
Mar 05 2007
Lionello Lunesu wrote:Actually, I was surprised myself, but it did work. And come to think of it, I remember Walter mentioning that he made it work, but I can't seem to find any reference to this in the changelog...I must have missed the comment. Glad to hear it! Sean
Mar 05 2007
Bill Baxter wrote:Lionello Lunesu wrote:Actually, with a slight modification that compiles just fine: --- struct SomeType { int member = 0;// default initializer here static SomeType opCall( int whatever ) { SomeType st; st.member = whatever;//custom initialize return st; } //... } void main() { SomeType st = 2;//construction } --- Static opCall isn't compile-time executable since it uses a struct :(, so the declaration must be in a function. (This is actually a pretty good argument to allow compile-time execution to work with structs, I think) This has been allowed for a while now, see http://www.digitalmars.com/d/changelog2.html#new0177 : --- ---Instead of a constructor, create a "static opCall". opCall is the overload for "(..)" so you can instantiate your type similar to C++: struct SomeType { int member = 0;// default initializer here static SomeType opCall( int whatever ) { SomeType st; st.member = whatever;//custom initialize return st; } //... } SomeType st = 2;//construction No need for constructors ;)I don't think that quite works as you wrote. I think it needs to be SomeType st = SomeType(2); or auto st = SomeType(2); if you want to avoid repeating your repeat-avoiding self repeatedly.
Mar 05 2007
Frits van Bommel wrote:This has been allowed for a while now, see http://www.digitalmars.com/d/changelog2.html#new0177 : --- ---Ah you found it! I didn't know it was pre-1.0 :) L.
Mar 05 2007
Lionello Lunesu wrote:Frits van Bommel wrote:Ah, ok. I do remember those vague lines in the changelog now. --bbThis has been allowed for a while now, see http://www.digitalmars.com/d/changelog2.html#new0177 : --- ---Ah you found it! I didn't know it was pre-1.0 :) L.
Mar 05 2007
Lionello Lunesu Wrote:SomeType st = 2;//construction No need for constructors ;)OK, To explain why I don't want to allow this syntax I need to explain som of how the quan library works. Its main purpose is to catch errors in dimensional analysis. So for example : assume some types representing Force, Mass and Acceleration. Now I say Mass m; Acceleration; Force f = m * a; // OK this is dimensionally correct according to Physics. However If I say: Force f = m / a; // Error. This is dimensionally not correct and the library is designed to not allow this to compile. In fact the dimension of all physical quantities can be represented as combinations of powers of the base dimensions e.g( in The SI system): length, mass, time, temperature, current, substance, intensity. Force for example is mass^1, length ^1, time ^-2 etc. (Just to jog the memory of Physics lessons) (And behind the scenes this is how the library works, by computing the resulting dimension in a calculation using metaprogramming) Also there are so called dimensionless quantities and these are represented in the library by inbuilt types. e.g int, double etc are seen by the library as dimensionless types, and certain calculations Do result in dimensionless types. E.g: Length L1, L2; double ratio = L1/ L2; // OK the result is dimensionless so is a numeric type. Therefore I don't allow the syntax: Length L= 1; As it is dimensionally incorrect to convert a numeric type to a physical quantity I do however allow the syntax Length L(1); It is specifically allowed to allow value initialisation of a physical_quantity from a numeric. (At some point you need to load the initial value and experience of quan library shows this works and is a compact way to express it) In C++ these 2 forms of initialisation can be differentiated by making the constructor explicit, which is basically how I deal with it in C++. I can get the explicit syntax in D I think by using a static OpCall, but I cant avoid the implicit construction :-( Finally The physical quantity class is actually more complicated and can be constructed with dimensionally equivalent quantities but with other units and so on. I am not sure how I would tackle that problem in D, but at the moment I am stuck on this one. regards Andy Little
Mar 05 2007
Andy Little wrote:Lionello Lunesu Wrote:Take a look at this lib. It does most of what I see your lib doing and might give you some ides on how to make yours work in D. http://www.csc.kth.se/~ol/physical.dSomeType st = 2;//construction No need for constructors ;)OK, To explain why I don't want to allow this syntax I need to explain som of how the quan library works. Its main purpose is to catch errors in dimensional analysis.
Mar 05 2007
BCS Wrote:Andy Little wrote:Hey, that looks interesting, certainly a lot leaner than my Quan library. The example made me laugh as it seems to be a D version of one of the examples in Quan. It will be interesting to study as I know the domain and so it will certainly help me to understand a bit more about D. Are there any plans to flesh it out? ( though it looks pretty functional already). Seems like it could be a nice example for D. regards Andy LittleLionello Lunesu Wrote:Take a look at this lib. It does most of what I see your lib doing and might give you some ides on how to make yours work in D. http://www.csc.kth.se/~ol/physical.dSomeType st = 2;//construction No need for constructors ;)OK, To explain why I don't want to allow this syntax I need to explain som of how the quan library works. Its main purpose is to catch errors in dimensional analysis.
Mar 05 2007
Lionello Lunesu Wrote:Instead of a constructor, create a "static opCall". opCall is the overload for "(..)" so you can instantiate your type similar to C++: struct SomeType { int member = 0;// default initializer here static SomeType opCall( int whatever ) { SomeType st; st.member = whatever;//custom initialize return st; } //... } SomeType st = 2;//construction No need for constructors ;)Aha. If I chnge struct to class I am getting something close to what I want: import std.stdio; class X{ static X opCall( double n ) { X xx; xx.x = n; return xx; } private: double x; } int main(char[][] args) { X x = X(3); //ok X x = 3; // lError ine 21 X y = x; // OK writefln("%s",x.x); return 0; } gives: class1.d(21): Error: cannot implicitly convert expression (3) of type int to cla ss1.X Error: cannot cast int to class1.X (Which is what I want :-) ) That sorts that case out. I'm back on the road for the moment :-) regards Andy Little
Mar 05 2007
"Andy Little" <andy servocomm.freeserve.co.uk> wrote in message news:esgps5$2116$1 digitalmars.com...Aha. If I chnge struct to class I am getting something close to what I want: import std.stdio; class X{ static X opCall( double n ) { X xx;^^^ Don't forget to 'new' the instance of X here!xx.x = n; return xx; } private: double x; }
Mar 05 2007
Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
Uno wrote:You can do: auto x = X(3); and x will be put on the stack.Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
Walter Bright wrote:Uno wrote:Surely you mean scope x = X(3); Or did scope get rolled back into the auto keyword again while I wasn't looking? >_< -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/You can do: auto x = X(3); and x will be put on the stack.Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
On Mon, 05 Mar 2007 20:15:04 +1100, Daniel Keep <daniel.keep.lists gmail.com> wrote:Walter Bright wrote:I think he means structs: struct X{ static X opCall( int n_in){ X x; return x; } } void main() { auto x = X(1); //allocates x of type X on stack and assigns the result of X.opCall(1) to it. X x1 = 1; // does the same thing to x1 x1 = cast(X)2; //calls X.opCall(2) and assigns the result to x1; } Scope classes are allocated on stack but still require 'new'. class X { this(int n_in) { } ~this() { } } void test() { ` scope auto x = new X(1); // x allocated on stack } //~this called on x on scope exit void main() { test(); }Uno wrote:Surely you mean scope x = X(3); Or did scope get rolled back into the auto keyword again while I wasn't looking? >_<You can do: auto x = X(3); and x will be put on the stack.Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
On Mon, 05 Mar 2007 12:10:53 +0200, Max Samukha <samukha voliacable.com> wrote:On Mon, 05 Mar 2007 20:15:04 +1100, Daniel Keep <daniel.keep.lists gmail.com> wrote:Correction: surely not classes are allocated but objects.Walter Bright wrote:I think he means structs: struct X{ static X opCall( int n_in){ X x; return x; } } void main() { auto x = X(1); //allocates x of type X on stack and assigns the result of X.opCall(1) to it. X x1 = 1; // does the same thing to x1 x1 = cast(X)2; //calls X.opCall(2) and assigns the result to x1; } Scope classes are allocated on stack but still require 'new'. class X { this(int n_in) { } ~this() { } } void test() { ` scope auto x = new X(1); // x allocated on stack } //~this called on x on scope exit void main() { test(); }Uno wrote:Surely you mean scope x = X(3); Or did scope get rolled back into the auto keyword again while I wasn't looking? >_<You can do: auto x = X(3); and x will be put on the stack.Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
Walter Bright wrote:http://www.digitalmars.com/d/memory.html#stackclassUno wrote:Surely you mean scope x = X(3); Or did scope get rolled back into the auto keyword again while I wasn't looking? >_<You can do: auto x = X(3); and x will be put on the stack.Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
Kyle Furlong wrote:Yes, yes; I'm a dimwit. Just ignore me :P With all this talk about structs and classes and static opCall, I forgot which one we were talking about :3 -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/Walter Bright wrote:http://www.digitalmars.com/d/memory.html#stackclassUno wrote:Surely you mean scope x = X(3); Or did scope get rolled back into the auto keyword again while I wasn't looking? >_<You can do: auto x = X(3); and x will be put on the stack.Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
Walter Bright wrote:Uno wrote:Uh, I think this one should go on the eater-eggs list!? I've read the docs on "Allocating Class Instances On The Stack" but I had no idea you could instantiate classes without 'new'! I love it! L.You can do: auto x = X(3); and x will be put on the stack.Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
Lionello Lunesu wrote:Walter Bright wrote:Uhm I think you'll still need a struct + static opCall for this to work. L.Uno wrote:Uh, I think this one should go on the eater-eggs list!? I've read the docs on "Allocating Class Instances On The Stack" but I had no idea you could instantiate classes without 'new'! I love it!You can do: auto x = X(3); and x will be put on the stack.Its not possible it seems to do e.g this: X x(3); rather you have to do: X x = new X(3);Yep, I don't like that syntax too. Everywhere news.. And although D has many great features such small things prevent me to switch to D.
Mar 05 2007
You can do: auto x = X(3); and x will be put on the stack.I didn't know that shortcut.. thanks! Now it looks much better and it's acceptable for me, but c++ form is still shorter and more elegant (of course it's disputable).
Mar 05 2007
Uno wrote:The problem with the C++ form is that it's semantically identical to a function prototype statement. I do think it would be great if there were a common syntax to construct all types in D, but I'm not sure if "X x(a)" is it. "X x = X(a)" is probably better. But I'd like this to work for concrete types as well. SeanYou can do: auto x = X(3); and x will be put on the stack.I didn't know that shortcut.. thanks! Now it looks much better and it's acceptable for me, but c++ form is still shorter and more elegant (of course it's disputable).
Mar 05 2007