Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On Sunday, 29 July 2018 at 12:30:58 UTC, Steven Schveighoffer wrote: On 7/28/18 6:06 PM, aliak wrote: [...] What I meant was that string is actually mutable (the data isn't mutable, but the string can be re-assigned to another one), so Optional!string is more useful than immutable(Optional!(char[])). I shouldn't have said that immutable(Optional!T) is useless, you are right, and it wouldn't make sense for the defined flag to change there anyway. [...] Ah right. So it seems inout is removing head qualifiers on by-val parameters? Filed what I think I understood from this: https://issues.dlang.org/show_bug.cgi?id=19125
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On 7/28/18 6:06 PM, aliak wrote: On Friday, 27 July 2018 at 14:52:20 UTC, Steven Schveighoffer wrote: On 7/23/18 2:39 PM, aliak wrote: Hi, I'm playing around with an Optional wrapper type. It stores a type T and a bool that defines whether a value is defined or not: struct Optional(T) { T value; bool defined = false; this(U : T)(auto ref inout(U) value) inout { this.value = value; this.defined = true; } } Don't use inout here. The point of inout on the constructor is to *transfer* the mutability of the parameter to the struct instance. But you want to simply copy the type into the struct (an immutable(Optional!T) is quite useless, no?) Just use U, not inout(U), and don't put inout on the constructor. But then it only works for mutable Optional right? Why would an immutable(Optional!T) be useless? Data can be "forever" empty or a certain value. What I meant was that string is actually mutable (the data isn't mutable, but the string can be re-assigned to another one), so Optional!string is more useful than immutable(Optional!(char[])). I shouldn't have said that immutable(Optional!T) is useless, you are right, and it wouldn't make sense for the defined flag to change there anyway. But I see a problem here. string *is* mutable, yet, the parameter is accepted as inout(char[]). This seems unreasonable, I may want to preserve the head mutability. I didn't realize IFTI would do this. May be a bug, but I'm not certain. But you have it as auto ref, which means since you only sent in rvalues of strings, you didn't test the ref-ness of it. Indeed, if you do: string s = "hello"; auto a = defined(s); you get what you expected! This doesn't make a whole lot of sense. I wouldn't expect different types using IFTI this way. I'd recommend filing a bug on inout and IFTI. There isn't a good way around this... -Steve
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On Friday, 27 July 2018 at 14:52:20 UTC, Steven Schveighoffer wrote: On 7/23/18 2:39 PM, aliak wrote: Hi, I'm playing around with an Optional wrapper type. It stores a type T and a bool that defines whether a value is defined or not: struct Optional(T) { T value; bool defined = false; this(U : T)(auto ref inout(U) value) inout { this.value = value; this.defined = true; } } Don't use inout here. The point of inout on the constructor is to *transfer* the mutability of the parameter to the struct instance. But you want to simply copy the type into the struct (an immutable(Optional!T) is quite useless, no?) Just use U, not inout(U), and don't put inout on the constructor. -Steve But then it only works for mutable Optional right? Why would an immutable(Optional!T) be useless? Data can be "forever" empty or a certain value.
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On 7/23/18 2:39 PM, aliak wrote: Hi, I'm playing around with an Optional wrapper type. It stores a type T and a bool that defines whether a value is defined or not: struct Optional(T) { T value; bool defined = false; this(U : T)(auto ref inout(U) value) inout { this.value = value; this.defined = true; } } Don't use inout here. The point of inout on the constructor is to *transfer* the mutability of the parameter to the struct instance. But you want to simply copy the type into the struct (an immutable(Optional!T) is quite useless, no?) Just use U, not inout(U), and don't put inout on the constructor. -Steve
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On Tuesday, 24 July 2018 at 14:11:51 UTC, Ali Çehreli wrote: On 07/24/2018 02:47 AM, Timoses wrote: > Why does this fail while it works when replacing T with U in struct > W(T)?? It's so odd. Both T and U seem to resolve to "string". > > struct W(T) { > const T value; > // Replacing `T value` with `U value` compiles > this(U : T)(auto ref const T value) { That means, "any U that can implicitly be converted to string". However, when U does not appear in the function parameter list, there is no way for the compiler to deduce U. (I don't think there is syntax to specify constructor template parameters explicitly.) And if the parameter is always T, why is the constructor a template? Ok, perhaps U is used inside the constructor and the programmer needs to specify it... Still, I don't think there is such syntax. Ali Ah, thanks!
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On 07/24/2018 02:47 AM, Timoses wrote: > Why does this fail while it works when replacing T with U in struct > W(T)?? It's so odd. Both T and U seem to resolve to "string". > > struct W(T) { > const T value; > // Replacing `T value` with `U value` compiles > this(U : T)(auto ref const T value) { That means, "any U that can implicitly be converted to string". However, when U does not appear in the function parameter list, there is no way for the compiler to deduce U. (I don't think there is syntax to specify constructor template parameters explicitly.) And if the parameter is always T, why is the constructor a template? Ok, perhaps U is used inside the constructor and the programmer needs to specify it... Still, I don't think there is such syntax. Ali
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On Monday, 23 July 2018 at 18:39:59 UTC, aliak wrote: Hi, I'm playing around with an Optional wrapper type. It stores a type T and a bool that defines whether a value is defined or not: struct Optional(T) { T value; bool defined = false; this(U : T)(auto ref inout(U) value) inout { this.value = value; this.defined = true; } } To facilitate it's use I have two type constructors: inout(Optional!T) some(T)(auto ref inout(T) value) { return inout(Optional!T)(value); } Optional!T no(T)() { return Optional!T(); } The above produces a problem when working with strings. Basically the type information gets slightly altered so you can't do this: auto a = [no!string, some("hello")]; You get a type mismatch: * no!string = Optional!string * some("hello") = immutable(Optional!(char[])) I've created a short code gist, so basically I'm wondering how to get it to compile without changing what's in main() https://run.dlang.io/is/BreNdZ I guess I can specialize on string type T, but this is a more general problem that can be shown with: struct S {} alias Thing = immutable S; Thing thing = S(); auto x = some(thing); auto y = no!Thing; auto arr = [x, y]; // no can do buddy Cheers, - Ali I'm not being very helpful here, just throwing in more questions again: Why does this fail while it works when replacing T with U in struct W(T)?? It's so odd. Both T and U seem to resolve to "string". struct W(T) { const T value; // Replacing `T value` with `U value` compiles this(U : T)(auto ref const T value) { pragma(msg, T); // string pragma(msg, U); // string this.value = value; } } auto defined(T)(auto ref const T value) { return W!T(value); } void main() { auto a = defined("hello"); } Is this a bug?
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On Monday, 23 July 2018 at 19:31:42 UTC, aliak wrote: Ok, now I'm totally confused. Defining an extra type constructor makes everything work. I.e add a const one to the inout one: auto defined(T)(const auto ref T value) { return W!T(value); } and everything works! Can anyone say why that is? Boh, seems other problems crop up now as doing this: auto a = defined!(int*)(null); produces error: onlineapp.d(13): Error: inout constructor onlineapp.W!(int*).W.__ctor!(int*).this creates const object, not mutable onlineapp.d(30): Error: template instance `onlineapp.defined!(int*)` error instantiating https://run.dlang.io/is/BWYxA8
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On Monday, 23 July 2018 at 19:22:13 UTC, aliak wrote: On Monday, 23 July 2018 at 19:02:02 UTC, Jacob Carlborg wrote: This [1] compiles the first example but not the second. [1] https://run.dlang.io/is/SJ02kP Aye it does, but it also sets T to always const which is unfortunately impractical for my use case :( Ok, now I'm totally confused. Defining an extra type constructor makes everything work. I.e add a const one to the inout one: auto defined(T)(const auto ref T value) { return W!T(value); } and everything works! Can anyone say why that is?
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On Monday, 23 July 2018 at 19:02:02 UTC, Jacob Carlborg wrote: This [1] compiles the first example but not the second. [1] https://run.dlang.io/is/SJ02kP Aye it does, but it also sets T to always const which is unfortunately impractical for my use case :(
Re: How to avoid inout type constructor with Optional type wrapper undoing string type
On 2018-07-23 20:39, aliak wrote: Hi, I'm playing around with an Optional wrapper type. It stores a type T and a bool that defines whether a value is defined or not: struct Optional(T) { T value; bool defined = false; this(U : T)(auto ref inout(U) value) inout { this.value = value; this.defined = true; } } To facilitate it's use I have two type constructors: inout(Optional!T) some(T)(auto ref inout(T) value) { return inout(Optional!T)(value); } Optional!T no(T)() { return Optional!T(); } The above produces a problem when working with strings. Basically the type information gets slightly altered so you can't do this: auto a = [no!string, some("hello")]; You get a type mismatch: * no!string = Optional!string * some("hello") = immutable(Optional!(char[])) I've created a short code gist, so basically I'm wondering how to get it to compile without changing what's in main() https://run.dlang.io/is/BreNdZ I guess I can specialize on string type T, but this is a more general problem that can be shown with: struct S {} alias Thing = immutable S; Thing thing = S(); auto x = some(thing); auto y = no!Thing; auto arr = [x, y]; // no can do buddy This [1] compiles the first example but not the second. [1] https://run.dlang.io/is/SJ02kP -- /Jacob Carlborg
How to avoid inout type constructor with Optional type wrapper undoing string type
Hi, I'm playing around with an Optional wrapper type. It stores a type T and a bool that defines whether a value is defined or not: struct Optional(T) { T value; bool defined = false; this(U : T)(auto ref inout(U) value) inout { this.value = value; this.defined = true; } } To facilitate it's use I have two type constructors: inout(Optional!T) some(T)(auto ref inout(T) value) { return inout(Optional!T)(value); } Optional!T no(T)() { return Optional!T(); } The above produces a problem when working with strings. Basically the type information gets slightly altered so you can't do this: auto a = [no!string, some("hello")]; You get a type mismatch: * no!string = Optional!string * some("hello") = immutable(Optional!(char[])) I've created a short code gist, so basically I'm wondering how to get it to compile without changing what's in main() https://run.dlang.io/is/BreNdZ I guess I can specialize on string type T, but this is a more general problem that can be shown with: struct S {} alias Thing = immutable S; Thing thing = S(); auto x = some(thing); auto y = no!Thing; auto arr = [x, y]; // no can do buddy Cheers, - Ali