digitalmars.D - D vs. placement new (for classes) aka why D needs .sizeof and .alignof for classes (values not references)
- Forest Ray (5/5) Apr 12 2007 Before I add this to the bug database I wanted to run this by everyone a...
- Chris Nicholson-Sauls (14/22) Apr 12 2007 Given:
- Frank Benoit (keinfarbton) (1/5) Apr 12 2007 no, it doesn't :)
- torhu (3/9) Apr 12 2007 obj.classinfo.init.length is documented as 'init.length gives size in
- Frank Benoit (keinfarbton) (3/13) Apr 12 2007 well, i don't know about the size of the class, but it does not give the
- Frank Benoit (keinfarbton) (4/6) Apr 12 2007 I was sure i had an example that shows it doesn't.
- Forest Ray (13/22) Apr 12 2007 Thanks for get me thinking along that path, the size of a class can be f...
- Frank Benoit (keinfarbton) (3/3) Apr 13 2007 Finally i found my testcase...
- Chris Nicholson-Sauls (4/10) Apr 12 2007 Note to self: sleep|eat|veg first, post later. Ah well, at least the co...
- Sean Kelly (3/30) Apr 12 2007 See http://d.puremagic.com/issues/show_bug.cgi?id=88
- Dan (20/20) Apr 13 2007 I love D, one of the reasons being because Walter has provided unprecede...
- Sean Kelly (34/63) Apr 13 2007 Funny. I just finished "Prefactoring" by Ken Pugh, and he seems to feel...
- David B. Held (51/88) Apr 14 2007 I agree that inheritance is generally overused, and even Bjarne has
- Chris Nicholson-Sauls (10/86) Apr 14 2007 Uhm... except that we have them already? Or is this not what you meant:
- David B. Held (4/14) Apr 14 2007 Hmm...that's pretty cool. I guess that is needed for Java
- Chris Nicholson-Sauls (8/24) Apr 15 2007 I assume that's why we got them. I really don't remember what justifica...
- Dan (2/4) Apr 15 2007 I don't, if one wanted everything to be class-oriented. An associative ...
- Daniel Keep (158/165) Apr 16 2007 OH but you CAN! It took me a while to work this out, and I must admit
- Dan (8/8) Apr 16 2007 Okay, so my summary so far:
- Lars Ivar Igesund (9/13) Apr 17 2007 I very much agree with this. See
- Dan (5/6) Apr 17 2007 Ooo.. nifty. A link!
Before I add this to the bug database I wanted to run this by everyone and see if I'm overlooking something. Classes in D are always a reference. Therefore the .sizeof and .alignof a class (reference) are always (void*).sizeof and (void*).alignof. D allows the class allocator (new) to be overloaded. The number of bytes required to hold the class (value) is passed as the first parameter to new(size_t size). This works well unless you are wanting to perform a placement new. When using placement new you pass in the storage for the object to be placed. new(size_t size, void* ptr) { return ptr; } The problem is at compile time you can NOT determine the size or alignment of a class (value), only the reference. Therefore you can not know the sizeof the buffer to preallocate to hold the class (value). I believe this to be an oversight in the language design. The alignment issue is easier to overcome, the ABI states the first field of a class (value) is the vbtbl pointer which will always mean the class (value) is (void*).alignof aligned. The .sizeof property for a class (value) is not available, here in lies the problem. Placement new is the easy example where the sizeof the class (value) is needed. Also consider the case of a blocks of class (values) being preallocated for a free list.
Apr 12 2007
Forest Ray wrote:Before I add this to the bug database I wanted to run this by everyone and see if I'm overlooking something. Classes in D are always a reference. Therefore the .sizeof and .alignof a class (reference) are always (void*).sizeof and (void*).alignof. D allows the class allocator (new) to be overloaded. The number of bytes required to hold the class (value) is passed as the first parameter to new(size_t size). This works well unless you are wanting to perform a placement new. When using placement new you pass in the storage for the object to be placed. new(size_t size, void* ptr) { return ptr; } The problem is at compile time you can NOT determine the size or alignment of a class (value), only the reference. Therefore you can not know the sizeof the buffer to preallocate to hold the class (value). I believe this to be an oversight in the language design. The alignment issue is easier to overcome, the ABI states the first field of a class (value) is the vbtbl pointer which will always mean the class (value) is (void*).alignof aligned. The .sizeof property for a class (value) is not available, here in lies the problem. Placement new is the easy example where the sizeof the class (value) is needed. Also consider the case of a blocks of class (values) being preallocated for a free list.Given: class Foo { ... } auto obj = new Foo; There is: obj.sizeof Which you know, and does as you say. But then there is: obj.classinfo.init.sizeof Which will render the actual size of class instances. :) Granted it isn't very pretty, but it works. What _would_ be nifty, would be if one could use 'Foo.sizeof' (invoke .sizeof on the type rather than the variable) to get the same value. Ie, make Class.sizeof an alias to Class.classinfo.init.sizeof -- I don't think this would be a problem. In the meantime, the .classinfo trick is your friend. -- Chris Nicholson-Sauls
Apr 12 2007
Which you know, and does as you say. But then there is: obj.classinfo.init.sizeof Which will render the actual size of class instances. :)no, it doesn't :)
Apr 12 2007
Frank Benoit (keinfarbton) wrote:obj.classinfo.init.length is documented as 'init.length gives size in bytes of class'.Which you know, and does as you say. But then there is: obj.classinfo.init.sizeof Which will render the actual size of class instances. :)no, it doesn't :)
Apr 12 2007
torhu schrieb:Frank Benoit (keinfarbton) wrote:well, i don't know about the size of the class, but it does not give the size of the class /instance/.obj.classinfo.init.length is documented as 'init.length gives size in bytes of class'.Which you know, and does as you say. But then there is: obj.classinfo.init.sizeof Which will render the actual size of class instances. :)no, it doesn't :)
Apr 12 2007
well, i don't know about the size of the class, but it does not give the size of the class /instance/.I was sure i had an example that shows it doesn't. But it seems I am wrong. Sorry about that. If i find it, I file a bug report. Frank
Apr 12 2007
Thanks for get me thinking along that path, the size of a class can be found by using CLASS.classinfo.init.length import std.stdio; class foo { int a = 1; int b = 2; int c = 3; } void main() { writefln("size = ", foo.classinfo.init.length); } ./xxx size = 20 Frank Benoit (keinfarbton) Wrote:well, i don't know about the size of the class, but it does not give the size of the class /instance/.I was sure i had an example that shows it doesn't. But it seems I am wrong. Sorry about that. If i find it, I file a bug report. Frank
Apr 12 2007
Finally i found my testcase... it does not work on linux. See http://d.puremagic.com/issues/show_bug.cgi?id=1141
Apr 13 2007
Frank Benoit (keinfarbton) wrote:Note to self: sleep|eat|veg first, post later. Ah well, at least the correct property got brought up eventually. I'll just go punish myself now (ie, go to bed). :) -- Chris Nicholson-SaulsWhich you know, and does as you say. But then there is: obj.classinfo.init.sizeof Which will render the actual size of class instances. :)no, it doesn't :)
Apr 12 2007
Forest Ray wrote:Before I add this to the bug database I wanted to run this by everyone and see if I'm overlooking something. Classes in D are always a reference. Therefore the .sizeof and .alignof a class (reference) are always (void*).sizeof and (void*).alignof. D allows the class allocator (new) to be overloaded. The number of bytes required to hold the class (value) is passed as the first parameter to new(size_t size). This works well unless you are wanting to perform a placement new. When using placement new you pass in the storage for the object to be placed. new(size_t size, void* ptr) { return ptr; } The problem is at compile time you can NOT determine the size or alignment of a class (value), only the reference. Therefore you can not know the sizeof the buffer to preallocate to hold the class (value). I believe this to be an oversight in the language design. The alignment issue is easier to overcome, the ABI states the first field of a class (value) is the vbtbl pointer which will always mean the class (value) is (void*).alignof aligned. The .sizeof property for a class (value) is not available, here in lies the problem. Placement new is the easy example where the sizeof the class (value) is needed. Also consider the case of a blocks of class (values) being preallocated for a free list.See http://d.puremagic.com/issues/show_bug.cgi?id=88 Sean
Apr 12 2007
I love D, one of the reasons being because Walter has provided unprecedented flexibility for structs; giving us almost all the features of classes without their drawbacks. structs have operator overloading and methods. : D structs now only lack constructors, destructors, inheritance, interfaces, and private members (encapsulation). I agree that constructors, destructors and interfaces are useful features... moving on; ~~ Inheritance: Inheritance is something I tend to disagree with because: if one examines a class inheriting from another, there is no indication of the presence of inherited properties or methods within it's declaration other than the ': superClass' at the top. Upon examining the superClass, you may then have to examine it's superClass and so forth; so finding out what members a class may have can take examining a dozen files. This is the intended modus operandi. I argue the better methodology is to implement interfaces, and architect the code such that few - if any - features are ever duplicated. If need be, implementing a template is also an option. Sure aristotle found that many things exhibit the same features and methods, I argue that redundancy is counter-productive to efficient algorithm execution; having no reflection on whether cats have fur and dogs do too. ~~ Encapsulation: Oddly, Java Programmers(tm) tend to think that encapsulating a property and providing a simple getter and setter for it is somehow a good thing. I argue that you're cluttering your NS with redundant information, and causing your code to jump into the getter and setter method every time you access a property without adding anything useful. In open source programming, the only reason I can find to encapsulate is to provide a clearly defined external interface to allow implementation changes without affecting the implemented interface; i.e: allowing programmers to see into the box might lead one to take advantage of it's bugs. Again, the usefulness of interfaces makes itself clear. ~~ Drawbacks of Classes: Classes lack transparency. You don't know the size, the location, the alignment... there is code and structure within them you aren't aware of, and much of it is often unneccassary. You cannot intelligently manipulate the implementation of a class even internally - such as iterating through an array of them and accessing a property simply by adding the sizeof to an iterator. You cannot pass a class by value, while a struct can be passed by value or reference. You cannot easily duplicate an Object instanciated from a class. You cannot declare an instanciated Object literal, but you can declare such a struct. These shortcomings I feel are sufficient to warrant the use of structs unless you are implementing an interface which other programmers will use in their own code (read: library), or getters/setters/ctor/dtor are critical to the legible implementation of something such that a good-old-fashioned method on the struct won't do. I'm looking forward to any replies. I want to learn any reasons why I might be wrong?
Apr 13 2007
Dan wrote:Inheritance: Inheritance is something I tend to disagree with...I argue the better methodology is to implement interfacesFunny. I just finished "Prefactoring" by Ken Pugh, and he seems to feel the same way. One reason seemed to be that it's easier to add or change interface compliance than it is to restructure an inheritance hierarchy. And for implementation sharing, it's often just as easy to abstract the common bits into support objects.Encapsulation: Oddly, Java Programmers(tm) tend to think that encapsulating a property and providing a simple getter and setter for it is somehow a good thing. I argue that you're cluttering your NS with redundant information, and causing your code to jump into the getter and setter method every time you access a property without adding anything useful.The argument for Java is that if everything is abstracted through get/set methods then there is a common point of analysis for debugging and it is painless to add additional functionality, change implementation, etc. Since D has property syntax however, the argument for starting out with everything hidden behind get/set methods is a bit weaker. If you have public data and later decide to hide it behind get/set methods, you can often do so without changing syntax from a user end. I don't think efficiency is an issue however. Get/set methods are almost always inlined, so there should be no performance penalty.Drawbacks of Classes: Classes lack transparency. You don't know the size, the location, the alignment... there is code and structure within them you aren't aware of, and much of it is often unneccassary. You cannot intelligently manipulate the implementation of a class even internally - such as iterating through an array of them and accessing a property simply by adding the sizeof to an iterator.I'm not sure it's really as bad as all that. Knowing class instance size at compile-time would be useful for some storage methods, but data order and such shouldn't be an issue. However, the .tupleof property implies that class data will typically be stored in declaration order anyway, since to do otherwise would complicate things unnecessarily.You cannot pass a class by value, while a struct can be passed by value or reference. You cannot easily duplicate an Object instanciated from a class. You cannot declare an instanciated Object literal, but you can declare such a struct.Personally, I think it's actually a good thing that classes can't be passed by value. It's a bit of a change from C++, but it dramatically simplifies some things that are difficult to impossible in C++. For example, one idea being discussed for multithreaded C++ 0x is to pass uncaught exceptions to the joining thread. Because exceptions are typically allocated on the stack and thrown via copying, this is not at all easy, but in D I was able to implement this in about five minutes.These shortcomings I feel are sufficient to warrant the use of structs unless you are implementing an interface which other programmers will use in their own code (read: library), or getters/setters/ctor/dtor are critical to the legible implementation of something such that a good-old-fashioned method on the struct won't do.Without copy semantics (which I'm not sure structs should have), the use of structs is somewhat limited in D. For the most part, I think they really are best as aggregates. But this difference between classes and structs is good justification for both to exist in the language. Sean
Apr 13 2007
Sean Kelly wrote:Dan wrote:I agree that inheritance is generally overused, and even Bjarne has lamented this fact. He originally designed abstract base classes as a way to implement interfaces in C++ with the intention that most inheritance would be of such ABCs, but was quite dismayed when people mostly ignored the mechanism and proceeded to derive every class in sight. He might as well have thrown in std::Object. Thus, interfaces should definitely be preferred where possible. That being said, many idioms and design patterns are not possible without outright inheritance, like CRTP and Policy-Based Design. There is a rightful place for both.[...] Inheritance is something I tend to disagree with... I argue the better methodology is to implement interfacesFunny. I just finished "Prefactoring" by Ken Pugh, and he seems to feel the same way. One reason seemed to be that it's easier to add or change interface compliance than it is to restructure an inheritance hierarchy. And for implementation sharing, it's often just as easy to abstract the common bits into support objects.The problem with Java-style "encapsulation" is not that it's redundant, but that it's not encapsulation. The presence of an explicit setter is almost always an indication of a design flaw. The exception to this principle are frameworks that are heavily and explicitly stateful, such as GUIs. In this case, I think setters are just fine, but you will often find that they are more than a trivial assignment, also. In good encapsulation, accessors give you readonly visibility, while mutators are carefully constructed to only provide the types of state change that are necessary for the object, rather than the arbitrary and random mutation that explicit setters allow. This is primarily because mutators need to preserve class invariants, which is either harder or less efficient to do with arbitrary setters.Encapsulation: [...]Classes are supposed to lack transparency. That's the point of abstraction. ;) The benefit of classes is runtime dispatch. If you are willing to pay for that, you are usually not concerned with the alignment and other low-level details. Accessing a class by directly addressing its internals is a fairly unsound thing to do. Allowing users to do that would make it pointless to have access modifiers. If you really need to do something like that, you should be able to use a disassembly to see how the class is laid out. I think that's a perfectly reasonable requirement for doing something as non-portable and intrusive as that.Drawbacks of Classes: Classes lack transparency. You don't know the size, the location, the alignment... there is code and structure within them you aren't aware of, and much of it is often unneccassary. You cannot intelligently manipulate the implementation of a class even internally - such as iterating through an array of them and accessing a property simply by adding the sizeof to an iterator.[...]The benefit of passing entities by value is efficiency, because copying the value is relatively cheap. However, classes are already bigger than structs, and most classes of interesting size would be fairly expensive to copy around as values. Cloning an object is not something that everyone wants to do, but implementing it is fairly straightforward. I'm not seeing the big drawback here. Struct literals make sense because they are intended to be used as value types. Classes are not intended to be used as value types, so there is a much less compelling argument for allowing Class literals.You cannot pass a class by value, while a struct can be passed by value or reference. You cannot easily duplicate an Object instanciated from a class. You cannot declare an instanciated Object literal, but you can declare such a struct.[...]I think structs should have copy semantics, personally; but that's another story. I think a good design practice is to use value types (immutable structs) wherever possible and free functions. After all, this is the essence of functional programming (or part of it, anyway), which has many benefits to recommend it. On the other hand, this doesn't work so well with highly mutable systems like GUIs and DBs, which tend to be the workhorses of industry and probably comprise a fair portion of D's market segment. DaveThese shortcomings I feel are sufficient to warrant the use of structs unless you are implementing an interface which other programmers will use in their own code (read: library), or getters/setters/ctor/dtor are critical to the legible implementation of something such that a good-old-fashioned method on the struct won't do.Without copy semantics (which I'm not sure structs should have), the use of structs is somewhat limited in D. For the most part, I think they really are best as aggregates. But this difference between classes and structs is good justification for both to exist in the language.
Apr 14 2007
David B. Held wrote:Sean Kelly wrote:Uhm... except that we have them already? Or is this not what you meant: -- Chris Nicholson-SaulsDan wrote:I agree that inheritance is generally overused, and even Bjarne has lamented this fact. He originally designed abstract base classes as a way to implement interfaces in C++ with the intention that most inheritance would be of such ABCs, but was quite dismayed when people mostly ignored the mechanism and proceeded to derive every class in sight. He might as well have thrown in std::Object. Thus, interfaces should definitely be preferred where possible. That being said, many idioms and design patterns are not possible without outright inheritance, like CRTP and Policy-Based Design. There is a rightful place for both.[...] Inheritance is something I tend to disagree with... I argue the better methodology is to implement interfacesFunny. I just finished "Prefactoring" by Ken Pugh, and he seems to feel the same way. One reason seemed to be that it's easier to add or change interface compliance than it is to restructure an inheritance hierarchy. And for implementation sharing, it's often just as easy to abstract the common bits into support objects.The problem with Java-style "encapsulation" is not that it's redundant, but that it's not encapsulation. The presence of an explicit setter is almost always an indication of a design flaw. The exception to this principle are frameworks that are heavily and explicitly stateful, such as GUIs. In this case, I think setters are just fine, but you will often find that they are more than a trivial assignment, also. In good encapsulation, accessors give you readonly visibility, while mutators are carefully constructed to only provide the types of state change that are necessary for the object, rather than the arbitrary and random mutation that explicit setters allow. This is primarily because mutators need to preserve class invariants, which is either harder or less efficient to do with arbitrary setters.Encapsulation: [...]Classes are supposed to lack transparency. That's the point of abstraction. ;) The benefit of classes is runtime dispatch. If you are willing to pay for that, you are usually not concerned with the alignment and other low-level details. Accessing a class by directly addressing its internals is a fairly unsound thing to do. Allowing users to do that would make it pointless to have access modifiers. If you really need to do something like that, you should be able to use a disassembly to see how the class is laid out. I think that's a perfectly reasonable requirement for doing something as non-portable and intrusive as that.Drawbacks of Classes: Classes lack transparency. You don't know the size, the location, the alignment... there is code and structure within them you aren't aware of, and much of it is often unneccassary. You cannot intelligently manipulate the implementation of a class even internally - such as iterating through an array of them and accessing a property simply by adding the sizeof to an iterator.[...]The benefit of passing entities by value is efficiency, because copying the value is relatively cheap. However, classes are already bigger than structs, and most classes of interesting size would be fairly expensive to copy around as values. Cloning an object is not something that everyone wants to do, but implementing it is fairly straightforward. I'm not seeing the big drawback here. Struct literals make sense because they are intended to be used as value types. Classes are not intended to be used as value types, so there is a much less compelling argument for allowing Class literals.You cannot pass a class by value, while a struct can be passed by value or reference. You cannot easily duplicate an Object instanciated from a class. You cannot declare an instanciated Object literal, but you can declare such a struct.[...]
Apr 14 2007
Chris Nicholson-Sauls wrote:[...] Uhm... except that we have them already? Or is this not what you meant:Hmm...that's pretty cool. I guess that is needed for Java compatibility, huh? Dave
Apr 14 2007
David B. Held wrote:Chris Nicholson-Sauls wrote:I assume that's why we got them. I really don't remember what justification Walter gave for them at the time, but it was probably a requested thing. Although honestly, the one thing I used this often for in Java was event handlers... and in D we have the oh-so-beautiful delegates to do that sort of thing. Plus the three or so Signals/Slots implementations floating around, which are also beautiful. So I have trouble thinking of any really compelling use for anonymous objects. -- Chris Nicholson-Sauls[...] Uhm... except that we have them already? Or is this not what you meant:Hmm...that's pretty cool. I guess that is needed for Java compatibility, huh? Dave
Apr 15 2007
Chris Nicholson-Sauls Wrote:implementations floating around, which are also beautiful. So I have trouble thinking of any really compelling use for anonymous objects.I don't, if one wanted everything to be class-oriented. An associative array of Objects implementing the same interface differently, for example...
Apr 15 2007
Forest Ray wrote:Before I add this to the bug database I wanted to run this by everyone and see if I'm overlooking something. Classes in D are always a reference. Therefore the .sizeof and .alignof a class (reference) are always (void*).sizeof and (void*).alignof. D allows the class allocator (new) to be overloaded. The number of bytes required to hold the class (value) is passed as the first parameter to new(size_t size). This works well unless you are wanting to perform a placement new. When using placement new you pass in the storage for the object to be placed. new(size_t size, void* ptr) { return ptr; } The problem is at compile time you can NOT determine the size or alignment of a class (value), only the reference. Therefore you can not know the sizeof the buffer to preallocate to hold the class (value). I believe this to be an oversight in the language design. The alignment issue is easier to overcome, the ABI states the first field of a class (value) is the vbtbl pointer which will always mean the class (value) is (void*).alignof aligned. The .sizeof property for a class (value) is not available, here in lies the problem. Placement new is the easy example where the sizeof the class (value) is needed. Also consider the case of a blocks of class (values) being preallocated for a free list.OH but you CAN! It took me a while to work this out, and I must admit that I have *not* tested the code in some time. That said, it should still work. In a nutshell, here's how it works: given a class type, you can deduce the size of an instance at compile time by finding the maximum of (offset+size) for each member variable of the class. If the class has no members, then use 2*(void*).sizeof, to account for the ClassInfo and vtbl pointers. You also need to add in some padding for any additional interfaces. Finally, you take the maximum of that and the size of the super class (if any). It's messy, and it was largely arrived at by "define a whole bunch of classes and fudge it until it's right", but I've used it in two custom allocators and never had a problem. FYI, I release the below code into the public domain: share and enjoy! -- Daniel ----- module etc.mem.util; private struct Align { ubyte a; void* b; } private const PTR_ALIGN = Align.tupleof[1].alignof; version( X86 ) const MEM_ALIGN = 8u; else static assert(false, "Unknown memory alignment for this platform."); private template AlignPad(size_t base, size_t aligned) { static if( aligned == 0 ) const AlignPad = base; else const AlignPad = ((base+PTR_ALIGN-1)/PTR_ALIGN)*PTR_ALIGN + aligned; } template InstanceSize(T) { static if( is( T == Object ) ) const InstanceSize = 2*(void*).sizeof; else const InstanceSize = Max!( AlignPad!( InstanceSize!(Super!(T)), InterfaceCount!(T)*(void*).sizeof), AlignPad!( InstanceSizeImpl!(T, 0), + InterfaceCount!(T)*(void*).sizeof)); } private template Super(T) { static if( is( T S == super ) ) alias First!(S) Super; else static assert(false, "Can't get super of "~T.mangleof); } private template First(T) { alias T First; } private template First(T, Ts...) { alias T First; } private template InstanceSizeImpl(T, size_t i) { static if( i < T.tupleof.length ) const InstanceSizeImpl = Max!( T.tupleof[i].offsetof + T.tupleof[i].sizeof, InstanceSizeImpl!(T, i+1)); else // This is necessary to account for classes without member // variables. const InstanceSizeImpl = 2*(void*).sizeof; } private template Max(size_t a, size_t b) { static if( a > b ) const Max = a; else const Max = b; } template InstanceSizeAligned(T, size_t alignment=MEM_ALIGN) { static if( alignment == 0 ) const InstanceSizeAligned = InstanceSize!(T); else const uint InstanceSizeAligned = InstanceSizeAlignImpl!(T, alignment).result; } private template InstanceSizeAlignedImpl(T, size_t alignment) { private const base_size = InstanceSize!(T); const result = ((base_size+alignment-1)/alignment)*alignment; } private template InterfaceCount(T) { static if( is( T == Object ) ) const InterfaceCount = 0u; else static if( is( T S == super ) ) const InterfaceCount = InterfaceCountImpl!(S); } private template InterfaceCountImpl(TBase, TInterfaces...) { const InterfaceCountImpl = TInterfaces.length; } version( etc_mem_util_main ) { import std.stdio; interface I1 { } interface I2 { } interface I3 : I2 { } class A { } class B : A, I1 { } class C : B { ubyte x; real y; } class D : C, I3 { } class E : D, I3 { } template SuperTuple(T) { static if( is( T S == super ) ) alias S SuperTuple; } void main() { writefln("A: %s; %d, %d", typeid(SuperTuple!(A)), A.classinfo.init.length, InstanceSize!(A)); writefln("B: %s; %d, %d", typeid(SuperTuple!(B)), B.classinfo.init.length, InstanceSize!(B)); writefln("C: %s; %d, %d", typeid(SuperTuple!(C)), C.classinfo.init.length, InstanceSize!(C)); writefln("D: %s; %d, %d", typeid(SuperTuple!(D)), D.classinfo.init.length, InstanceSize!(D)); writefln("E: %s; %d, %d", typeid(SuperTuple!(E)), E.classinfo.init.length, InstanceSize!(E)); writefln("InterfaceCount!(E) == %d", InterfaceCount!(E)); writefln("ptr alignment: %d", Align.tupleof[1].alignof); } } -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 16 2007
Okay, so my summary so far: - having the ability to define a getter/setter using the same syntax as a property means defining simple getter/setter methods is pointless. - having simple getter/setters is loss-less as it's inlined anyways; it's just messy source. - at least many of us agree that interfaces and refactoring trump inheritance. - it would be cool if structs could be made to conform to interfaces. - it would be cool if getting the sizeof and alignof a class was easier. - encapsulation is useful only because it prevents people from lazily circumventing interfaces. Is it possible for a module to make everything private except the interfaces? (enforcement by denying access to the symbols at compile time?) - there is no longer a benefit to having the code and data local to one another on the modern x86 platform because code and data have separate dedicated cache regions.
Apr 16 2007
Dan wrote:- at least many of us agree that interfaces and refactoring trump inheritance.It's often a good solution, but far from always.- it would be cool if structs could be made to conform to interfaces.I very much agree with this. See http://d.puremagic.com/issues/show_bug.cgi?id=1023 -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Apr 17 2007
Lars Ivar Igesund Wrote:http://d.puremagic.com/issues/show_bug.cgi?id=1023Ooo.. nifty. A link! If indeed we enumerated the properties in the same way that we enumerated variadic arguments in a function, then we could very reasonably write our own interface checking for structs, and someone could release a template that performed checking quite readily; with debug{} else{} thrown into the template, it could do very well indeed! Sincerely, Dan
Apr 17 2007