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









Jonathan M Davis <jmdavisProg gmx.com> 