digitalmars.D - Alias this does not work with pointers?
- Nicholas Wilson (26/26) Mar 09 2016 struct Bar_T; // opaque
- Jonathan M Davis (17/43) Mar 09 2016 I see no bugs here. Just because type T can be implicitly
- Chris Wright (34/34) Mar 09 2016 alias this can do so much more, though.
struct Bar_T; // opaque alias Bar = Bar_T*; void someFuncIWantWrapped(Bar* bar) { } struct Foo { Bar bar; alias bar this; } void someFunc(Foo* foo) { someFuncIWantWrapped(foo); } gives Error: function someFuncIWantWrapped (Bar_T** bar) is not callable using argument types Foo* I feel like this should work. Yes I realise that I can fix it by void someFunc(Foo foo) { someFuncIWantWrapped(&foo.bar); } but I'm generating this and the name of bar changes and in generated from multiple code paths. Should I report this as a bug?
Mar 09 2016
On Thursday, 10 March 2016 at 01:25:44 UTC, Nicholas Wilson wrote:struct Bar_T; // opaque alias Bar = Bar_T*; void someFuncIWantWrapped(Bar* bar) { } struct Foo { Bar bar; alias bar this; } void someFunc(Foo* foo) { someFuncIWantWrapped(foo); } gives Error: function someFuncIWantWrapped (Bar_T** bar) is not callable using argument types Foo* I feel like this should work. Yes I realise that I can fix it by void someFunc(Foo foo) { someFuncIWantWrapped(&foo.bar); } but I'm generating this and the name of bar changes and in generated from multiple code paths. Should I report this as a bug?I see no bugs here. Just because type T can be implicitly converted to type U doesn't mean that T* can be implicitly converted to U* - e.g. int* can't be safely converted to long* in the general case. There are some cases where it can be done in system code if the programmer knows what they're doing but not in safe code - and regardless, it's done by reinterpreting the bytes, not by the kind of conversion that alias this is doing. You're asking for the compiler to somehow take T* and convert it to a completely unrelated type U* just because the programmer has provided a way to convert T to U. But since that conversion is not done be reinterpreting the bytes, there's no way to do that even in system code, let alone implicitly in safe code. Regardless, Foo defined the alias this, not Foo*, so alias this isn't going to work with Foo*. Foo* may point to a Foo, but isn't a Foo, and it doesn't follow the same conversion rules. - Jonathan M Davis
Mar 09 2016
alias this can do so much more, though. For instance: struct Foo { int a; string b; alias a this; } void bar(int* p, size_t len) { for (int i = 0; i < len; i++) { p[i] = 0; } } bar(new Foo[2].ptr, 2); Two fields. You don't want to overwrite a pointer, so you can't just turn it to an implicit cast. Or another example: struct Foo { double s; int square() { return cast(int)(s * s); } alias square this; } How do you convert a Foo* to an int*? Do you allocate space for it on the heap? But what if the Foo* points to a malloc'd section of memory? Or some other allocator? Or if it's on the heap and the function is marked nogc? You could put it on the stack as an alternative, but then the pointer will be invalid when the function exits... What if it's sent off to a C function that stores it? Should the allocation be pinned by default? When would it be unpinned? It's a silent, hidden allocation beyond the user's control. We would like it to be allocated like the Foo* was allocated, but that's not currently possible. Instead of providing an implementation that occasionally works but typically causes a crash or an unavoidable inefficiency, it's just not there to trip people up.
Mar 09 2016