digitalmars.D.learn - Struct ctor called with cast
- Radu (19/21) Feb 27 2018 enum Type { a };
- ag0aep6g (20/41) Feb 27 2018 Not a bug. The spec says [1]: "Casting a value v to a struct S, when
- Radu (30/77) Feb 27 2018 OK, got it - thanks.
- ag0aep6g (14/27) Feb 27 2018 [...]
- Radu (2/21) Feb 27 2018 Understood, make sense now, thanks!
- Steven Schveighoffer (16/36) Feb 27 2018 Look at your constructor. You actually have a TEMPLATED constructor
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.
Feb 27 2018
On 02/27/2018 09:30 PM, Radu wrote: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_expressionsenum 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.
Feb 27 2018
On Tuesday, 27 February 2018 at 20:51:25 UTC, ag0aep6g wrote:On 02/27/2018 09:30 PM, Radu wrote:OK, got it - thanks. But this: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_expressionsenum 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.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*. Addingthis(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.
Feb 27 2018
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. */ { /* ... */ } ----
Feb 27 2018
On Tuesday, 27 February 2018 at 21:04:59 UTC, ag0aep6g wrote:On 02/27/2018 09:59 PM, Radu wrote:Understood, make sense now, thanks!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. */ { /* ... */ } ----
Feb 27 2018
On 2/27/18 3:59 PM, Radu wrote:On Tuesday, 27 February 2018 at 20:51:25 UTC, ag0aep6g wrote:[snip]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); }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
Feb 27 2018