digitalmars.D.learn - opCast cannot implicitly convert a.opCast of type X to Y
- aliak (45/45) Feb 11 2018 From spec: Cast expression: "cast ( Type ) UnaryExpression"
- rumbu (3/12) Feb 12 2018 In my opinion, you should fill a documentation enhancement
- Nathan S. (2/15) Feb 13 2018 Having the result of "cast(float) a" not be a float would be evil.
- aliak (2/20) Feb 13 2018 Ya :p dunno what I was thinking.
- Meta (10/56) Feb 14 2018 I think the best way to do this is to implement `map` for your
From spec: Cast expression: "cast ( Type ) UnaryExpression" converts UnaryExpresssion to Type. And https://dlang.org/spec/operatoroverloading.html#cast makes no mention of the return type of opCast. One could think that the return type of opCast would be the return type. But it seems it must be the same as the template parameter of opCast else you get a compile error that seems like it can be much better. --- import std.stdio; struct B(T) { T t; } struct A(T) { T t; auto opCast(U)() { return B!U(cast(U)t); } } void main() { auto a = A!int(3); auto b = cast(float)a; // error } Error: cannot implicitly convert expression a.opCast() of type B!float to float Is this deliberate? The use case I have is making an optional type that you can cast to a different type: auto opCast(U)() const { static if (isOptional!U) { alias V = OptionalTarget!U; return empty ? no!V : some!V(cast(V)front); // it's a range so "front" is the raw value } else { return empty ? no!U : some!U(cast(U)front); } } It would allow for scenarios like: Optional!int a = 3; auto b = cast(float)a; // b == some!float Cheers - Ali
Feb 11 2018
On Monday, 12 February 2018 at 02:05:16 UTC, aliak wrote:From spec: Cast expression: "cast ( Type ) UnaryExpression" converts UnaryExpresssion to Type. And https://dlang.org/spec/operatoroverloading.html#cast makes no mention of the return type of opCast. One could think that the return type of opCast would be the return type. But it seems it must be the same as the template parameter of opCast else you get a compile error that seems like it can be much better. - AliIn my opinion, you should fill a documentation enhancement request on issues.dlang.org.
Feb 12 2018
On Monday, 12 February 2018 at 02:05:16 UTC, aliak wrote:struct B(T) { T t; } struct A(T) { T t; auto opCast(U)() { return B!U(cast(U)t); } } void main() { auto a = A!int(3); auto b = cast(float)a; // error }Having the result of "cast(float) a" not be a float would be evil.
Feb 13 2018
On Tuesday, 13 February 2018 at 12:12:30 UTC, Nathan S. wrote:On Monday, 12 February 2018 at 02:05:16 UTC, aliak wrote:Ya :p dunno what I was thinking.struct B(T) { T t; } struct A(T) { T t; auto opCast(U)() { return B!U(cast(U)t); } } void main() { auto a = A!int(3); auto b = cast(float)a; // error }Having the result of "cast(float) a" not be a float would be evil.
Feb 13 2018
On Monday, 12 February 2018 at 02:05:16 UTC, aliak wrote:From spec: Cast expression: "cast ( Type ) UnaryExpression" converts UnaryExpresssion to Type. And https://dlang.org/spec/operatoroverloading.html#cast makes no mention of the return type of opCast. One could think that the return type of opCast would be the return type. But it seems it must be the same as the template parameter of opCast else you get a compile error that seems like it can be much better. --- import std.stdio; struct B(T) { T t; } struct A(T) { T t; auto opCast(U)() { return B!U(cast(U)t); } } void main() { auto a = A!int(3); auto b = cast(float)a; // error } Error: cannot implicitly convert expression a.opCast() of type B!float to float Is this deliberate? The use case I have is making an optional type that you can cast to a different type: auto opCast(U)() const { static if (isOptional!U) { alias V = OptionalTarget!U; return empty ? no!V : some!V(cast(V)front); // it's a range so "front" is the raw value } else { return empty ? no!U : some!U(cast(U)front); } } It would allow for scenarios like: Optional!int a = 3; auto b = cast(float)a; // b == some!float Cheers - AliI think the best way to do this is to implement `map` for your optional type. Optional!U map(U, alias f)() { return empty? no!U : some!U(f(t)); } Optional!int a = 3; auto b = a.map!(v => cast(float)v); assert(is(typeof(b) == Optional!float));
Feb 14 2018
On Wednesday, 14 February 2018 at 15:14:24 UTC, Meta wrote:I think the best way to do this is to implement `map` for your optional type. Optional!U map(U, alias f)() { return empty? no!U : some!U(f(t)); } Optional!int a = 3; auto b = a.map!(v => cast(float)v); assert(is(typeof(b) == Optional!float));Ooh yes, of course! Thank you :)
Feb 14 2018
On Wednesday, 14 February 2018 at 23:46:30 UTC, aliak wrote:On Wednesday, 14 February 2018 at 15:14:24 UTC, Meta wrote:Even better: import std.conv; auto b = a.map!(to!float);I think the best way to do this is to implement `map` for your optional type. Optional!U map(U, alias f)() { return empty? no!U : some!U(f(t)); } Optional!int a = 3; auto b = a.map!(v => cast(float)v); assert(is(typeof(b) == Optional!float));Ooh yes, of course! Thank you :)
Feb 14 2018
On Thursday, 15 February 2018 at 00:27:40 UTC, Meta wrote:On Wednesday, 14 February 2018 at 23:46:30 UTC, aliak wrote:Actually, that won't quite work without redefining map a little: Optional!U map(alias f, U = typeof(f(t.init)))() { etc... }On Wednesday, 14 February 2018 at 15:14:24 UTC, Meta wrote: Ooh yes, of course! Thank you :)Even better: import std.conv; auto b = a.map!(to!float);
Feb 14 2018
On Thursday, 15 February 2018 at 00:34:33 UTC, Meta wrote:On Thursday, 15 February 2018 at 00:27:40 UTC, Meta wrote:Ah yes, true, also auto return would work. But then you'd still need to do the typeof(f(T.init)) evaluation in the body... plus you lose being able to see an explicit return type i guess... hmm. So nevermind :) Though a free function would be good me thinks. Then you could use it seamlessly with std.algorithm.map. Optional!U map(alias f, T, U = typeof(f(T.init)))(Optional!T opt) { return Optional!U(f(opt.t)); } Cheers, - AliOn Wednesday, 14 February 2018 at 23:46:30 UTC, aliak wrote:Actually, that won't quite work without redefining map a little: Optional!U map(alias f, U = typeof(f(t.init)))() { etc... }On Wednesday, 14 February 2018 at 15:14:24 UTC, Meta wrote: Ooh yes, of course! Thank you :)Even better: import std.conv; auto b = a.map!(to!float);
Feb 14 2018