digitalmars.D.learn - nested inout return type
- Simon =?UTF-8?B?QsO8cmdlcg==?= (15/15) Jun 13 2016 I'm writing a custom (originally multi-dimensional) Slice-type,
- Era Scarecrow (8/15) Jun 13 2016 Hmmm. Wouldn't just returning an inout of the Slice work?
- Era Scarecrow (10/14) Jun 13 2016 Seems the pointer has to be force-cast back to a normal pointer
- Simon =?UTF-8?B?QsO8cmdlcg==?= (17/31) Jun 14 2016 Then instead of Slice!(const(T)) one would use const(Slice!T).
- Steven Schveighoffer (11/33) Jun 14 2016 Yes, this is a missing piece of the language. In order to use custom
- Simon =?UTF-8?B?QsO8cmdlcg==?= (17/23) Jun 14 2016 Hm, you are right, in fact it doesn't work. Somehow it seemed to
- Era Scarecrow (13/16) Jun 14 2016 Of course... My amateur D-fu skills show themselves. cast()
- Steven Schveighoffer (17/27) Jun 14 2016 It's mostly akin to immutable (which would require similar syntax). It's...
- Era Scarecrow (19/23) Jun 14 2016 For the longest time I didn't have internet consistently, so I
I'm writing a custom (originally multi-dimensional) Slice-type, analogous to the builtin T[], and stumbled upon the problem that the following code won't compile. The workaround is simple: just write the function three times for mutable/const/immutable. But as "inout" was invented to make that unneccessary I was wondering if there is a clever way to make this work. struct Slice(T) { T* ptr; size_t length; Slice!(inout(T)) opSlice(size_t a, size_t b) inout { return Slice!(inout(T))(ptr+a, b-a); } }
Jun 13 2016
On Monday, 13 June 2016 at 22:31:00 UTC, Simon Bürger wrote:But as "inout" was invented to make that unneccessary I was wondering if there is a clever way to make this work. <snip> Slice!(inout(T)) opSlice(size_t a, size_t b) inout { return Slice!(inout(T))(ptr+a, b-a); }Hmmm. Wouldn't just returning an inout of the Slice work? Otherwise you'll get inner template instantiation and that can be annoying inout(Slice) opSlice(size_t a, size_t b) inout { return cast(inout(Slice)) Slice(ptr+a, b-a); }
Jun 13 2016
On Monday, 13 June 2016 at 23:51:40 UTC, Era Scarecrow wrote:inout(Slice) opSlice(size_t a, size_t b) inout { return cast(inout(Slice)) Slice(ptr+a, b-a); }Seems the pointer has to be force-cast back to a normal pointer so the constructor can work. (Because the function is inout, ptr becomes inout(T*) ) return cast(inout(Slice)) Slice(cast(T*)ptr+a, b-a); Beyond that it works as expected :) Writeln gives the following output on Slice with opSlices: Slice!int(18FD60, 10) const(Slice!int)(18FD60, 10) immutable(Slice!int)(18FD90, 10)
Jun 13 2016
On Tuesday, 14 June 2016 at 01:50:17 UTC, Era Scarecrow wrote:On Monday, 13 June 2016 at 23:51:40 UTC, Era Scarecrow wrote:Then instead of Slice!(const(T)) one would use const(Slice!T). Then there is no analogue of the following: const(T)[] s = ... s = s[5..7] which is quite common when parsing strings for example. Still, might be the cleanest approach. However I found another solution for now without using any "inout": * only do one mutable version of opSlice * add implicit cast (using "alias this") for const(Slice!T) -> Slice!(const(T)). So when trying to opSlice on a const it will first cast to a mutable-slice-of-const-elements and then do the slice. This is closer to the behavior of "const(T[])", though it might have issues when using immutable and not only const. Not sure. Anyway, thanks for the help, and if someone cares, the full resulting code is on github.com/Krox/jive/blob/master/jive/array.dinout(Slice) opSlice(size_t a, size_t b) inout { return cast(inout(Slice)) Slice(ptr+a, b-a); }Seems the pointer has to be force-cast back to a normal pointer so the constructor can work. (Because the function is inout, ptr becomes inout(T*) ) return cast(inout(Slice)) Slice(cast(T*)ptr+a, b-a); Beyond that it works as expected :) Writeln gives the following output on Slice with opSlices: Slice!int(18FD60, 10) const(Slice!int)(18FD60, 10) immutable(Slice!int)(18FD90, 10)
Jun 14 2016
On 6/14/16 9:22 AM, Simon Bürger wrote:On Tuesday, 14 June 2016 at 01:50:17 UTC, Era Scarecrow wrote:Better: inout(Slice)(ptr+a, b-a);On Monday, 13 June 2016 at 23:51:40 UTC, Era Scarecrow wrote:inout(Slice) opSlice(size_t a, size_t b) inout { return cast(inout(Slice)) Slice(ptr+a, b-a); }Seems the pointer has to be force-cast back to a normal pointer so the constructor can work. (Because the function is inout, ptr becomes inout(T*) ) return cast(inout(Slice)) Slice(cast(T*)ptr+a, b-a);Then instead of Slice!(const(T)) one would use const(Slice!T). Then there is no analogue of the following: const(T)[] s = ... s = s[5..7]Yes, this is a missing piece of the language. In order to use custom types, you must give up tail modifiers.which is quite common when parsing strings for example. Still, might be the cleanest approach. However I found another solution for now without using any "inout": * only do one mutable version of opSlice * add implicit cast (using "alias this") for const(Slice!T) -> Slice!(const(T)).Interesting, but unfortunately, the compiler isn't eager about this conversion. auto x = s[5 .. 7] isn't going to give you a Slice!(const(T)), like an array would. But I like the idea. And of course, there is the issue of not allowing structs with inout members. So really you need to triplicate the function for all the modifiers. And of course, alias this can only be used once... -Steve
Jun 14 2016
On Tuesday, 14 June 2016 at 14:47:11 UTC, Steven Schveighoffer wrote:Hm, you are right, in fact it doesn't work. Somehow it seemed to in my usecase. Well, triplicate it is then. Which isn't that bad using something like auto opSlice(size_t a, size_t b) { // actual non-trivial code } auto opSlice(size_t a, size_t b) const { return Slice!(const(T))(ptr, length).opSlice(a,b); } auto opSlice(size_t a, size_t b) immutable { return Slice!(immutable(T))(ptr, length).opSlice(a,b); }* only do one mutable version of opSlice * add implicit cast (using "alias this") for const(Slice!T) -> Slice!(const(T)).Interesting, but unfortunately, the compiler isn't eager about this conversion. auto x = s[5 .. 7] isn't going to give you a Slice!(const(T)), like an array would. But I like the idea.
Jun 14 2016
On Tuesday, 14 June 2016 at 14:47:11 UTC, Steven Schveighoffer wrote:Of course... My amateur D-fu skills show themselves. cast() const() immutable() are the same, why not inout? Hmmm... Reminds me when I didn't understand how to get the address or use pointers correctly, so I'd do stuff like &ptr[i] everywhere because no one told me a better way to do it. I also remember seeing odd issues and bugs in C when using a char and then having negative numbers so having to use & 0xff flags everywhere until I added the _unsigned_ keyword in. I feel like a tutorial for common problems and solutions should be present for C, C++ & D. Then again maybe that's some cookbooks that I haven't purchased/read yet.On Tuesday, 14 June 2016 at 01:50:17 UTC, Era Scarecrow wrote:Better: inout(Slice)(ptr+a, b-a);return cast(inout(Slice)) Slice(cast(T*)ptr+a, b-a);
Jun 14 2016
On 6/14/16 3:38 PM, Era Scarecrow wrote:On Tuesday, 14 June 2016 at 14:47:11 UTC, Steven Schveighoffer wrote:It's mostly akin to immutable (which would require similar syntax). It's because once constructed, inout-flavored wrappers cannot change anything internally. So you have to do it all at once. const is different, because you can construct mutable, and then simply cast to const when you feel like it. But of course, if the components you are using to construct are already flavored, you have no choice. All-at-once construction is the only way without casting.Of course... My amateur D-fu skills show themselves. cast() const() immutable() are the same, why not inout? Hmmm...On Tuesday, 14 June 2016 at 01:50:17 UTC, Era Scarecrow wrote:Better: inout(Slice)(ptr+a, b-a);return cast(inout(Slice)) Slice(cast(T*)ptr+a, b-a);I feel like a tutorial for common problems and solutions should be present for C, C++ & D. Then again maybe that's some cookbooks that I haven't purchased/read yet.For a long time I have been working on an article to talk about the quirks/tricks of inout. I gave a talk at dconf, but there are more things to show than are possible in a spoken talk. I honestly think the best place to go figure these things out is stackoverflow (or just the internet in general). Whenever I have a technical problem I can't figure out (or am too lazy to diagnose myself), I search and SO usually gives me an answer :) -Steve
Jun 14 2016
On Tuesday, 14 June 2016 at 19:48:06 UTC, Steven Schveighoffer wrote:I honestly think the best place to go figure these things out is stackoverflow (or just the internet in general). Whenever I have a technical problem I can't figure out (or am too lazy to diagnose myself), I search and SO usually gives me an answer :)For the longest time I didn't have internet consistently, so I often had to figure these things out solo and alone. Honestly I'm still new to figuring out where things are on the internet, or what I need and don't need. Doesn't help being self taught means I don't know some of the lingo. What is map? What does reduce do? What's a HashMap? These things by themselves (to someone relatively new) doesn't make sense, and the STL and C++ seem to actively push me away from understanding it so I dropped them wholesale. The only libraries that made sense and I would rely on were the bare minimum core library ones included in the '88 CPL including bare minimum string and IO functions. Perhaps that's why I'm still shy about learning some of the libraries and understanding some of the more ingenious solutions that can be written in a couple lines rather than building my own solution which is clunky (but better than C++). Although I'm doing better than I used to, it's still a chore. :(
Jun 14 2016