Thread overview
Complicated @property access only works when I write an extra parenthesis "()"
May 26, 2023
realhet
May 26, 2023
Adam D Ruppe
May 26, 2023
realhet
May 27, 2023
realhet
May 26, 2023
realhet
May 26, 2023

Hello,

I tried to narrow the problem and make a small example, but I've failed.

I try to describe the syndrome, maybe someone knows about it.
(I heard that @properties are not 100% functional, maybe it's because of that, I dunno...)

With pragma msg, I verify the time of things:

karcSamples
This is a class, I create it from a class template, which has a lot of template mixins inside.

karcSamples[key]
The type of this is a RecordAccessor struct, which is a Voldemort struct inside a function. That function is called by karcSamples.opIndex(key).

karcSamples[key].lod0
The type of this is BlobLoader
'lod0' is a mixin generated @property getter. It calls a template function in the karcSamples class: _getBlob!"lod0"(key) this also calls an internal struct called DataLoggerBlobAA which is acting like an associative array. That iternal struct overloads the opBinary!"in" operator and returns a BlobLoader struct.

karcSamples[key].lod0._size -> error void has no property ._size
But this is weird, because BlobLoader actually HAS a @property called _size.

karcSamples[key].lod0()
The type of this is also BlobLoader. I have a feeling, that karcSamples[key].lod0 only returns a function pointer (the property function) which is implicitly evaluated, except when I use the ._size thing to evaluate a property.

karcSamples[key].lod0()._size
And this finally works, but it's ugly.

Anyone knows how to eliminate that extra () from there? The typeof() is works good for it, but the actual compilation thinks it's "void", not the BlobLoader struct reported by typeof(). Only the extra () let it compile successfuly.

May 26, 2023
On Friday, 26 May 2023 at 21:00:20 UTC, realhet wrote:
> Only the extra () let it compile successfuly.

No way to fix it. If the function takes an extra argument you can kinda trick it but for zero arg function pointer return from a property it is just plain broken and has been the whole time.

Don't expect it to ever be fixed.
May 26, 2023

On Friday, 26 May 2023 at 21:00:20 UTC, realhet wrote:

Update:

auto x = karcSamples[a.key].lod0;	print(x._size);
auto y = karcSamples[a.key].lod0();	print(y._size);
with(karcSamples[a.key].lod0) print(_size);
with(karcSamples[a.key].lod0()) print(_size);

When I put it into a temp variable or inside a with(), then both form works ok.

Bit when I try to write the whole thing in a single nice expression: No property _size for the type void.

In the documentation I see this:

  • For the expression typeof(exp) where exp is an @property function, the type is the return type of the function, rather than the type of the function.
  • For the expression __traits(compiles, exp) where exp is an @property function, a further check is made to see if the function can be called.

I think this extra step is not always working and by writing an extra () or by using a temp variable or a with(), I was able to force it. I only hope there is a workaround that I can implement inside my template things, so the business logic could be nice as it can be...

May 26, 2023
On Friday, 26 May 2023 at 21:11:45 UTC, Adam D Ruppe wrote:
> On Friday, 26 May 2023 at 21:00:20 UTC, realhet wrote:
>> Only the extra () let it compile successfuly.
>
> No way to fix it. If the function takes an extra argument you can kinda trick it but for zero arg function pointer return from a property it is just plain broken and has been the whole time.
>
> Don't expect it to ever be fixed.

At least my 5 hour trying-and-failing session comes to a logical end here :D

Thank You!

May 27, 2023
It seems like I managed to solve it.

All the chain of properties now capturing a generic value type T.
And finally the most inner associative array will handle the implicit cast.
Maybe that extra implicit () got confused when the types are same, but the aliases to those types are different. o.O

Now both expressions are working.

   samples[key].mainPicture().width
   samples[key].mainPicture.width

Side effect: The internal chaos behind this also got rediced by 25% as I had to refactor to find the root of the problem :D