Re: What is put() useful for with regards to dynamic arrays?
On Sat, 30 Apr 2011 00:09:09 -0400, Andrej Mitrovic wrote: > import std.range; > > void main() > { > int[] a = [1, 2, 3]; > > a.put(6); > assert(a == [2, 3]); > > a.put([1, 2]); > assert(a.length == 0); > } > > Seems kind of odd.. put is implemented as an append method for some > custom types, e.g. std.array.appender. But for arrays put just removes > Item or RangeLength number of elements from the array. What's the use > case for this? This should probably be in a FAQ somewhere. :) http://www.digitalmars.com/d/archives/digitalmars/D/ std.array.put_doesn_t_put_106871.html -Lars
Re: Matrix creation quiz
I was away. Don: > That would not fix this problem. You're doing arithmetic on unsigned > values, where overflow doesn't happen. My enhancement request about integral overflows asks for two compiler switches: one that turns signed integral overflows (at compile time or run time) into errors, and one switch that turns both signed and unsigned overflows into errors. If you use the second switch you have overflows on unsigned values too. > -- which compiles happily on 32 bits, but won't compile on a 64 bit > system. I think it should be rejected on all systems. I agree. I think code that doesn't work on 64 bit systems has to not work on 32 bit ones too. Bye, bearophile
Re: "not an lvalue"
On Sun, 01 May 2011 09:30:34 -0400, CrypticMetaphor wrote: Hi, I've been away from D for a while, but now I'm back and I'm stuck with an compile time error. I've got a Matrix33 class and a Vector3 class, but something is wrong with the way I return my Vector3 in my matrix class: If I do this I get an error: Matrix33 mtest = new Matrix33(); mtest.SetIdentity(); Vector3 test1 = new Vector3(0, 0, 0); Vector3 test2 = test + mtest.GetColumn(2); I get the error "Error: mtest.GetColumn(x) is not an lvalue" But the following works: Matrix33 mtest = new Matrix33(); mtest.SetIdentity(); Vector3 test1 = new Vector3(0, 0, 0); Vector3 temp = mtest.GetColumn(2); Vector3 test2 = test + temp; // GetColumn method Matrix33 { // ... /// Get a matrix column, horizontal line Vector3 GetColumn(uint index) { assert(!(index > 2), "index is too high"); return new Vector3(cell[index * 3], cell[index * 3 + 1], cell[index * 3 + 2]); } // ... } My questions: What changes do I have to make to make the first example compile? I think others have said you need to not use ref. The solution (which is not yet properly implemented) is to use auto ref. The way it is supposed to work is like this: void foo(T t); // t is passed by value (copied). t can be an lvalue or an rvalue void foo(ref T t); // t is passed by reference. t can only be an lvalue void foo(auto ref T t); // t is passed by reference. t can be an lvalue or an rvalue. Essentially, with auto-ref you are saying, I know there are dangers in passing rvalues here, but I still want to accept an rvalue by reference. There was confusion on Walter's part as to how this was supposed to work, so auto ref currently doesn't act this way. There are two workarounds I know of: 1. as you have done, convert the rvalue to an lvalue by assigning to a temporary 2. call the method on the rvalue. For some reason (probably to make people not go insane) you are allowed to pass an rvalue by ref if you are calling a method on it. i.e. this should work (don't remember vectors much, but I believe addition is commutative?): Vector3 test2 = mtest.GetColumn(2) + test; If you can't do the second method, I think method 1 is your only option. -Steve
Re: What is put() useful for with regards to dynamic arrays?
Thanks, that post explained it. Obviously I wasn't the first and likely won't be the last person to run into this. Maybe put's documentation could make a note of this.
Re: opDollar()
Dmitry Olshansky wrote: On 26.03.2011 11:03, Caligo wrote: "In the expression a[, ...,], if $ occurs in, it is rewritten as a.opDollar!(i)()." -- TDPL, pg 380 Is that correct? if so, could some one give an example code? I don't understand the need for the parameter. Also, what is the signature for opDollar() in a struct. I'm getting errors trying to implement this. That parameter means number of dimension. When implementing some kind of multidimensional array (e.g. an 2D raster Image) you'd have: img[$-1, $-1] = lastValue; // the first dollar should resolve to "width", the second to "height" Now speaking of it's implementation - it's quite broken. It's not broken -- it's not implemented at all! The relevant bug report is http://d.puremagic.com/issues/show_bug.cgi?id=3474 (vote up!) Still it's not considered to be a critical one, since you can workaround it by: img[img.width-1,img.height-1] = lastValue;
Re: expression templates
Mr enuhtac wrote: Hello everyone, I'm new to D and this list (although I've had a look onto D a few years ago). I hope you guys can help me with my questions. At the moment I'm trying to implement some expression template stuff. My first goal is to encode an expression into a type representing that expression without any additional functionality (like the possibility to evaluate that expression). Actually this is very simple and short in D. This is my approach: struct OpBinary( string Op, R1, R2 ) { alias typeof( mixin( "R1.EvalT.init" ~ Op ~ "R2.EvalT.init" ) ) EvalT; enum string Operator = Op; }; struct Constant( T, T v ) { alias T EvalT; enum T value = v; }; struct Expr( R ) { auto opBinary( string Op, R2 )( Expr!R2 ) { return Expr!( OpBinary!( Op, R, R2 ) )(); } auto opBinary( string Op, T )( T v ) if( isNumeric!T ) { return Expr!( OpBinary!( Op, R, Constant!( T, v ) ) )(); } auto opBinaryRight( string Op, T )( T v ) if( isNumeric!T ) { return Expr!( OpBinary!( Op, Constant!( T, v ), R ) )(); } }; But I cannot figure out how to implement expression templates for comparison operators, which is crucial for my purpose. The opCmp function is great for implementing comparison functionality, but when building an expression template tree the information on the actual comparison operator is needed. opCmp just knows that a comparison is going on, the actual type of comparison is unknown. What I would like to have is something like this: auto opCmp( string Op, R2 )( Expr!R2 ) { return Expr!( OpBinary!( Op, R, R2 ) )(); } So opCmp knows about the actual operator and would just use my OpBinary struct to encode it. But this is not possible. The only workaround for I this problem I can imagine is using my own comparison functions instead of the comparison operators: op!"<"( a, b ) instead of a < b. Another possibility would be to call opBinary explicitly: a.opCmp!"<"( b ) In this case I would not even have to write additional code. But these workarounds are ugly, if would greatly prefer the normal comparison operators. Does anyone has an idea how to use them? Regards, enuhtac In the present language I don't think it's possible to do expression templates involving opCmp or opEquals, since you have no control over the return type. One other solution I did: I had some code where the result of the expression template was used in a mixin, so I moved the mixin outside the expression. Then I changed all the >, <, == into something else before converting it into an expression template. But this is ugly as well.
Difference between stack-allocated class and struct
What are the differences between class instantiated by scope and struct itself? Two, that comes to my mind are: - vtable existance (yep, struct with inheritation - that's what i like) - lol, i just forgot while writing this e-mail :) Sincerely, Mariusz Gliwiński
Re: Difference between stack-allocated class and struct
> What are the differences between class instantiated by scope and struct > itself? > Two, that comes to my mind are: > - vtable existance (yep, struct with inheritation - that's what i like) > - lol, i just forgot while writing this e-mail First off, I would point out that scoped classes are going away (though std.typecons.scoped serves as a replacement). Now, structs are value types and are meant to be on the stack. When you assign one to another, a copy is made. If the original is altered, it doesn't affect the copy, and if the original goes away, the copy is unaffected. Classes are reference types and are meant to be on the heap. When you assign one to another, you're merely copying the reference. Both refer to the same object. No copy is made. So, when you alter one, you also alter the other. When one goes away, it doesn't affect the other, but if the underlying object went away, then they would both be screwed. Normally, class objects don't go away until the garbage collector collects them, but if you use scope (or std.typecons.scoped), then the object is on the stack instead of the heap, and as soon as that scope goes away, so does the object, so if you have references to it elsewhere, they're invalid, but the program won't know that, and it'll try and use them anyway. It can lead to serious bugs. Scoped classes are inherently unsafe, which is why they're going away. It's like when you return an address to a local variable: int* foo() { int a = 7; return &a; } The pointer will be invalid, and you're going to have bugs. Now, the compiler's going to catch such a simple case as this, but what if you did something like this? int* foo() { int a = 7; return bar(&a); } int* bar(int* b) { return b; } The compiler can't catch that. The same goes if you were to use a scoped class instead of an int. In general, scoped classes are a _bad_ idea and should not be used unless profiling has shown that they speed up critical code and you're _certain_ that you're using them in a manner which won't cause a reference to the class to escape the function and outlive the function call. As for everything else structs are structs and classes are classes. All of the normal differences apply. That includes the fact that structs have no inheritance and no vtable while classes do have inheritance and do have a vtable. However, you pretty much lose polymorphism if you use a scoped class. You're guaranteeing that the class that you're using is _exactly_ that type and not a subclass of that type. This is because the object is put on the stack inside the function and the compiler must know its _exact_ size. It's exactly like what you get with classes on the stack in C++. Putting them on the stack loses any of the advantages of polymorhism and risks slicing ( http://en.wikipedia.org/wiki/Object_slicing ) when you assign a subclass object to a base class object. So, if you're using a scoped class, you're _not_ getting the benefits of polymorphism. What you're doing is saying that you know that you have an object of a particular type - that _exact_ type - which you know is not going to need to exist once you exit that scope, and you want to increase the efficiency of that code, so you make it so that the object is created on the stack instead of the heap. And in so doing, you _must_ make sure that no reference to that object escapes - which often isn't easy if you have to pass that object to any other functions, and even if you verify that it's safe now, it might not be later. Structs and classes are inherently different. Structs are value types and classes are reference types. All you're doing with a scoped class is forcing the object to be put on the stack instead of the heap, which doesn't really change anything for the class except for the fact that it must be of that _exact_ type (so no polymorphism), and you have to make sure that no references to it escape, or you could have serious bugs. - Jonathan M Davis
Re: Difference between stack-allocated class and struct
Firstly, thanks for comprehensive answer and I'd like to excuse for my stupid mistakes, which are caused by learning a lot and not actually programming. On date 2011-05-02 23:03, Jonathan M Davis wrote: Classes are reference types and are meant to be on the heap. Yeah, value vs reference semantics - that was the thing i forgot... So, if you're using a scoped class, you're _not_ getting the benefits of polymorphism. I completely didn't think about, that stack size needs to be known already at time of compiling. You just probably saved me a lot of problems. So, scoped classes can't be used for filling gap in struct inheritance. I'll clarify myself: All i would need is extending - without polymorphism. Containment, can be solution for fields which doesn't annoys so much (although image in auto-generated documentation, just like it's with subclassing, would be nice). Unfortunately, the worse case is about methods, which have to be manually forwarded to contained struct. So, does someone sees any nice solution for method forwarding as described? Should i make use of some mixin's? Thanks, Mariusz Gliwiński
Re: Difference between stack-allocated class and struct
> Firstly, thanks for comprehensive answer and I'd like to excuse for my > stupid mistakes, which are caused by learning a lot and not actually > programming. > > On date 2011-05-02 23:03, Jonathan M Davis wrote: > > Classes are reference types and are meant to be on the heap. > > Yeah, value vs reference semantics - that was the thing i forgot... > > > So, if you're using a scoped class, you're _not_ getting the benefits of > > polymorphism. > > I completely didn't think about, that stack size needs to be known > already at time of compiling. You just probably saved me a lot of problems. > > > So, scoped classes can't be used for filling gap in struct inheritance. > > I'll clarify myself: > All i would need is extending - without polymorphism. > Containment, can be solution for fields which doesn't annoys so much > (although image in auto-generated documentation, just like it's with > subclassing, would be nice). > Unfortunately, the worse case is about methods, which have to be > manually forwarded to contained struct. > > So, does someone sees any nice solution for method forwarding as > described? Should i make use of some mixin's? alias this is supposed to be one of the better solutions for dealing with the sort of problem that you're looking at. Unfortunately, it's highly buggy at the moment, so it's questionable as to whether it would work. And even if it works, you can currently only have one alias this per type, so if you need more than that, you'd need another solution (eventually, alias this should work just fine, and you should be able to have multiple of them per type, but not yet). At the moment, you pretty much need to do manual forwarding. Now, with the clever use of compile-time reflection via __traits and/or std.traits along with template mixins or string mixins, you should be able to get the compiler to generate all of the forwarded functions for you, but you'd still have to write the code for generating the mixins, which could be somewhat tricky. If you get it right though, then it would generate all of the appropriate functions regardless of whether any are added to or removed from the type that you're forwarding function calls to. - Jonathan M Davis
Re: Difference between stack-allocated class and struct
Mariusz Gliwiński wrote: I'll clarify myself: All i would need is extending - without polymorphism. Containment, can be solution for fields which doesn't annoys so much (although image in auto-generated documentation, just like it's with subclassing, would be nice). Unfortunately, the worse case is about methods, which have to be manually forwarded to contained struct. So, does someone sees any nice solution for method forwarding as described? Should i make use of some mixin's? You can use 'alias this': http://www.digitalmars.com/d/2.0/class.html#AliasThis
Re: Difference between stack-allocated class and struct
Here is my prototype COM compile-time reflection based wrapper mixin (which I have abandoned in favor of alias this since it covers 95% of my use cases even though it isn't perfectly safe). I am new at D so you have been warned, though this part of the language seems pretty straightforward enough. It is possible the track down the argument names but takes some rather intricate parsing to do correctly (and the example someone linked me in another thread of mine chocked on const types due to parsing bugs). http://snipt.org/xsu The wrapped interface also needs to be a mixin so it can be created in the correct module, with visibility to all the types passed to the interface's methods. So something like the following is going to fail miserably unless ComPtr is also made into a mixin and instantiated in the correct module. struct ComPtr(T) { public: T m_Pointer; mixin(WrapComInterface!(T)("m_Pointer") };