Thread overview |
---|
February 27, 2018 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. |
February 27, 2018 Re: Struct ctor called with cast | ||||
---|---|---|---|---|
| ||||
Posted in reply to Radu | 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 |
February 27, 2018 Re: Struct ctor called with cast | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | 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. |
February 27, 2018 Re: Struct ctor called with cast | ||||
---|---|---|---|---|
| ||||
Posted in reply to Radu | 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. */ { /* ... */ } ---- |
February 27, 2018 Re: Struct ctor called with cast | ||||
---|---|---|---|---|
| ||||
Posted in reply to Radu | 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 |
February 27, 2018 Re: Struct ctor called with cast | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | 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!
|
Copyright © 1999-2021 by the D Language Foundation