digitalmars.D - refInt = ref int: how to achieve this? or is this a bug?
- mw (21/21) Jun 17 2020 ----------------
- Steven Schveighoffer (10/36) Jun 17 2020 It's not possible in this way. ref is a storage class and not part of
- mw (14/23) Jun 17 2020 I'm trying to typedef a PushT here:
- mw (23/29) Jun 17 2020 I would consider it a bug, *even* C++ can handle this better :-)
- Avrina (24/55) Jun 17 2020 It's not a bug, it is purposefully designed to be that way.
- mw (34/36) Jun 17 2020 Thanks for the suggestion.
- MoonlightSentinel (9/10) Jun 17 2020 Try
- MoonlightSentinel (12/13) Jun 17 2020 On Wednesday, 17 June 2020 at 22:15:08 UTC, MoonlightSentinel
- mw (7/17) Jun 17 2020 That's the semantics of reference: you cannot define a ref
- MoonlightSentinel (7/13) Jun 17 2020 That's the inherent difference here, ref is a half-baked type
- mw (5/7) Jun 17 2020 It's not the bug in my code,
- Stanislav Blinov (5/12) Jun 17 2020 It is both. In your code, for trying to use `ref` as a type
- mw (12/19) Jun 17 2020 Given the current language semantics, right, it shouldn't be
- Stanislav Blinov (8/26) Jun 17 2020 Which translates to "take everything that implicitly converts to
- mw (8/18) Jun 17 2020 It has to be done: because the C lib only accept void* as value.
- mw (3/22) Jun 17 2020 OK, guess Auto Ref Parameters is specially designed for this:
- Paul Backus (8/14) Jun 17 2020 void* address(T)(ref T arg)
- Stanislav Blinov (20/39) Jun 17 2020 That's completely backwards. Because the C lib only takes void*,
- mw (18/23) Jun 17 2020 Thank you for your comments.
- mw (4/6) Jun 17 2020 typo:
- Stanislav Blinov (22/37) Jun 17 2020 So... not doing this:
- mw (38/50) Jun 17 2020 Can all of these be rewritten as:
- mw (7/23) Jun 17 2020 https://github.com/dlang/phobos/blob/master/std/range/package.d#L921
- Steven Schveighoffer (6/33) Jun 18 2020 Three lines up:
- Stanislav Blinov (6/11) Jun 18 2020 Yup, it's just a bug in the parser. You can even do a
- H. S. Teoh (6/11) Jun 18 2020 Wow that's ridiculous. A bug should be filed for this!
- Stanislav Blinov (4/10) Jun 19 2020 It has been, not to worry. Also, a sense of deja vu kept bugging
- H. S. Teoh (7/9) Jun 19 2020 LOL, wow. Now *that* is totally ridiculous. :-D (And yeah, I also
- Stanislav Blinov (11/22) Jun 17 2020 No, I can't.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (30/31) Jun 17 2020 (Aside: I think this thread should be on the 'learn' forum.)
- mw (9/12) Jun 17 2020 That's my initially thought, but then I realized this could be a
- Stanislav Blinov (11/23) Jun 17 2020 This is not a bug, this is by design.
- mw (13/23) Jun 17 2020 This discussion is not about this particular usage in that
- Stanislav Blinov (4/8) Jun 17 2020 f(T) {}
- mw (3/12) Jun 17 2020 This alone will not work, have to add more static if's
---------------- import std.stdio; alias refInt = ref int; void f(refInt i) { i = 456; } void main() { int i = 123; writeln(i); f(i); writeln(i); } ---------------- $ $DMD/windows/bin64/rdmd.exe reft.d 123 123 $ $LDC/bin/rdmd reft.d 123 123 How to achieve this typdef/alias that what I want? Thanks.
Jun 17 2020
On 6/17/20 4:38 PM, mw wrote:---------------- import std.stdio; alias refInt = ref int; void f(refInt i) { i = 456; } void main() { int i = 123; writeln(i); f(i); writeln(i); } ---------------- $ $DMD/windows/bin64/rdmd.exe reft.d 123 123 $ $LDC/bin/rdmd reft.d 123 123 How to achieve this typdef/alias that what I want?It's not possible in this way. ref is a storage class and not part of the type. Essentially, your alias statement becomes: alias refInt = int; Which in itself is somewhat of a "feature", as storage classes that do not apply are ignored. Some may consider it a bug, but I haven't seen anyone attempt something like what you have, it sure seems like the compiler should complain. -Steve
Jun 17 2020
On Wednesday, 17 June 2020 at 20:47:59 UTC, Steven Schveighoffer wrote:On 6/17/20 4:38 PM, mw wrote: It's not possible in this way. ref is a storage class and not part of the type. Essentially, your alias statement becomes: alias refInt = int; Which in itself is somewhat of a "feature", as storage classes that do not apply are ignored. Some may consider it a bug, but I haven't seen anyone attempt something like what you have, it sure seems like the compiler should complain.I'm trying to typedef a PushT here: https://github.com/mingwugmail/liblfdsd/blob/master/liblfds.dpp#L52 The C interface only accept void*, so I need different PushT type for different D type (basic type int|double, ..., struct, class, stirng|array). Without be able to `alias PushT = ref T`, it's hard to define this func: https://github.com/mingwugmail/liblfdsd/blob/master/liblfds.dpp#L72 bool push(PushT value) { ... } Any work-around? or suggestions how to structure the D code?
Jun 17 2020
On Wednesday, 17 June 2020 at 20:47:59 UTC, Steven Schveighoffer wrote:Essentially, your alias statement becomes: alias refInt = int; Which in itself is somewhat of a "feature", as storage classes that do not apply are ignored. Some may consider it a bug, but I haven't seen anyone attempt something like what you have, it sure seems like the compiler should complain.I would consider it a bug, *even* C++ can handle this better :-) i.e. no surprise to the programmer. cat reft.cpp ---------------------- #include <stdio.h> typedef int& refInt; void f(refInt i) { i = 456; } int main() { int i = 123; printf("%d\n", i); f(i); printf("%d\n", i); } ---------------------- $ make reft g++ reft.cpp -o reft $ ./reft 123 456
Jun 17 2020
On Wednesday, 17 June 2020 at 21:27:01 UTC, mw wrote:On Wednesday, 17 June 2020 at 20:47:59 UTC, Steven Schveighoffer wrote:It's not a bug, it is purposefully designed to be that way. Just like you can't do ref variables. void main() { int a; int& b = a; // ok C++ ref int c = a; // not valid D } You can do something like this instead, not sure what you are trying to do tho. Could just be easier to put a separate function in the `static if` that you are trying to define the ref type in instead. import std.stdio; void foo(T)(auto ref T v) if (is(T : int) == __traits(isRef, v)) { writeln(__traits(isRef, v) ? "by ref" : "by value"); } void main() { int a; foo(a); // by ref // foo(10); // error by value float b; // foo(b); // error by ref foo(10.0f); // by value }Essentially, your alias statement becomes: alias refInt = int; Which in itself is somewhat of a "feature", as storage classes that do not apply are ignored. Some may consider it a bug, but I haven't seen anyone attempt something like what you have, it sure seems like the compiler should complain.I would consider it a bug, *even* C++ can handle this better :-) i.e. no surprise to the programmer. cat reft.cpp ---------------------- #include <stdio.h> typedef int& refInt; void f(refInt i) { i = 456; } int main() { int i = 123; printf("%d\n", i); f(i); printf("%d\n", i); } ---------------------- $ make reft g++ reft.cpp -o reft $ ./reft 123 456
Jun 17 2020
On Wednesday, 17 June 2020 at 21:49:29 UTC, Avrina wrote:void foo(T)(auto ref T v) if (is(T : int) == __traits(isRef, > v)) {Thanks for the suggestion. Yes, that what I mean by: "guess I have to write more `static if`s." That is ugly. My thought is that: pointer and reference are all types of its own right: typedef `int*` is ptr in C++ typedef `int&` is ref in C++ and can you see the beauty of this symmetry? :-) In D, alias can correctly treat int* as pointer type, but treat `ref int` as `int`, this break the symmetry alias `int*` is ptr in D alias `ref int` becomes *int* in D can you see the visual ugliness of this? :-) not even to mention the semantic ugliness: compiler error on g(), not on f(): --------------------------- alias refInt = ref int; alias ptrInt = int*; void f(refInt i) { i = 456; } void g(ptrInt i) { } void main() { int i = 123; writeln(i); // 123 f(i); writeln(i); // 123! again g(i); // Error: function `reft.g(int* i)` is not callable using argument types `(int)` } ---------------------------
Jun 17 2020
On Wednesday, 17 June 2020 at 22:09:35 UTC, mw wrote:and can you see the beauty of this symmetry? :-)Try int main() { typedef int* ptrInt; ptrInt arr; typedef int& refInt; refInt[] arr2; }
Jun 17 2020
On Wednesday, 17 June 2020 at 22:15:08 UTC, MoonlightSentinel wrote:On Wednesday, 17 June 2020 at 22:09:35 UTC, mw wrote:On Wednesday, 17 June 2020 at 22:15:08 UTC, MoonlightSentinel wrote: Wrong code, this was the intended code: int main() { typedef int* ptrInt; ptrInt arr[5]; typedef int& refInt; refInt arr2[5]; }
Jun 17 2020
On Wednesday, 17 June 2020 at 22:15:08 UTC, MoonlightSentinel wrote:On Wednesday, 17 June 2020 at 22:09:35 UTC, mw wrote:That's the semantics of reference: you cannot define a ref variable out of air. The equivalent D code cannot be compiled either. We are talking about pass either `ptr` or `ref` to other functions here.and can you see the beauty of this symmetry? :-)Try int main() { typedef int* ptrInt; ptrInt arr; typedef int& refInt; refInt[] arr2; }
Jun 17 2020
On Wednesday, 17 June 2020 at 22:33:50 UTC, mw wrote:We are talking about pass either `ptr` or `ref` to other functions here.To quote some more of your previous post:My thought is that: pointer and reference are all types of its own right: typedef `int*` is ptr in C++ typedef `int&` is ref in C++That's the inherent difference here, ref is a half-baked type constructor in C++ (and porting that behaviour to D would be a mistake as it would screw with highly templated code). But i would agree with you that there is a bug in your initial code, the `ref` should be rejected.
Jun 17 2020
On Wednesday, 17 June 2020 at 22:48:25 UTC, MoonlightSentinel wrote:But i would agree with you that there is a bug in your initialIt's not the bug in my code,code, the `ref` should be rejected.it's the compiler's bug not rejecting it, given it's current semantics; instead it *silently* treat alias `ref int` as `int`.
Jun 17 2020
On Wednesday, 17 June 2020 at 23:05:59 UTC, mw wrote:On Wednesday, 17 June 2020 at 22:48:25 UTC, MoonlightSentinel wrote:It is both. In your code, for trying to use `ref` as a type qualifier when it is not (see [1] for type qualifiers), and in the compiler, for not issuing an error. [1] https://dlang.org/spec/const3.htmlBut i would agree with you that there is a bug in your initialIt's not the bug in my code,code, the `ref` should be rejected.it's the compiler's bug not rejecting it, given it's current semantics; instead it *silently* treat alias `ref int` as `int`.
Jun 17 2020
On Wednesday, 17 June 2020 at 23:09:55 UTC, Stanislav Blinov wrote:Given the current language semantics, right, it shouldn't be typedef/alias-ed, But it make the code so complex / ugly to write: either: void foo(T)(auto ref T v) if (is(T : int) == __traits(isRef, v)) {} or f( T) /*more static if here*/ { /*potential dup code here*/ } f(ref T) /*more static if here*/ { /*potential dup code here*/ } I would call for improvement.it's the compiler's bug not rejecting it, given it's current semantics; instead it *silently* treat alias `ref int` as `int`.It is both. In your code, for trying to use `ref` as a type qualifier when it is not (see [1] for type qualifiers), and inthe compiler, for not issuing an error. [1] https://dlang.org/spec/const3.html
Jun 17 2020
On Wednesday, 17 June 2020 at 23:24:32 UTC, mw wrote:On Wednesday, 17 June 2020 at 23:09:55 UTC, Stanislav Blinov wrote:Which translates to "take everything that implicitly converts to int by reference, and everything else - by value". I would love to see that same intent expressed in C++ in one declaration.Given the current language semantics, right, it shouldn't be typedef/alias-ed, But it make the code so complex / ugly to write: either: void foo(T)(auto ref T v) if (is(T : int) == __traits(isRef, v)) {}it's the compiler's bug not rejecting it, given it's current semantics; instead it *silently* treat alias `ref int` as `int`.It is both. In your code, for trying to use `ref` as a type qualifier when it is not (see [1] for type qualifiers), and inor f( T) /*more static if here*/ { /*potential dup code here*/ } f(ref T) /*more static if here*/ { /*potential dup code here*/ } I would call for improvement.Again, looking at your code, this all comes out of your trying to conflate references and pass by reference. References (i.e. classes) and values (i.e. primitive types and structs) are semantically different, so should be treated differently.
Jun 17 2020
On Wednesday, 17 June 2020 at 23:48:52 UTC, Stanislav Blinov wrote:It has to be done: because the C lib only accept void* as value. So on the D side, need to pass to C: -- primitive types, class (essentially pointers) by value -- struct, union, array|string, by reference The discussion here is how to make this passing code simple to write.f( T) /*more static if here*/ { /*potential dup code here*/ } f(ref T) /*more static if here*/ { /*potential dup code here*/ } I would call for improvement.Again, looking at your code, this all comes out of your trying to conflate references and pass by reference. References (i.e. classes) and values (i.e. primitive types and structs) are semantically different, so should be treated differently.
Jun 17 2020
On Wednesday, 17 June 2020 at 23:58:37 UTC, mw wrote:On Wednesday, 17 June 2020 at 23:48:52 UTC, Stanislav Blinov wrote:OK, guess Auto Ref Parameters is specially designed for this: https://dlang.org/spec/template.html#auto-ref-parametersIt has to be done: because the C lib only accept void* as value. So on the D side, need to pass to C: -- primitive types, class (essentially pointers) by value -- struct, union, array|string, by reference The discussion here is how to make this passing code simple to write.f( T) /*more static if here*/ { /*potential dup code here*/ } f(ref T) /*more static if here*/ { /*potential dup code here*/ } I would call for improvement.Again, looking at your code, this all comes out of your trying to conflate references and pass by reference. References (i.e. classes) and values (i.e. primitive types and structs) are semantically different, so should be treated differently.
Jun 17 2020
On Wednesday, 17 June 2020 at 23:58:37 UTC, mw wrote:It has to be done: because the C lib only accept void* as value. So on the D side, need to pass to C: -- primitive types, class (essentially pointers) by value -- struct, union, array|string, by reference The discussion here is how to make this passing code simple to write.void* address(T)(ref T arg) { static if (is(T == class) || is(T == interface)) return cast(void*) arg; else return cast(void*) &arg; }
Jun 17 2020
On Wednesday, 17 June 2020 at 23:58:37 UTC, mw wrote:On Wednesday, 17 June 2020 at 23:48:52 UTC, Stanislav Blinov wrote:That's completely backwards. Because the C lib only takes void*, it forfeits any type safety and memory safety, so it is *on you* to preserve that. Which would require quite some code indeed. I don't think you've fully considered the implications of your code. You allocate an opaque memory region, which the GC knows nothing about, and you want to put pointers and references into it. That's bug number 1. Whether the GC *should* know about that memory depends on types you're using - static ifs are a must. You want to escape unshared pointers into other threads. That's bug number 2. The language can't statically verify that a pointer you're passing is the only pointer. It can only help you verify that a pointer you're passing may not point to unshared data - static ifs are a must. You want to escape pointers to locals on the stack to other threads. That's, tentatively, bug number 3. And no static ifs for that one, here you're on your own. And you want it all doable with "simple to write" code? That code *should* be onerous to write, like any other side stepping of the type system.It has to be done: because the C lib only accept void* as value. So on the D side, need to pass to C: -- primitive types, class (essentially pointers) by value -- struct, union, array|string, by reference The discussion here is how to make this passing code simple to write.f( T) /*more static if here*/ { /*potential dup code here*/ } f(ref T) /*more static if here*/ { /*potential dup code here*/ } I would call for improvement.Again, looking at your code, this all comes out of your trying to conflate references and pass by reference. References (i.e. classes) and values (i.e. primitive types and structs) are semantically different, so should be treated differently.
Jun 17 2020
On Thursday, 18 June 2020 at 00:40:15 UTC, Stanislav Blinov wrote:That's completely backwards. Because the C lib only takes void*, it forfeits any type safety and memory safety, so it is *on you* to preserve that. Which would require quite some code indeed. I don't think you've fully considered the implications of your code.Thank you for your comments. But I think you complicated the design: C is C, D is D. So let -- C manage C's memory (the container), and -- D manage C's memory (the objects) The only thing interfacing is simple the (void*) as *value*. -- all primitive types | class (pointers)'s *value* are stored as value of (void*) -- all (fat) objects' *address* are stored as value of (void*) The only extra requirement on the D side is to keep reference to those fat objects to avoid it being GC-ed before being pop-ed. (Just as don't push a stack var into any-type-of queue, and pop it after the stack is gone -- this are the responsibility of the programmer, not the container.) That's all. Anyway, this is a bit off-topic of this thread. Feel free to comment on github after I finish it, and welcome to be my code reviewers.
Jun 17 2020
On Thursday, 18 June 2020 at 01:21:52 UTC, mw wrote:-- C manage C's memory (the container), and -- D manage C's memory (the objects)typo: -- D manage D's memory but you know I like symmetry, easy to detect errors.
Jun 17 2020
On Thursday, 18 June 2020 at 01:21:52 UTC, mw wrote:Thank you for your comments. But I think you complicated the design: C is C, D is D. So let -- C manage C's memory (the container), and -- D manage D's memory (the objects) The only thing interfacing is simple the (void*) as *value*. -- all primitive types | class (pointers)'s *value* are stored as value of (void*) -- all (fat) objects' *address* are stored as value of (void*) The only extra requirement on the D side is to keep reference to those fat objects to avoid it being GC-ed before being pop-ed. (Just as don't push a stack var into any-type-of queue, and pop it after the stack is gone -- this are the responsibility of the programmer, not the container.) That's all.So... not doing this: queue.push(new Object); // receiver may get garbage reference or this (when compiled with -preview=rvaluerefparam, in other words, when rvalues would be allowed to bind to refs): queue.push(FatStruct()); // temporary is gone after push() returns or, more to the point, since you want this to be very "generic": queue.push(createStuff!options()); // yeah, createStuff is somewhere inside 20kLOC in another module ...NOT doing any of those are all also programmer's responsibility? You're absolutely correct, C is C, and D is D, and type system exists for a reason, yet you're trying to circumvent it, and don't like it when the language fights back. Like I originally remarked, if you *want* to be escaping pointers, then escape pointers, and state as much in your interface. That will simplify it (the interface), and leave your users (i.e. "the programmers") with no illusions as to what's going on. ...or, realize that values and references have different semantics, and require different handling (in other words, different queue types).
Jun 17 2020
On Thursday, 18 June 2020 at 02:22:55 UTC, Stanislav Blinov wrote:On Thursday, 18 June 2020 at 01:21:52 UTC, mw wrote:queue.push(new Object); // receiver may get garbage reference queue.push(FatStruct()); // temporary is gone after push() queue.push(createStuff!options()); // yeah, createStuff isCan all of these be rewritten as: dSideRefHolderVar = dSideWhateverStuff(); queue.push(dSideRefHolderVar); ? To use that C lib, then have to live with its constraints. I have no intention to wrap that library to work universally in the D world. If dpp can provide a thin oo wrapper automatically, I don’t even want to write this one.You're absolutely correct, C is C, and D is D, and type systemI’m glad you recognize this:-)exists for a reason, yet you're trying to circumvent it, and don't like it when the language fights back.This is not true: the compiler silently throw away ref from the alias without issuing an error; if it did, I would be more sure it’s a feature rather than bug, given the current semantics. Then I will try to find other way to make it work.Like I originally remarked, if you *want* to be escaping pointers, then escape pointers, and state as much in your interface. That will simplify it (the interface), and leave your users (i.e. "the programmers") with no illusions as to what's going on.That’s right: The library user have to know how the original library works in order to use the wrapper. Maybe I haven’t mentioned this: “To make those initial values valid (which is to say, visible) upon other logical cores, threads on those cores need to issue the define https://www.liblfds.org/mediawiki/index.php?title=r7.1.1:Define_LFDS711_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE ” It’s ugly macro of that C lib need to be called, but need to live with it. And even laughable this: The LFDS711_QUEUE_BMM_QUERY_GET_POTENTIALLY_INACCURATE_COUNT query is not guaranteed to be accurate. Where enqueue and dequeue operations are not guaranteed to be visible by the time the function calls return, similarly, it may be that a count will during its operation not see an element which has been enqueued, or see that an element has been dequeued. In general however it should be bang on; it's just it's not guaranteed. https://www.liblfds.org/mediawiki/index.php?title=r7.1.1:Function_lfds711_queue_bmm_query#Notes Yet, this library is the best time tested open source library on the internet. I have no interest to re-invent the wheels, or make the wrapper universal. Because it’s much better than the ~4x times slower fewly-used D queues I have found.
Jun 17 2020
On Wednesday, 17 June 2020 at 23:09:55 UTC, Stanislav Blinov wrote:On Wednesday, 17 June 2020 at 23:05:59 UTC, mw wrote:https://github.com/dlang/phobos/blob/master/std/range/package.d#L921 ``` alias ElementType = ref RvalueElementType; ``` Even code in phobos try to write this way too :-)On Wednesday, 17 June 2020 at 22:48:25 UTC, MoonlightSentinel wrote:It is both. In your code, for trying to use `ref` as a type qualifier when it is not (see [1] for type qualifiers), and in the compiler, for not issuing an error. [1] https://dlang.org/spec/const3.htmlBut i would agree with you that there is a bug in your initialIt's not the bug in my code,code, the `ref` should be rejected.it's the compiler's bug not rejecting it, given it's current semantics; instead it *silently* treat alias `ref int` as `int`.
Jun 17 2020
On 6/18/20 2:01 AM, mw wrote:On Wednesday, 17 June 2020 at 23:09:55 UTC, Stanislav Blinov wrote:Three lines up: https://github.com/dlang/phobos/blob/master/std/range/package.d#L918 // This doesn't work yet I don't think it will ever work. -SteveOn Wednesday, 17 June 2020 at 23:05:59 UTC, mw wrote:https://github.com/dlang/phobos/blob/master/std/range/package.d#L921 ``` alias ElementType = ref RvalueElementType; ``` Even code in phobos try to write this way too :-)On Wednesday, 17 June 2020 at 22:48:25 UTC, MoonlightSentinel wrote:It is both. In your code, for trying to use `ref` as a type qualifier when it is not (see [1] for type qualifiers), and in the compiler, for not issuing an error. [1] https://dlang.org/spec/const3.htmlBut i would agree with you that there is a bug in your initialIt's not the bug in my code,code, the `ref` should be rejected.it's the compiler's bug not rejecting it, given it's current semantics; instead it *silently* treat alias `ref int` as `int`.
Jun 18 2020
On Thursday, 18 June 2020 at 14:16:51 UTC, Steven Schveighoffer wrote:Three lines up: https://github.com/dlang/phobos/blob/master/std/range/package.d#L918 // This doesn't work yet I don't think it will ever work. -SteveYup, it's just a bug in the parser. You can even do a alias wow = ref override abstract final scope static __gshared int; Still gonna be an int tho.
Jun 18 2020
On Thu, Jun 18, 2020 at 02:20:04PM +0000, Stanislav Blinov via Digitalmars-d wrote: [...]Yup, it's just a bug in the parser. You can even do a alias wow = ref override abstract final scope static __gshared int; Still gonna be an int tho.Wow that's ridiculous. A bug should be filed for this! T -- Those who don't understand Unix are condemned to reinvent it, poorly.
Jun 18 2020
On Thursday, 18 June 2020 at 14:45:01 UTC, H. S. Teoh wrote:It has been, not to worry. Also, a sense of deja vu kept bugging me, I found why: https://forum.dlang.org/post/k2fq3b$1t33$1 digitalmars.comalias wow = ref override abstract final scope static __gshared int; Still gonna be an int tho.Wow that's ridiculous. A bug should be filed for this! T
Jun 19 2020
On Fri, Jun 19, 2020 at 01:21:07PM +0000, Stanislav Blinov via Digitalmars-d wrote: [...]It has been, not to worry. Also, a sense of deja vu kept bugging me, I found why: https://forum.dlang.org/post/k2fq3b$1t33$1 digitalmars.comLOL, wow. Now *that* is totally ridiculous. :-D (And yeah, I also vaguely remember seeing that back then.) T -- Life is too short to run proprietary software. -- Bdale Garbee
Jun 19 2020
On Wednesday, 17 June 2020 at 22:09:35 UTC, mw wrote:My thought is that: pointer and reference are all types of its own right: typedef `int*` is ptr in C++ typedef `int&` is ref in C++ and can you see the beauty of this symmetry? :-)No, I can't. typedef int* intPtr; const intPtr ip = new int; typedef int& intRef; const intRef i = 3; // oops, does not compileIn D, alias can correctly treat int* as pointer type, but treat `ref int` as `int`, this break the symmetryref int is not a type. What should break is the line alias intRef = ref int; should not compile. Looks like it does compile. That's a bug.alias `int*` is ptr in D alias `ref int` becomes *int* in D can you see the visual ugliness of this? :-) not even to mention the semantic ugliness:You're conflating reference types and pass by reference. These are not the same thing in D, and never will be.
Jun 17 2020
On 6/17/20 1:38 PM, mw wrote:alias refInt = ref int;(Aside: I think this thread should be on the 'learn' forum.) I've just come up with the following struct just to compile the code. It works but as you see with need for refInt(i) inside main, constructors are not called automatically in D. (Hence your thread. :) ) import std.stdio; struct refInt { int * p; this(ref int i) { this.p = &i; } ref int reference() { return *p; } alias reference this; auto opAssign(int i) { reference() = i; return this; } } void f(refInt i) { i = 456; } void main() { int i = 123; writeln(i); f(refInt(i)); writeln(i); } Ali
Jun 17 2020
On Wednesday, 17 June 2020 at 21:01:53 UTC, Ali Çehreli wrote:On 6/17/20 1:38 PM, mw wrote: (Aside: I think this thread should be on the 'learn' forum.)That's my initially thought, but then I realized this could be a D bug, or a feature request.struct refInt {...}Yes, I know there are work-around, but for my usage: https://github.com/mingwugmail/liblfdsd/blob/master/liblfds.dpp#L52 all these work-around are too heavy, a verbatim typedef in my question is the most succinct way to be used. Sigh, looks like it's not supported at this time, guess I have to write more `static if`s.
Jun 17 2020
On Wednesday, 17 June 2020 at 21:20:00 UTC, mw wrote:On Wednesday, 17 June 2020 at 21:01:53 UTC, Ali Çehreli wrote:This is not a bug, this is by design. Also, you're trying to escape a pointer to arbitrary non-`shared` data residing on the stack into some global, shared, storage. I.e. (a) to not cause UB, you will need to make sure the consumer gets the data before you go out of scope, which defeats the purpose of this lock-free queue. And (b) to not cause UB, you will need to make sure consumer does not access the data concurrently with the producer. With that taken into account, if you do want to be escaping pointers, just escape pointers.On 6/17/20 1:38 PM, mw wrote: (Aside: I think this thread should be on the 'learn' forum.)That's my initially thought, but then I realized this could be a D bug, or a feature request.struct refInt {...}Yes, I know there are work-around, but for my usage: https://github.com/mingwugmail/liblfdsd/blob/master/liblfds.dpp#L52 all these work-around are too heavy, a verbatim typedef in my question is the most succinct way to be used. Sigh, looks like it's not supported at this time, guess I have to write more `static if`s.
Jun 17 2020
On Wednesday, 17 June 2020 at 22:19:28 UTC, Stanislav Blinov wrote:This is not a bug, this is by design. Also, you're trying to escape a pointer to arbitrary non-`shared` data residing on the stack into some global, shared, storage. I.e. (a) to not cause UB, you will need to make sure the consumer gets the data before you go out of scope, which defeats the purpose of this lock-free queue. And (b) to not cause UB, you will need to make sure consumer does not access the data concurrently with the producer. With that taken into account, if you do want to be escaping pointers, just escape pointers.This discussion is not about this particular usage in that particular queue (either shared/lock free or not). Even with a plain dummy queue, the user can do whatever s/he want with the queue, e.g. push a stack var, and pop it when that stack is gone :-). The queue object has no control of this, again regardless of what kind of the queue it is. It's the programmers' responsibility to make sure the push/pop usage is right. Here we are discussing how to write: -- f(pass by value) and -- f(pass by ref) in a simple and straight forward way.
Jun 17 2020
On Wednesday, 17 June 2020 at 22:41:21 UTC, mw wrote:Here we are discussing how to write: -- f(pass by value) and -- f(pass by ref) in a simple and straight forward way.f(T) {} f(ref T) {} ¯\_(ツ)_/¯
Jun 17 2020
On Wednesday, 17 June 2020 at 22:50:01 UTC, Stanislav Blinov wrote:On Wednesday, 17 June 2020 at 22:41:21 UTC, mw wrote:This alone will not work, have to add more static if'sHere we are discussing how to write: -- f(pass by value) and -- f(pass by ref) in a simple and straight forward way.f(T) {} f(ref T) {}
Jun 17 2020