Re: meaning of "auto ref const"?
On Tuesday, 20 December 2016 at 20:08:32 UTC, Ali Çehreli wrote: If the purpose is optimization, the good news are Yes it is :) * Classes are already reference types so there is no lvalue or rvalue reference distinction there Ok, this one is quite intuitive. import std.stdio; ... Thank you for the illustrative example, I have reproduced it. There is a surprising difference in D: In D, non-constness of an object seems to be more important in overload resolution: Notice how mutable lvalue above is passed to by-copy instead of the potentially-more-optimal by-const-ref above. D realizes that a mutable object is for mutation and because by-const-ref cannot mutate it, D passes it to the by-copy function. (This may be seen as a bug by some.) Thank you for pointing out this. I was not aware of that, and for sure this is not the C++ behavior. Interestingly, enabling the by-mutable-ref overload above, now the mutable object goes to by-ref and there is no automatic copy: Ok, that is "moral" and without surprise. --- rvalue --- constructor 1 foo(by-copy) 1 destructor for1 --- mutable lvalue --- constructor 2 foo(by-ref) 2 destructor for2 --- const lvalue --- constructor 3 foo(by-ref-const) 3 destructor for3 Ali [1] I have an issue with "rvalue reference" as rvalue references can be references to lvalues as well. :p Thank you for your time and these valuable explanations, I learnt a lot. --Vincent
Re: meaning of "auto ref const"?
On Tuesday, 20 December 2016 at 19:24:32 UTC, Ali Çehreli wrote: As a general rule, 'auto ref' should probably be const. If the purpose of 'ref' is so that the argument would be mutated, then allowing a copy of an rvalue to this function could very well be a bug: struct S { int i; } void foo()(auto ref S s) { s.i = 42; // <-- Cannot be observed if the arg is rvalue } void main() { foo(S(1)); } Thank you Ali! This is effectively a trap I had not realized, you probably save me from some long debugging time.
Re: meaning of "auto ref const"?
On Sunday, 18 December 2016 at 14:32:08 UTC, kinke wrote: TypeInfo_Struct apparently requires (or used to require) an `int opCmp(ref const T rhs)` overload, i.e., a version taking the rhs lvalue argument by reference (see https://dlang.org/spec/operatoroverloading.html#compare). Note that there are other overloads afterwards which take the rhs argument by value, thereby allowing rhs rvalues too. Thank you for your complementary answer and explanation. All these look less strange to me now.
Re: meaning of "auto ref const"?
On Sunday, 18 December 2016 at 14:25:04 UTC, Basile B. wrote: ... As you can see, auto ref is more flexible with the parameter. This make sense for templated functions. Thank you for your detailed answer, things are perfectly clear now. Also sorry for the doc linksI should have found it before asking my question.
meaning of "auto ref const"?
Reading std/bigint.d code: https://github.com/dlang/phobos/blob/00c1cc3b0d354363793c8b419ce84da722578138/std/bigint.d#L589 I have seen this: bool opEquals()(auto ref const BigInt y) const pure @nogc { return sign == y.sign && y.data == data; } my problem is that I do not understand the role/meaning of "auto" in this context. Moreover in the opCmp code, "auto" is not present anymore, which is an extra source of confusions for me. int opCmp(ref const BigInt y) pure nothrow @nogc const { // Simply redirect to the "real" opCmp implementation. return this.opCmp!BigInt(y); } What is the rational? - Another interrogation for me, who come from C++, is how to translate into D: template void foo(T&& t);
Re: [Semi-OT] I don't want to leave this language!
On Wednesday, 7 December 2016 at 16:15:32 UTC, Chris wrote: I don't understand this discussion at all. Why not have both? I don't need bare metal stuff at the moment but I might one day, and I perfectly understand that people may need it. At the same time, there are people who are happy with runtime/Phobos/GC. In my opinion it's not a question of "either or" but of "both and". Yes, I do agree, that is not exclusive. I only said that IMHO it would be very useful to have a clear "mechanism" (pragma, compiler flags...) to generate code close to what can be done with C. The goal being to have appealing (= fast & low memory footprint) libraries to attract people. That said, D with all its features GC, ... is great, but maybe that is not the feature that catches potential user attention the most. -- Vincent
Re: [Semi-OT] I don't want to leave this language!
On Wednesday, 7 December 2016 at 11:48:32 UTC, bachmeier wrote: I write D code all the time for my research. I want to write correct code quickly. My time is too valuable to spend weeks writing code to cut the running time by a few minutes. That might be fun for some people, but it doesn't pay the bills. It's close enough to optimized C performance out of the box. But ultimately I need a tool that provides fast code, has libraries to do what I want, and allows me to write a correct program with a limited budget. This is, of course, not universal, but zero overhead is not important for most of the numerical code that is written. I understand and I do agree with these points, honestly. These points are also the reason why I will maybe try to use D for my own codes (D is really much better than C++ concerning template, meta programming syntax, embedded unit tests etc...). However I think that to popularize/attract people to use D, it is very important, to have a mechanism/feature that allows you to be close to the "zero overhead" situation. If you have two concurrent libraries (even in different languages), people will adopt the fastest one... As an example, look at the BLAS lib, people do not try to read/understand the code to see how nice it is, they just look at benchmarks and take the fastest implementation for their architecture. IMHO that is the reason why D must let the opportunity, for those who want (library developers for instance) of coding down to the metal: the goal is to have visibility in benchmarks and to attract users. At least it is my point of view. -- Vincent
Re: [Semi-OT] I don't want to leave this language!
On Tuesday, 6 December 2016 at 17:00:35 UTC, Jonathan M Davis wrote: So, while there are certainly folks who would prefer using D as a better C without druntime or Phobos, I think that you're seriously overestimating how many folks would be interested in that. Certainly, all of the C++ programmers that I've worked with professionally would have _zero_ interest in D as a better C. - Jonathan M Davis Considering scientific/numerical applications, I do agree with Ilya: it is mandatory to have zero overhead and a straightforward/direct interoperability with C. I am impressed by the Mir lib results and I think "BetterC" is very attractive/important. -- Vincent
Re: fPIC Error
On Thursday, 3 November 2016 at 05:16:11 UTC, Dlang User wrote: I am running Debian Testing and I think I have run into the recent fPIC issue. This is the source code for the test project I am using: import std.stdio; void main() { writeln("Edit source/app.d to start your project."); readln(); } When I try to compile a project, I get the following errors (truncated for brevity): /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libphobos2.a(thread_26c_155.o): relocation R_X86_64_32 against symbol `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Nonrepresentable section on output collect2: error: ld returned 1 exit status dmd failed with exit code 1. Exit code 2 Build complete -- 1 error, 0 warnings I got the same problem, still under Debian. A fix is to use these flags: dmd -shared -m64 -fPIC -defaultlib=libphobos2.so app.d You can also use another compiler: dub --compiler=ldc2 or rdmd --compiler=ldc2 Note that it is not recommended to use gdc because it is not up to date, use dmd or ldc2. Also note, that if you use Emacs + Org Mode, http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-C.html you will encounter the same problem. A fix is to add the following line in your .emacs file: (setq org-babel-D-compiler "rdmd --compiler=ldc2") Vincent
A curated list of links related to D (github/awesome D)
Maybe interesting (hoping it is not too redundant with the links here) https://github.com/zhaopuming/awesome-d Vincent
Re: static array internal & dangling reference
On Monday, 14 November 2016 at 17:15:43 UTC, Steven Schveighoffer wrote: What has happened is that the stack allocated for f() (and since released) is still referenced by sb[]. In a weird way, since you haven't called any other functions, that data is still "valid"! Thank you for the clarification. I am convinced, I think this is the "true" reason why Valgrind does not react. I'm not sure what valgrind uses to determine what data is uninitialized or allocated, but in a very real sense, this code is deterministic, and will always result in the same result. Is it good practice? No. It's very fragile, and would break as soon as you called another function or reallocated that stack space (as your second example shows). I understand you, and for sure this is not a good practice. I think it is time for me to ruminate on something else... Thank you - Vincent
Re: static array internal & dangling reference
On Monday, 14 November 2016 at 06:10:38 UTC, Jonathan M Davis wrote: I would have hoped that it would have complained about the first one. I don't know why it isn't. It definitely results in having a pointer to memory that should no longer be referenced. Yes I would have hoped too, because it has the unfortunate consequence that we can not rely 100% that there is no dangling pointer even if valgrind said OK. Regardless, there's no question that returning a dynamic array which is a slice of a static array is not something that is valid to do when that static array is a local variable. Valgrind just isn't managing to catch it in this case, unfortunately. I do agree, this is not a construct to use, I only have done this for testing purpose to see how D reacts. Vincent
Re: static array internal & dangling reference
On Sunday, 13 November 2016 at 23:39:37 UTC, Steven Schveighoffer wrote: Note that he is declaring an int[10] inside the function and then returning it. The compiler must see that the int[10] will be returned, and so it reuses the pre-allocated buffer for returning as the same address to avoid copying. I would guess it's probably fine, with no dangling reference. Thank you for your comment. On my side there is still something mysterious. I one case: int[] f() { int[10] sa; foreach(int i, ref sa_i;sa){ sa_i=i; } int[] sb=sa; return sb; } void f_test() { auto sb=f(); sb[2]=100; // Valgrind ok } Valgrind does not complain. But on the other case: // same int[] f() function void f_test() { auto sb=f(); sb[2] = 100; writeln(sb[2]); int test[100]; // these two lines make Valgrind panicking writeln(sb[2]); // } it complains with "Conditional jump or move depends on uninitialised value(s)" I think my two examples are creating a dangling pointer. But I would be happy to understand why Valgrind is not complaining for the first one. Vincent
Re: static array internal & dangling reference
On Saturday, 12 November 2016 at 11:03:31 UTC, Mike Parker wrote: Thank you very much for your clarifications & explanations, I am reassured to see that things work like in C. I will also look the links you provided, thank you again for your time. Vincent
Re: static array internal & dangling reference
Thank you for your answer cym13. I reproduced your result for: On Saturday, 12 November 2016 at 10:45:23 UTC, cym13 wrote: void f_test() { auto sb=f(); sb[2] = 100; writeln(sb[2]); // prints 100 int test[100]; writeln(sb[2]); // prints 0 } now I am convinced of the invalid access, and this time valgrind was not happy, insulting me with: ==13545== Conditional jump or move depends on uninitialised value(s) ==13545==at 0x10A6BA: _D3std4conv55__T11toTextRangeTiTS3std5stdio4File17LockingTextWriterZ11toTextRangeFNfiS3std5stdio4File17LockingTextWriterZv (indexType.d:5123) ==13545==by 0x10ABED: _D3std5stdio4File14__T5writeTiTaZ5writeMFNfiaZv (stdio.d:1424) ==13545==by 0x10A08C: _D3std5stdio14__T7writelnTiZ7writelnFNfiZv (stdio.d:3211) However for my first example, I have checked again and void f_test() { auto sb=f(); sb[2]=100; } Valgrind is silent... I thought it was because of a compiler optimization that removed the unusued "sb[2]=100" statement, but even with: void f_test() { auto sb=f(); sb[2]=100; writeln(sb[2]); } which prints 100, Valgrind still do not complain... ?!? I will try to investigate this and give a feedback if I find an explanation. Vincent
static array internal & dangling reference
Hi all, Still learning... This time what surprised me is how static arrays work. I assume (is it true?) that for efficiency reason static size arrays like int[10] are on the stack and do not involve dynamic memory allocation: First surprise: it is possible to share a static array: void main() { int[10] sa; foreach(int i, ref sa_i;sa){ sa_i=i; } writeln("\n vect init sa",sa); int[] sb=sa[3..6]; // <- did not think it was possible sb[2]=100; writeln("\n vect sa ",sa); writeln("\n vect sb ",sb); } which prints: vect init sa[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] vect sa [0, 1, 2, 3, 4, 100, 6, 7, 8, 9] // <- sa and sb are really shared vect sb [3, 4, 100] Second surprise: I tried to create a dangling reference with: int[] f() { int[10] sa; foreach(int i, ref sa_i;sa){ sa_i=i; } int[] sb=sa; return sb; } void f_test() { auto sb=f(); sb[2]=100; // I expected an "invalid access" (it points to "sa", a local variable) } However calling f_test seems ok and valgrind tool does not complain... So my questions are: 0/ does I miss something? (in C++ for sure you create a dangling pointer) 1/ what is the internal mechanism for that? Is the GC involved? Performance impact? 2/ any link describing this in more details is welcome Thank you
Re: cross_module function overloading & alias & template: how to ?
On Thursday, 10 November 2016 at 20:12:10 UTC, Jonathan M Davis wrote: On Thursday, November 10, 2016 17:41:02 Picaud Vincent via Digitalmars-d- learn wrote: It is certainly a compiler problem: I used gdc -> compile error, but with dmd it compiles and runs fine. Full details in the git repo. Don't bother with gdc at this point. Unless there's a development version of it that's actually up-to-date and hasn't been released yet, it's too old to be reliable with regards to what correct D is. If something doesn't work in gdc, it could easily be because of a bug that has since been fixed. Unfortunately, the gdc folks have never managed to release an updated gdc that uses the D version of the compiler front-end, so as I understand it, they're still stuck at 2.067 (which is over 2 years old), whereas dmd is now at 2.072. ldc should be reasonably up-to-date if you want an alternative to dmd, and I expect that the gdc guys will get there eventually, but they haven't yet. - Jonathan M Davis I just have compiled my example with ldc and everything is ok! I was not aware of that concerning gdc. Thank you for this information, I lost around 2 hours struggling with initial code trying to guess what was wrong. Conclusion: now I will only use ldc and dmd. Thanks to Steven too for his clarification concerning template<->symbol Vincent
Re: cross_module function overloading & alias & template: how to ?
On Thursday, 10 November 2016 at 17:12:32 UTC, Jonathan M Davis wrote: On Thursday, November 10, 2016 15:46:11 Picaud Vincent via Digitalmars-d- learn wrote: [...] Honestly, I'm surprised that the compiler let you alias std.algorithm.comparison.min, because it's a templated function, and in the case of templates, you alias instantiations of templates, not the templates themselves. std.algorithm.comparison.min is just a template for a function, not an actual function. Something like std.algorithm.comparison.min!(int, int) would be an actual function. [...] Hi Jonathan, I just read your answer, thank you a lot Unfortunately I have not the time right now to answer (I am leaving my job it is 6:53PM). I will answer later. However I just created a github repo to reproduce my observations: https://github.com/vincent-picaud/DLang_overloading It is certainly a compiler problem: I used gdc -> compile error, but with dmd it compiles and runs fine. Full details in the git repo. More answers later... I have to leave
cross_module function overloading & alias & template: how to ?
Hi All, In my adventure to learn a little bit of D coming from C++ I am now faced with the following problem: I have read about "cross-module overloading", §5.5.2 page 146 of Andrei Alexandrescu book. That makes sense to me and this is interesting. As a concrete example here the scenario: I want to define a specialized version of the min function. In D knowing that if there is an ambiguity between modules the compiler generates an error, the following example does NOT work: == // I am the my_min.d file module my_min; int min(int a,int b) { return (a use my_min.min auto dc=min(4.5,b); // OK! -> use std.algorithm.comparison.min } == But now I have the following problem: if I use a parametrized function min: == module my_min; import std.algorithm.comparison; T min(T)(T a,T b) { return (a What am I missing? What is the right way to do that? Thank you :)
Re: New to D and mimicking C++ : how to implement std::integral_constant<>?
Hi Basile, Thank you for your code, it allowed me to grasp a little bit more about how to do things in D. Vincent
Re: New to D and mimicking C++ : how to implement std::integral_constant<>?
On Monday, 7 November 2016 at 23:07:27 UTC, Picaud Vincent wrote: typo... auto capacity = max(0,(size_-1)*stride_+1); To be more correct I have something like: alias IntergralConstant!(int,0) Zero_c; alias IntergralConstant!(int,1) One_c; auto capacity = max(Zero_c,(size_-One_c)*stride_+One_c); with "smooth" implicit conversion IntegralConstant -> int for cases where size_ or stride_ are "int" and not both IntegralConstant types.
Re: New to D and mimicking C++ : how to implement std::integral_constant<>?
On Monday, 7 November 2016 at 22:18:56 UTC, Jerry wrote: On Monday, 7 November 2016 at 21:37:50 UTC, Picaud Vincent wrote: static if ( isIntegralConstant!(typeof(required_capacity()) ) { } else { } } Premature post send by error sorry Well something like: static if ( isIntegralConstant!(typeof(required_capacity()) ) ElementType[required_capacity()] data_; else ElementType[] data_; } For that, at least in C++, I need integral_constant<> type with compile-time arithmetic and smooth integration with "usual" size_t/ptrdiff_t types. 2/ I also would like to test some implementations concerning automatic differentiation. I have my own C++ libs, inspired, but ~20% faster than Adept: http://www.met.reading.ac.uk/clouds/adept/ and I would like to know how I can do that in D Well... That is the idea... I hope I will get some results and I will be happy to share if it is something interesting. Vincent Ah I get what you mean, you can do that without using a special type. struct Vector(T, Args...) if(Args.length == 1) { static if(is(Args[0] == size_t)) { size_t size; } else static if(Args[0] != 0) // would error if it's a type that's not size_t { enum size = Args[0]; } else { static assert(0); } } Vector!(int, 10) a; Vector!(int, size_t) b; // both work with IntegralConstant could use __traits(compiles) to see if it's not a type, for that second static if. Which would probably be better, so if you pass a float or something, it won't give a weird error. Thank you again Jerry! For sure my way of thinking is twisted by my C++ habits! :-/ The positive point is that D seems to offer much shorter solutions (this is my hope). However I still need some investigations and/or some guidance: -> not sure that it is ok for me as I really want to track "static constants" all the way long. That is the reason why I introduced the IntegralConstant type (with operator overloading, work in progress) For instance, the code: enum int a=1,b=2; auto c = a+b; pragma(msg,typeof(c)); // prints "int" static assert(c==3); // compilation fails: "variable c cannot be read at compile time" To implement my vector structs I need: 1/ a way to detect compile-time constant vs "dynamic" values 2/ to perform and to propagate compile-time constants across "arithmetic" computations. For instance to compute the required capacity to store vector data, I need something like auto capacity = max(0,(size_-1)*stride_); and this expression must make sense for both "dynamic" values and compile-time constant. In one case I expect typeof(capacity) -> int, in the other typeof(capacity) -> IntegralConst
Re: New to D and mimicking C++ : how to implement std::integral_constant<>?
On Monday, 7 November 2016 at 21:23:37 UTC, Picaud Vincent wrote: On Monday, 7 November 2016 at 18:59:24 UTC, Jerry wrote: On Monday, 7 November 2016 at 18:42:37 UTC, Picaud Vincent wrote: template isIntegralConstant(ANY) { enum bool isIntegralConstant=__traits(identifier,ANY)=="IntegralConstant"; } A bit more elegant way of doing that would be: enum isIntegralConstant(T) = is(T : IntegralConstant!U, U...); I would be very graceful for any help/advice that explains the right way to implement C++ std::integral_constantin the D language. Vincent Now the question is, do you really need IntegralConstant? I've never used it in C++ so I don't really know any of the use cases for it. But generally in D if you need something to be a compile time constant value you can just use "enum". It can be any type as well, so long as it can be evaluated at compile time. enum long someConstant = 1 << 32; Hi Jerry, Thank you so much for your quick answer! I tried your suggestion and it works. My main interest is numerical computations. I have some C++ libs using meta-programming and I want to see how I can translate some parts in D. The goal is to check: productivity & code readability & performance. I will try to implement 2 toy examples: 1/ A basic example of strided dense vector structure dealing with the dynamic/static size in an uniform way. In D I thing this can be done with something like this (not tried yet to compile it, but that is the idea to mimick my C++ implementation) struct Vector(T,SIZE,STRIDE) if( (is(SIZE==size_t)||isIntegralConstant!SIZE) ...) { alias T ElementType; private SIZE size_; private STRIDE stride_; ... auto required_capacity() { return size_*stride_; } // return a size_t or a IntegralConst static if ( isIntegralConstant!(typeof(required_capacity()) ) { } else { } } Premature post send by error sorry Well something like: static if ( isIntegralConstant!(typeof(required_capacity()) ) ElementType[required_capacity()] data_; else ElementType[] data_; } For that, at least in C++, I need integral_constant<> type with compile-time arithmetic and smooth integration with "usual" size_t/ptrdiff_t types. 2/ I also would like to test some implementations concerning automatic differentiation. I have my own C++ libs, inspired, but ~20% faster than Adept: http://www.met.reading.ac.uk/clouds/adept/ and I would like to know how I can do that in D Well... That is the idea... I hope I will get some results and I will be happy to share if it is something interesting. Vincent
Re: New to D and mimicking C++ : how to implement std::integral_constant<>?
On Monday, 7 November 2016 at 18:59:24 UTC, Jerry wrote: On Monday, 7 November 2016 at 18:42:37 UTC, Picaud Vincent wrote: template isIntegralConstant(ANY) { enum bool isIntegralConstant=__traits(identifier,ANY)=="IntegralConstant"; } A bit more elegant way of doing that would be: enum isIntegralConstant(T) = is(T : IntegralConstant!U, U...); I would be very graceful for any help/advice that explains the right way to implement C++ std::integral_constantin the D language. Vincent Now the question is, do you really need IntegralConstant? I've never used it in C++ so I don't really know any of the use cases for it. But generally in D if you need something to be a compile time constant value you can just use "enum". It can be any type as well, so long as it can be evaluated at compile time. enum long someConstant = 1 << 32; Hi Jerry, Thank you so much for your quick answer! I tried your suggestion and it works. My main interest is numerical computations. I have some C++ libs using meta-programming and I want to see how I can translate some parts in D. The goal is to check: productivity & code readability & performance. I will try to implement 2 toy examples: 1/ A basic example of strided dense vector structure dealing with the dynamic/static size in an uniform way. In D I thing this can be done with something like this (not tried yet to compile it, but that is the idea to mimick my C++ implementation) struct Vector(T,SIZE,STRIDE) if( (is(SIZE==size_t)||isIntegralConstant!SIZE) ...) { alias T ElementType; private SIZE size_; private STRIDE stride_; ... auto required_capacity() { return size_*stride_; } // return a size_t or a IntegralConst static if ( isIntegralConstant!(typeof(required_capacity()) ) { } else { } }
New to D and mimicking C++ : how to implement std::integral_constant<>?
Hi all, I have ~15y of C++ and now I want to test D, because it seems really intersting and "cleaner" than C++. As an exercice I m trying to implement something equivalent to the C++ std::integral_constantin D. In D: struct IntegralConstant(T, T VALUE) { ... } But I do not know how to write a compile-time type check. I tried template isIntegralConstant(ANY) { enum bool isIntegralConstant=__traits(identifier,ANY)=="IntegralConstant"; } But when using it with ANY=long type, I get a compile-time error: "argument long has no identifier" A workaround that worked is: struct IntegralConstantTag {} struct IntegralConstant(T, T VALUE) { private IntegralConstantTag selfTag_; alias selfTag_ this; } template isIntegralConstant(ANY) { enum bool isIntegralConstant=is(ANY : IntegralConstantTag); } But now I'm sticked by a compiler issue when I want to introduce 2 "alias this" to allow implicit conversion: struct IntegralConstant(T, T VALUE) { private IntegralConstantTag selfTag_; alias selfTag_ this; T value_=VALUE; alias value_ this; } Compiler error message is "integralConstant.d:16:3: error: there can be only one alias this". I would be very graceful for any help/advice that explains the right way to implement C++ std::integral_constant in the D language. Vincent