Thread overview | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 23, 2018 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 |
July 23, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | 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 |
July 23, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | 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 :(
|
July 23, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | 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?
|
July 23, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | 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 |
July 24, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | 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?
|
July 24, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timoses | 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 |
July 25, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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!
|
July 27, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | 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
|
July 28, 2018 Re: How to avoid inout type constructor with Optional type wrapper undoing string type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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.
|
Copyright © 1999-2021 by the D Language Foundation