digitalmars.D - rval->ref const(T), implicit conversions
- Manu via Digitalmars-d (52/52) Jan 18 2016 One more time...
- bachmeier (4/7) Jan 18 2016 This is a good example of why D should stop trying to convert C++
- Namespace (1/1) Jan 18 2016 You don't give up, huh? ;)
- kinke (8/9) Jan 19 2016 I'm glad he doesn't. I couldn't agree more with Manu. It's the
- tsbockman (41/52) Jan 18 2016 Does this do what you want?
- Meta (5/85) Jan 18 2016 There was this pull request which implemented `auto ref` for
- Namespace (1/1) Jan 18 2016 That is mine. I closed it after it was more or less abandoned.
- tsbockman (28/39) Jan 18 2016 Actually, I was way overthinking things. Does *this* do what you
- tsbockman (57/59) Jan 18 2016 Genericized:
- Nick Treleaven (6/17) Jan 18 2016 Seems like a template function wrapper could add the temporaries
- tsbockman (2/3) Jan 18 2016 https://github.com/D-Programming-Language/phobos/pull/3937
- bitwise (5/8) Jan 18 2016 Is this like...a sarcastic pull request?
- tsbockman (13/22) Jan 18 2016 It's ten times easier to write code that way, than the way Manu
- tsbockman (31/33) Jan 18 2016 To clarify:
- bitwise (22/55) Jan 18 2016 Sorry if that seemed mean, but it wasn't meant to be insulting.
- tsbockman (29/51) Jan 18 2016 That has fundamentally different semantics from my PR, and does
- tsbockman (3/6) Jan 18 2016 Oops - I was being a little dyslexic here. It's actually much
- bitwise (24/34) Jan 19 2016 Your solution suffers from exactly the same problem. It still
- Timon Gehr (2/9) Jan 19 2016 It actually isn't.
- bitwise (3/19) Jan 19 2016 Clearly, it is =)
- Timon Gehr (5/21) Jan 19 2016 The point isn't particularly original. It's come up in most sufficiently...
- bitwise (6/32) Jan 19 2016 I would argue that there is no sufficient length for this kind of
One more time... Assuming: void func(const CustomString &s1, const CustomString &s2); void func(ref const(CustomString) s1, ref const(CustomString) s2); C++: func("hello", "world"); D: auto dumb_name = CustomString("hello"); auto another_dumb_name = CustomString("world"); func(dumb_name, another_dumb_name); I _hate_ this. Almost every line of my current project's non-systems code looks like this. The majority of the code I'm working with is event handlers and glue logic, which looks like this. Tons of 1 liners and glue. D code is much larger by volume, and much less readable than C++. The statement above has about a 1/8 signal to noise ratio, and this is actually understated; I have a lot of functions that take 4 strings like that! This problem extends well beyond strings, but it's a classic example. The main advantage of D is modules, slices, forward referencing and compile times, but I'm seeing trade off of much less efficient code density/brevity for those advantages. D has a meta advantage, but I'm writing C++11/14 code now which is *almost* sufficient, so that advantage is quite diminished in 2016. In general, I'm finding it hard to do anything useful in this project without C++ style implicit conversions. Compared to C++ code, I'm finding D becomes riddled with explicit constructor calls and terrible stack variable names where C++ implicit construction/conversion would normally kick in. This becomes more awkward in some generic function situations, but it's especially painful (queue broken record) passing such rvalues to ref-args. There is truly nothing else in D that has caused so much unrelenting grief as not being able to pass an rvalue to ref const(T). If we are never to get a scope-like solution, then consider supporting C++ style rval->const ref, as a pure practicality. It's been long enough, like, 7 years or something I've been waiting. So, where are we heading with this? I raise this a couple of times a year. In 6 years, after a lot of talk (and various rejected proposals), as far as I can tell, we aren't any closer to a plan. In my experience, this has always been and remains the biggest practical annoyance writing D code, _by far_. It affects a very high number of my lines of code, of all kinds. What I don't get is, why does this seem to be unique to me? Perhaps it's because one common thread among almost all my D applications, is that I'm working together with C/C++. I can't transition to D unless I can work effectively against existing/established code. That's all I've been trying to do for this past 6-7 years, and I'm yet to successfully produced an acceptable transition path in my years of trying. This remains a very significant contributor to that failure. How are we going to resolve this? Nobody will want to transition if their code gets plainly worse, from a basic practical standpoint.
Jan 18 2016
On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:Nobody will want to transition if their code gets plainly worse, from a basic practical standpoint.This is a good example of why D should stop trying to convert C++ programmers. There's no way to integrate C++ code into a D project, beyond creating a C interface to some functions.
Jan 18 2016
On Monday, 18 January 2016 at 17:48:39 UTC, Namespace wrote:You don't give up, huh? ;)I'm glad he doesn't. I couldn't agree more with Manu. It's the one thing I really, I mean *really* detest about D. To me, this rvalue-to-ref bindability is 100x more important than the GC. Yet it keeps on being neglected and worked around with `auto ref` hacks. PS: I also hate the Roboto font (at least here on Windows w/ Firefox). :P
Jan 19 2016
On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:One more time... Assuming: void func(const CustomString &s1, const CustomString &s2); void func(ref const(CustomString) s1, ref const(CustomString) s2); C++: func("hello", "world"); D: auto dumb_name = CustomString("hello"); auto another_dumb_name = CustomString("world"); func(dumb_name, another_dumb_name);Does this do what you want? import std.stdio; bool isLValue(T)(ref T val) { return true; } struct CustomString { this(string data) { this.data = data; } string data; alias data this; } void func(ref CustomString s1, ref CustomString s2) { writeln(s1); writeln(s2); s2 = "universe!"; } pragma(inline, true) void arFunc(T, V)(auto ref T s1, auto ref V s2) { static if(__traits(compiles, isLValue(s1))) alias s1L = s1; else T s1L = s1; static if(__traits(compiles, isLValue(s2))) alias s2L = s2; else V s2L = s2; func(s1L, s2L); } void main() { CustomString b = CustomString("world!"); arFunc(CustomString("Hello"), b); writeln("Hello"); writeln(b); } If so, I probably genericize arFunc better so you can just do this: void funcImpl(ref const(CustomString) s1, ref const(CustomString) s2); alias func = arFunc!funcImpl;
Jan 18 2016
On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:One more time... Assuming: void func(const CustomString &s1, const CustomString &s2); void func(ref const(CustomString) s1, ref const(CustomString) s2); C++: func("hello", "world"); D: auto dumb_name = CustomString("hello"); auto another_dumb_name = CustomString("world"); func(dumb_name, another_dumb_name); I _hate_ this. Almost every line of my current project's non-systems code looks like this. The majority of the code I'm working with is event handlers and glue logic, which looks like this. Tons of 1 liners and glue. D code is much larger by volume, and much less readable than C++. The statement above has about a 1/8 signal to noise ratio, and this is actually understated; I have a lot of functions that take 4 strings like that! This problem extends well beyond strings, but it's a classic example. The main advantage of D is modules, slices, forward referencing and compile times, but I'm seeing trade off of much less efficient code density/brevity for those advantages. D has a meta advantage, but I'm writing C++11/14 code now which is *almost* sufficient, so that advantage is quite diminished in 2016. In general, I'm finding it hard to do anything useful in this project without C++ style implicit conversions. Compared to C++ code, I'm finding D becomes riddled with explicit constructor calls and terrible stack variable names where C++ implicit construction/conversion would normally kick in. This becomes more awkward in some generic function situations, but it's especially painful (queue broken record) passing such rvalues to ref-args. There is truly nothing else in D that has caused so much unrelenting grief as not being able to pass an rvalue to ref const(T). If we are never to get a scope-like solution, then consider supporting C++ style rval->const ref, as a pure practicality. It's been long enough, like, 7 years or something I've been waiting. So, where are we heading with this? I raise this a couple of times a year. In 6 years, after a lot of talk (and various rejected proposals), as far as I can tell, we aren't any closer to a plan. In my experience, this has always been and remains the biggest practical annoyance writing D code, _by far_. It affects a very high number of my lines of code, of all kinds. What I don't get is, why does this seem to be unique to me? Perhaps it's because one common thread among almost all my D applications, is that I'm working together with C/C++. I can't transition to D unless I can work effectively against existing/established code. That's all I've been trying to do for this past 6-7 years, and I'm yet to successfully produced an acceptable transition path in my years of trying. This remains a very significant contributor to that failure. How are we going to resolve this? Nobody will want to transition if their code gets plainly worse, from a basic practical standpoint.There was this pull request which implemented `auto ref` for non-template functions: https://github.com/D-Programming-Language/dmd/pull/4717 But it was closed. I can't remember the exact reason why.
Jan 18 2016
That is mine. I closed it after it was more or less abandoned.
Jan 18 2016
On Monday, 18 January 2016 at 18:03:34 UTC, Namespace wrote:That is mine. I closed it after it was more or less abandoned.Yeah.. I was initially for this proposal/PR, but on top of the fact that it will cause confusion because of how it differs from the template auto ref, it simply shouldn't be required at all. The rationale for not allowing temporaries to be passed as ref params, IIRC, had two parts: 1) passing by ref should mean that the callee is meant to modify the parameter 2) the callee may escape the ref parameter which would be unsafe I really don't feel the need to reiterate how broken the above logic is, as it's been stated so many times before, and I think it should really be as simple as this: struct S; void func(ref S s); func(S()); // FINE void func(ref S s) safe; func(S()); // ERROR Bit
Jan 18 2016
On Monday, 18 January 2016 at 19:32:19 UTC, bitwise wrote:struct S; void func(ref S s); func(S()); // FINE void func(ref S s) safe; func(S()); // ERRORIsn't that backwards? I mean, safe functions can't escape their parameters, so whether or not it is a temporary shouldn't matter to a safe function. Meanwhile, non- safe *can* escape parameters, and would fail or at least lead to problems if it tried to escape a ref to a temporary. On the other hand, banning safe code from passing a temporary as a ref parameter, while allowing it in non- safe code makes a bit more sense to me, but seems less desirable.
Jan 18 2016
On Monday, 18 January 2016 at 21:39:09 UTC, Anon wrote:On Monday, 18 January 2016 at 19:32:19 UTC, bitwise wrote:It turns out, you're right, but this only makes arguments against passing rvalues to ref params even _less_ valid. You could simply allow rvalue->ref implicit instantiation right now, and safe code would still be safe, and unsafe code would be more convenient. safety seems like a very specific concern. Many people just won't need that kind of guarantee. Some will be perfectly happy ensuring the safety of their own code, while others simply won't care if their code is totally safe because they're writing low risk or very simple software. Bitstruct S; void func(ref S s); func(S()); // FINE void func(ref S s) safe; func(S()); // ERRORIsn't that backwards? I mean, safe functions can't escape their parameters, so whether or not it is a temporary shouldn't matter to a safe function. Meanwhile, non- safe *can* escape parameters, and would fail or at least lead to problems if it tried to escape a ref to a temporary. On the other hand, banning safe code from passing a temporary as a ref parameter, while allowing it in non- safe code makes a bit more sense to me, but seems less desirable.
Jan 18 2016
On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:One more time... Assuming: void func(const CustomString &s1, const CustomString &s2); void func(ref const(CustomString) s1, ref const(CustomString) s2); C++: func("hello", "world"); D: auto dumb_name = CustomString("hello"); auto another_dumb_name = CustomString("world"); func(dumb_name, another_dumb_name);Actually, I was way overthinking things. Does *this* do what you want? import std.stdio; struct CustomString { this(string data) { this.data = data; } string data; alias data this; } void func(ref CustomString s1, ref CustomString s2) { writeln(s1); writeln(s2); s2 = "universe!"; } pragma(inline, true) void arFunc(T, V)(auto ref T s1, auto ref V s2) { func(s1, s2); } void main() { CustomString b = CustomString("world!"); arFunc(CustomString("Hello"), b); writeln("Hello"); writeln(b); } Again, I can probably automate generation of the wrapper easily enough.
Jan 18 2016
On Monday, 18 January 2016 at 18:08:31 UTC, tsbockman wrote:Again, I can probably automate generation of the wrapper easily enough.Genericized: template acceptRVals(alias func) { private: import std.traits : arity; alias impl = acceptRVals!(arity!func); public: alias acceptRVals = impl!func; } template acceptRVals(size_t arity) { private enum mixStr = function() { import std.conv : to; string ctParams = ""; string rtParams = ""; string callArgs = ""; foreach(size_t a; 0 .. arity) { string aStr = a.to!string; ctParams ~= "T" ~ aStr; rtParams ~= "auto ref T" ~ aStr ~ " a" ~ aStr; callArgs ~= "a" ~ aStr; if(a < (arity - 1)) { ctParams ~= ", "; rtParams ~= ", "; callArgs ~= ", "; } } return "pragma(inline, true) auto acceptRVals(" ~ ctParams ~ ")(" ~ rtParams ~ ") { return func(" ~ callArgs ~ "); }"; }(); template acceptRVals(alias func) { mixin(mixStr); } } struct CustomString { this(string data) { this.data = data; } string data; alias data this; } import std.stdio; alias func = acceptRVals!(function(ref CustomString s1, ref CustomString s2) { writeln(s1); writeln(s2); s2 = "universe!"; }); void main() { CustomString b = CustomString("world!"); func(CustomString("Hello"), b); writeln("Hello"); writeln(b); } (I'm sure there are various corner cases not handled properly by this; obviously it would be nice if this was just handled automatically by the compiler like it should be.)
Jan 18 2016
On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:One more time... Assuming: void func(const CustomString &s1, const CustomString &s2); void func(ref const(CustomString) s1, ref const(CustomString) s2); C++: func("hello", "world"); D: auto dumb_name = CustomString("hello"); auto another_dumb_name = CustomString("world"); func(dumb_name, another_dumb_name);Seems like a template function wrapper could add the temporaries and do implicit conversions by constructing CustomStrings from string literals as needed by func: manuCall!func("hello", "world"); Maybe not ideal, but better than the quoted D code.
Jan 18 2016
On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:[...]https://github.com/D-Programming-Language/phobos/pull/3937
Jan 18 2016
On Tuesday, 19 January 2016 at 00:11:45 UTC, tsbockman wrote:On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:Is this like...a sarcastic pull request? You can't actually expect people to write code like this just to have their functions take rvalues.. Bit[...]https://github.com/D-Programming-Language/phobos/pull/3937
Jan 18 2016
On Tuesday, 19 January 2016 at 03:01:55 UTC, bitwise wrote:On Tuesday, 19 January 2016 at 00:11:45 UTC, tsbockman wrote:It's ten times easier to write code that way, than the way Manu complained about in the OP. Manu's been trying to convince Walter to allow a compiler fix through for over six years (https://github.com/D-Programming-Language/dmd/pull/4717#issu comment-116182064); it's not working. If you want to, you can just sit there making nasty comments because it's not an ideal solution. But, my pull request is something practical that can make things easier for people who just want to write computer programs. I expect this will be much easier to actually get merged, and I'll be happy to see it deprecated whenever `scope` finally gets implemented.On Monday, 18 January 2016 at 15:36:09 UTC, Manu wrote:Is this like...a sarcastic pull request? You can't actually expect people to write code like this just to have their functions take rvalues.. Bit[...]https://github.com/D-Programming-Language/phobos/pull/3937
Jan 18 2016
On Tuesday, 19 January 2016 at 03:37:17 UTC, tsbockman wrote:It's ten times easier to write code that way, than the way Manu complained about in the OP.To clarify: 1) If `scope` were implemented, Manu's example would look like this: // Declaration void func(in CustomString s1, in CustomString s2); // Whenever rvalues need to be passed: func("hello", "world"); 2) With my PR, it looks like this: // Declaration private void funcImpl(ref const(CustomString) s1, ref const(CustomString) s2); mixin acceptRVals!("func", funcImpl); // Whenever rvalues need to be passed: func("hello", "world"); 3) Currently, we have this: // Declaration void func(ref const(CustomString) s1, ref const(CustomString) s2); // Whenever rvalues need to be passed; auto temp1 = "hello"; auto temp2 = "world"; func(temp1, temp2); If A is the number of such functions, B is the number of `ref` arguments per function, and C is the number of calls where rvalues should be passed: (2) Requires A more statements than (1). (3) Requires B*C more statements than (1). Obviously there is little reason to complain about any of this unless B >= 1 and C > A, so unless I'm missing something, my PR is a large improvement over the status quo.
Jan 18 2016
On Tuesday, 19 January 2016 at 04:27:12 UTC, tsbockman wrote:On Tuesday, 19 January 2016 at 03:37:17 UTC, tsbockman wrote:Sorry if that seemed mean, but it wasn't meant to be insulting. But while your solution is clever, I find it totally unrealistic. Why would anyone use it when they can just templatize their function and get exactly the same thing? struct S{} void foo(ref const(S) s) {} becomes void foo()(auto ref const(S) s) {} Not to mention the fact that people's first reaction to D's ref params not taking rvalues isn't going to be to look in the standard library. Finally, this situation simply should not be this complicated. A ref param should accept an rvalue. safety is a specific concern, and unless I'm annotating my code with safe, I should be able to write it however I want(within reason). To quote a famous author: "Sometimes, an entire community can miss a point". This is one of those points. Most of my reaction is to the fact that this is actually a problem. Sorry I offended you. BitIt's ten times easier to write code that way, than the way Manu complained about in the OP.To clarify: 1) If `scope` were implemented, Manu's example would look like this: // Declaration void func(in CustomString s1, in CustomString s2); // Whenever rvalues need to be passed: func("hello", "world"); 2) With my PR, it looks like this: // Declaration private void funcImpl(ref const(CustomString) s1, ref const(CustomString) s2); mixin acceptRVals!("func", funcImpl); // Whenever rvalues need to be passed: func("hello", "world"); 3) Currently, we have this: // Declaration void func(ref const(CustomString) s1, ref const(CustomString) s2); // Whenever rvalues need to be passed; auto temp1 = "hello"; auto temp2 = "world"; func(temp1, temp2); If A is the number of such functions, B is the number of `ref` arguments per function, and C is the number of calls where rvalues should be passed: (2) Requires A more statements than (1). (3) Requires B*C more statements than (1). Obviously there is little reason to complain about any of this unless B >= 1 and C > A, so unless I'm missing something, my PR is a large improvement over the status quo.
Jan 18 2016
On Tuesday, 19 January 2016 at 05:43:57 UTC, bitwise wrote:Sorry if that seemed mean, but it wasn't meant to be insulting. But while your solution is clever, I find it totally unrealistic. Why would anyone use it when they can just templatize their function and get exactly the same thing? struct S{} void foo(ref const(S) s) {} becomes void foo()(auto ref const(S) s) {}That has fundamentally different semantics from my PR, and does not solve Manu's problem at all. For example, this: int foo()(auto ref int x) { return x + 1; } Is actually a template with two possible instantiations (that's why `auto ref` is disallowed on non-template functions): // lvalues are passed by reference: int foo(ref int x) { return x + 1; } // rvalues are passed by value: int foo(int x) { return x + 1; } There are several problems with this: 1) It introduces substantial template bloat, as the number of instantiations of the entire function - including the body! - scales as the square of the number of `auto ref` parameters. 2) rvalues will be passed by value, which could be slow if the type is bulkier than `int`. 3) `auto ref` CANNOT be used on an extern(C++) function, because the rvalue calls won't link! By marking the wrapper `pragma(inline, true)` and forwarding everything to the all `ref` version of the function, my PR mostly solves (1), and entirely solves (2) and (3).Not to mention the fact that people's first reaction to D's ref params not taking rvalues isn't going to be to look in the standard library. Finally, this situation simply should not be this complicated. A ref param should accept an rvalue. safety is a specific concern, and unless I'm annotating my code with safe, I should be able to write it however I want(within reason). To quote a famous author: "Sometimes, an entire community can miss a point". This is one of those points. Most of my reaction is to the fact that this is actually a problem. Sorry I offended you. BitI understand, but please don't take it out on me. I have no more control over what gets into the compiler than you do.
Jan 18 2016
On Tuesday, 19 January 2016 at 06:17:17 UTC, tsbockman wrote:1) It introduces substantial template bloat, as the number of instantiations of the entire function - including the body! - scales as the square of the number of `auto ref` parameters.Oops - I was being a little dyslexic here. It's actually much worse than that: not N^2, but 2^N.
Jan 18 2016
On Tuesday, 19 January 2016 at 06:17:17 UTC, tsbockman wrote:On Tuesday, 19 January 2016 at 05:43:57 UTC, bitwise wrote:Your solution suffers from exactly the same problem. It still uses auto ref.[..]There are several problems with this: 1) It introduces substantial template bloat, as the number of instantiations of the entire function - including the body! - scales as the square of the number of `auto ref` parameters.2) rvalues will be passed by value, which could be slow if the type is bulkier than `int`.No, they won't. Temporaries will be created for rvalues, and lvalues will be passed by ref.3) `auto ref` CANNOT be used on an extern(C++) function, because the rvalue calls won't link!This is the _one_ advantage that your solution actually has over simply templatizing the function. You are still missing the point though. This shouldn't even be a problem in the first place. It's faulty language design. This limitation makes no sense, and should be removed. There is no argument anyone can make that isn't totally broken. Having ref params not take rvalues doesn't make the language any safer or more intuitive at all. If rvalues were allowed to be passed to ref params, the temporaries would be constructed on the stack right before the function call. It's already possible to have variables on the stack and pass them to ref params. There is no difference. In terms of conveying intention to the caller, just make the param const and you're done. Finally, for a language that is nearly 1:1 compatible with C++ in many areas, people will expect familiar semantics. There is no real reason to deviate here. At the very least, extern(C++) functions with ref params could take rvalues. Bit
Jan 19 2016
On Tuesday, 19 January 2016 at 17:23:33 UTC, bitwise wrote:On Tuesday, 19 January 2016 at 06:17:17 UTC, tsbockman wrote:You seem to have missed the significance of the "including the body!" part. Directly using `auto ref` results in all the code in THE BODY of the function being recompiled once *per instantiation*. Mine just recompiles THE WRAPPER, which is tiny and force inlined, and therefore should not bloat the generated binary at all. It will still slow down compilation a bit, but nowhere near as much as recompiling an arbitrarily large function body 2^N times.On Tuesday, 19 January 2016 at 05:43:57 UTC, bitwise wrote:Your solution suffers from exactly the same problem. It still uses auto ref.[..]There are several problems with this: 1) It introduces substantial template bloat, as the number of instantiations of the entire function - including the body! - scales as the square of the number of `auto ref` parameters.Whether a name is attached to it or not, a temporary will be created on the stack in the calling function. My wrapper passes a pointer to that stack location to the actual function implementation, rather than copying it into the stack frame of the function being called. This allows the same generated code to be used for the function, regardless of whether an rvalue or lvalue is passed.2) rvalues will be passed by value, which could be slow if the type is bulkier than `int`.No, they won't. Temporaries will be created for rvalues, and lvalues will be passed by ref.You are obviously confused about either about how template instantiation works in D, or about the mechanics of pass-by-ref versus pass-by-value. I'm not sure which.3) `auto ref` CANNOT be used on an extern(C++) function, because the rvalue calls won't link!This is the _one_ advantage that your solution actually has over simply templatizing the function.You are still missing the point though. This shouldn't even be a problem in the first place. It's faulty language design. This limitation makes no sense, and should be removed. There is no argument anyone can make that isn't totally broken.I have no idea why you keep trying to argue with me about the language design. I already agreed it would be better to just directly support passing rvalues to `ref` (or preferably, `scope`) parameters in the compiler. But again, I have ZERO control over this. I am not the one you need to convince - Walter and Andrei are. The fact that *I know* that I'm not in charge of the language design does not mean I am "missing the point".
Jan 19 2016
On Tuesday, 19 January 2016 at 17:48:24 UTC, tsbockman wrote:You are obviously confused about either about how template instantiation works in D, or about the mechanics of pass-by-ref versus pass-by-value. I'm not sure which.You are confused. You don't seem to be able to distinguish between indifference and lack of knowledge. I'm not here to analyze the finer points of you wrapper thingy that no one will ever use.I have no idea why you keep trying to argue with me about the language design. I already agreed it would be better to just directly support passing rvalues to `ref` (or preferably, `scope`) parameters in the compiler. But again, I have ZERO control over this. I am not the one you need to convince - Walter and Andrei are.We need a consensus, not one person to convince Walter or Andrei. The more people that get on board with this, the more likely it is to actually get fixed. You don't have ZERO control over it, you have one vote. The more that people try and hack their way around this problem, instead of speaking up about it, the less likely it is to get fixed. Bit
Jan 19 2016
On Tuesday, 19 January 2016 at 18:03:05 UTC, bitwise wrote:I'm not here to analyze the finer points of you wrapper thingy that no one will ever use.It's not a "finer point". This isn't really even about my wrapper at this point. Why should anyone listen to your demands for changes to the language, when you don't even understand how the relevant features work now?
Jan 19 2016
On Tuesday, 19 January 2016 at 18:18:30 UTC, tsbockman wrote:On Tuesday, 19 January 2016 at 18:03:05 UTC, bitwise wrote:It's not that I don't understand, I just don't care to convince YOU that I do. BitI'm not here to analyze the finer points of you wrapper thingy that no one will ever use.It's not a "finer point". This isn't really even about my wrapper at this point. Why should anyone listen to your demands for changes to the language, when you don't even understand how the relevant features work now?
Jan 19 2016
On Tuesday, 19 January 2016 at 18:28:28 UTC, bitwise wrote:It's not that I don't understand, I just don't care to convince YOU that I do. BitSo because you "don't care" -> you argue with me about what my own code does. Because you DO "understand" -> you give a point-by-point criticism that's completely wrong.
Jan 19 2016
On Tuesday, 19 January 2016 at 17:23:33 UTC, bitwise wrote:On Tuesday, 19 January 2016 at 06:17:17 UTC, tsbockman wrote:As a simple example, consider the following: void main() { func(5); int n = 6; func(n); } Defining `func` by directly using `auto ref`, this: void func()(auto ref int x) { enum set_at_compile_time = __traits(isRef, x); writeln(set_at_compile_time); } Will be compiled into two separate functions: void func1(int x) // pass by value { writeln(false); } void func2(ref int x) // pass by ref { writeln(true); } void main() { func1(5); // prints false int n = 6; func2(n); // prints true } (Try it here: http://dpaste.dzfl.pl/dc9af2059641) Whereas using my PR: void funcImpl(ref int x) { writeln(__traits(isRef, x)); } mixin acceptRVals!("func", funcImpl); It's effectively just one function: void funcImpl(ref int x) { writeln(true); } void main() { int x = 5; funcImpl(x); // prints true int n = 6; funcImpl(n); // prints true } Note that the output IS NOT THE SAME. (Try it yourself: http://dpaste.dzfl.pl/9ae30506b4a3) If you don't understand why, then you have no business trying to dictate how the language should handle rvalues. You also don't fully understand why Manu's not satisfied with just using `auto ref` directly.1) It introduces substantial template bloat, as the number of instantiations of the entire function - including the body! - scales as the square of the number of `auto ref` parameters.Your solution suffers from exactly the same problem. It still uses auto ref.2) rvalues will be passed by value, which could be slow if the type is bulkier than `int`.No, they won't. Temporaries will be created for rvalues, and lvalues will be passed by ref.
Jan 19 2016
On 01/19/2016 06:43 AM, bitwise wrote:Finally, this situation simply should not be this complicated. A ref param should accept an rvalue. safety is a specific concern, and unless I'm annotating my code with safe, I should be able to write it however I want(within reason). To quote a famous author: "Sometimes, an entire community can miss a point". This is one of those points.It actually isn't.
Jan 19 2016
On Tuesday, 19 January 2016 at 18:30:26 UTC, Timon Gehr wrote:On 01/19/2016 06:43 AM, bitwise wrote:Clearly, it is =) BitFinally, this situation simply should not be this complicated. A ref param should accept an rvalue. safety is a specific concern, and unless I'm annotating my code with safe, I should be able to write it however I want(within reason). To quote a famous author: "Sometimes, an entire community can miss a point". This is one of those points.It actually isn't.
Jan 19 2016
On 01/19/2016 07:43 PM, bitwise wrote:On Tuesday, 19 January 2016 at 18:30:26 UTC, Timon Gehr wrote:The point isn't particularly original. It's come up in most sufficiently long threads about the issue. Also, you seem to think that you don't miss the point and you are part of the community. It isn't a useful quote.On 01/19/2016 06:43 AM, bitwise wrote:Clearly, it is =) BitFinally, this situation simply should not be this complicated. A ref param should accept an rvalue. safety is a specific concern, and unless I'm annotating my code with safe, I should be able to write it however I want(within reason). To quote a famous author: "Sometimes, an entire community can miss a point". This is one of those points.It actually isn't.
Jan 19 2016
On Tuesday, 19 January 2016 at 18:57:03 UTC, Timon Gehr wrote:On 01/19/2016 07:43 PM, bitwise wrote:On Tuesday, 19 January 2016 at 18:30:26 UTC, Timon Gehr wrote:On 01/19/2016 06:43 AM, bitwise wrote:Clearly, it is =) BitFinally, this situation simply should not be this complicated. A ref param should accept an rvalue. safety is a specific concern, and unless I'm annotating my code with safe, I should be able to write it however I want(within reason). To quote a famous author: "Sometimes, an entire community can miss a point". This is one of those points.It actually isn't.The point isn't particularly original. It's come up in most sufficiently long threads about the issue.I would argue that there is no sufficient length for this kind of thread. The D community will(hopefully) continue to absorb new users regularly, and there may come a point where the balance tips enough to get this fixed. Bit
Jan 19 2016