Re: Struct ctor called with cast
On Tuesday, 27 February 2018 at 21:04:59 UTC, ag0aep6g wrote: On 02/27/2018 09:59 PM, Radu wrote: On Tuesday, 27 February 2018 at 20:51:25 UTC, ag0aep6g wrote: On 02/27/2018 09:30 PM, Radu wrote: [...] [...] [...] So the bug is that somehow the templated version makes it so there is an implicit void* ctor. In your original code (quoted above), you've got a templated constructor. The `Type` in `this(Type)(Type t)` is not the enum. It's a template parameter of the constructor. To get a non-templated constructor that takes a `Type` (the enum), you have to write: this(Type t) /* NOTE: Only one set of parentheses. */ { /* ... */ } Understood, make sense now, thanks!
Re: Struct ctor called with cast
On 2/27/18 3:59 PM, Radu wrote: On Tuesday, 27 February 2018 at 20:51:25 UTC, ag0aep6g wrote: On 02/27/2018 09:30 PM, Radu wrote: enum Type { a }; struct S(Type t = Type.a) { this(Type)(Type t) { import std.stdio; writeln("ctor called."); } } void main() { auto x = S!(Type.a)(Type.a); void* y = &x; auto z = (cast(S!(Type.a)) y); } [snip] So the bug is that somehow the templated version makes it so there is an implicit void* ctor. Look at your constructor. You actually have a TEMPLATED constructor inside a TEMPLATED type. In other words, inside your constructor, `Type` is not an enum Type, it's actually a void *. It becomes clearer if you change the name of the second template parameter: struct S(Type t = Type.a) { this(T)(T t) { import std.stdio; writeln("ctor called."); } } -Steve
Re: Struct ctor called with cast
On 02/27/2018 09:59 PM, Radu wrote: On Tuesday, 27 February 2018 at 20:51:25 UTC, ag0aep6g wrote: On 02/27/2018 09:30 PM, Radu wrote: [...] enum Type { a }; struct S(Type t = Type.a) { this(Type)(Type t) { import std.stdio; writeln("ctor called."); } } [...] So the bug is that somehow the templated version makes it so there is an implicit void* ctor. In your original code (quoted above), you've got a templated constructor. The `Type` in `this(Type)(Type t)` is not the enum. It's a template parameter of the constructor. To get a non-templated constructor that takes a `Type` (the enum), you have to write: this(Type t) /* NOTE: Only one set of parentheses. */ { /* ... */ }
Re: Struct ctor called with cast
On Tuesday, 27 February 2018 at 20:51:25 UTC, ag0aep6g wrote: On 02/27/2018 09:30 PM, Radu wrote: enum Type { a }; struct S(Type t = Type.a) { this(Type)(Type t) { import std.stdio; writeln("ctor called."); } } void main() { auto x = S!(Type.a)(Type.a); void* y = &x; auto z = (cast(S!(Type.a)) y); } Surprisingly the cast will actually call the ctor. Is this to be expected? Sure looks like a bug to me, as a non templated S will complain about the cast. Not a bug. The spec says [1]: "Casting a value v to a struct S, when value is not a struct of the same type, is equivalent to: S(v)" Templates have nothing to do with it. Your code boils down to this: struct S { this(void* t) { import std.stdio; writeln("ctor called."); } } void main() { void* y; auto z = cast(S) y; } [1] https://dlang.org/spec/expression.html#cast_expressions OK, got it - thanks. But this: struct S { this(int t) { import std.stdio; writeln("ctor called."); } } void main() { auto x = S(1); void* y = &x; auto z = (cast(S) y); } Produces: Error: cannot cast expression y of type void* to S Which is kinda correct as I don't have any ctor in S taking a void*. Adding this(void* t) { import std.stdio; writeln("ctor called."); } Will make the error go away. So the bug is that somehow the templated version makes it so there is an implicit void* ctor.
Re: Struct ctor called with cast
On 02/27/2018 09:30 PM, Radu wrote: enum Type { a }; struct S(Type t = Type.a) { this(Type)(Type t) { import std.stdio; writeln("ctor called."); } } void main() { auto x = S!(Type.a)(Type.a); void* y = &x; auto z = (cast(S!(Type.a)) y); } Surprisingly the cast will actually call the ctor. Is this to be expected? Sure looks like a bug to me, as a non templated S will complain about the cast. Not a bug. The spec says [1]: "Casting a value v to a struct S, when value is not a struct of the same type, is equivalent to: S(v)" Templates have nothing to do with it. Your code boils down to this: struct S { this(void* t) { import std.stdio; writeln("ctor called."); } } void main() { void* y; auto z = cast(S) y; } [1] https://dlang.org/spec/expression.html#cast_expressions
Struct ctor called with cast
I have this: enum Type { a }; struct S(Type t = Type.a) { this(Type)(Type t) { import std.stdio; writeln("ctor called."); } } void main() { auto x = S!(Type.a)(Type.a); void* y = &x; auto z = (cast(S!(Type.a)) y); } Surprisingly the cast will actually call the ctor. Is this to be expected? Sure looks like a bug to me, as a non templated S will complain about the cast.