Jump to page: 1 2
Thread overview
static weirdness
Jan 24, 2018
Alex
Jan 24, 2018
Alex
Jan 24, 2018
Jonathan M Davis
Jan 24, 2018
Alex
Jan 25, 2018
Kagamin
Jan 25, 2018
Jonathan M Davis
Jan 25, 2018
Alex
Jan 25, 2018
Kagamin
Jan 25, 2018
Jonathan M Davis
Jan 25, 2018
Kagamin
Jan 25, 2018
Jonathan M Davis
Jan 25, 2018
Mike Parker
Jan 25, 2018
Alex
January 24, 2018
the story of
https://forum.dlang.org/thread/qknxjxzbaowmsjdngvli@forum.dlang.org
continues

How can this be?

void main()
{
    auto s = S();
    auto t = T!s();
    assert(typeof(t).dummy == null);
    assert(t.dummy == null);
    t.foo;

}

struct S
{
    auto fun()
    {
    	return 42;
    }
}

struct T(alias stats)
{
    static typeof(stats)* dummy; // line 21
    static auto foo()
    {
    	assert(dummy == null); // line 24
        assert(dummy.fun == 42); //line 25
    }
}

I thought, if I don't initialize a pointer, like the one in line 21 (I assert this by the check in line 24) I can't use it line line 25.
However, I can...
January 24, 2018
On Wednesday, 24 January 2018 at 01:48:45 UTC, Alex wrote:

Ah... I figured it out.
For using the function of S, an object does not have to exist...
And in case I would return a member from S, there is a segmentation violation, as expected.
So, everything is ok.

Sorry for noise.
January 23, 2018
On Wednesday, January 24, 2018 01:48:45 Alex via Digitalmars-d-learn wrote:
> the story of https://forum.dlang.org/thread/qknxjxzbaowmsjdngvli@forum.dlang.org continues
>
> How can this be?
>
> void main()
> {
>      auto s = S();
>      auto t = T!s();
>      assert(typeof(t).dummy == null);
>      assert(t.dummy == null);
>      t.foo;
>
> }
>
> struct S
> {
>      auto fun()
>      {
>       return 42;
>      }
> }
>
> struct T(alias stats)
> {
>      static typeof(stats)* dummy; // line 21
>      static auto foo()
>      {
>       assert(dummy == null); // line 24
>          assert(dummy.fun == 42); //line 25
>      }
> }
>
> I thought, if I don't initialize a pointer, like the one in line
> 21 (I assert this by the check in line 24) I can't use it line
> line 25.
> However, I can...

That has nothing to do with static. That has to do with the fact that S.fun
is non-virtual (so there's no need to dereference the pointer to call it),
and fun doesn't access any members, so it doesn't need to dereference the
this pointer internally either. And since the pointer is never dereferenced,
it doesn't matter that it's null. You'd get the same behavior if you used
a non-static S.

On a side note, if you're checking for null, it's better to use the is operator rather than ==. For strings, there's a semantic difference, so it really matters. For classes, it avoids calling the free function opEquals (which will give the same result, but it's a pointless function call when you could just use is and avoid the call). For pointers, it matters that much less, but since it does matter in the other cases (especially strings), it's a good habit to get into just using is null instead of == null.

- Jonathan M Davis

January 24, 2018
On Wednesday, 24 January 2018 at 02:01:54 UTC, Jonathan M Davis wrote:
> On Wednesday, January 24, 2018 01:48:45 Alex via Digitalmars-d-learn wrote:
>> the story of https://forum.dlang.org/thread/qknxjxzbaowmsjdngvli@forum.dlang.org continues
>>
>> How can this be?
>>
>> void main()
>> {
>>      auto s = S();
>>      auto t = T!s();
>>      assert(typeof(t).dummy == null);
>>      assert(t.dummy == null);
>>      t.foo;
>>
>> }
>>
>> struct S
>> {
>>      auto fun()
>>      {
>>       return 42;
>>      }
>> }
>>
>> struct T(alias stats)
>> {
>>      static typeof(stats)* dummy; // line 21
>>      static auto foo()
>>      {
>>       assert(dummy == null); // line 24
>>          assert(dummy.fun == 42); //line 25
>>      }
>> }
>>
>> I thought, if I don't initialize a pointer, like the one in line
>> 21 (I assert this by the check in line 24) I can't use it line
>> line 25.
>> However, I can...
>
> That has nothing to do with static. That has to do with the fact that S.fun
> is non-virtual (so there's no need to dereference the pointer to call it),
> and fun doesn't access any members, so it doesn't need to dereference the
> this pointer internally either. And since the pointer is never dereferenced,
> it doesn't matter that it's null.

That's cool, by the way :)

> You'd get the same behavior if you used
> a non-static S.
>
> On a side note, if you're checking for null, it's better to use the is operator rather than ==. For strings, there's a semantic difference, so it really matters. For classes, it avoids calling the free function opEquals (which will give the same result, but it's a pointless function call when you could just use is and avoid the call). For pointers, it matters that much less, but since it does matter in the other cases (especially strings), it's a good habit to get into just using is null instead of == null.
>
Thanks.


January 25, 2018
On Wednesday, 24 January 2018 at 02:01:54 UTC, Jonathan M Davis wrote:
> (so there's no need to dereference the pointer to call it)

It used to check this pointer with an assert. When did it change?
January 25, 2018
On Thursday, January 25, 2018 10:17:34 Kagamin via Digitalmars-d-learn wrote:
> On Wednesday, 24 January 2018 at 02:01:54 UTC, Jonathan M Davis
>
> wrote:
> > (so there's no need to dereference the pointer to call it)
>
> It used to check this pointer with an assert. When did it change?

Actually, assert on a pointer to a struct or a reference to a class checks for null _and_ calls the invariant, and that hasn't changed. But you have to actually assert the pointer or reference if you want to do that, and the OP didn't do that. He asserted whether it == null.

- Jonathan M Davis

January 25, 2018
On Thursday, 25 January 2018 at 10:17:34 UTC, Kagamin wrote:
> On Wednesday, 24 January 2018 at 02:01:54 UTC, Jonathan M Davis wrote:
>> (so there's no need to dereference the pointer to call it)
>
> It used to check this pointer with an assert. When did it change?

Fortunately, I have some compilers here and just tested it. 2.076.1 results in a segmentation fault, whereas 2.077.0 does not.


January 25, 2018
On Thursday, 25 January 2018 at 12:06:07 UTC, Jonathan M Davis wrote:
> On Thursday, January 25, 2018 10:17:34 Kagamin via Digitalmars-d-learn wrote:
>> On Wednesday, 24 January 2018 at 02:01:54 UTC, Jonathan M Davis
>>
>> wrote:
>> > (so there's no need to dereference the pointer to call it)
>>
>> It used to check this pointer with an assert. When did it change?
>
> Actually, assert on a pointer to a struct or a reference to a class checks for null _and_ calls the invariant, and that hasn't changed. But you have to actually assert the pointer or reference if you want to do that, and the OP didn't do that. He asserted whether it == null.
>
> - Jonathan M Davis

Yeah... the cool thing is, that if the function does not need anything from the referenced object, then the pointer "degenerates" to a "namespace" implicitly... sorry, for strange wording.

It seems that this behavior changed from 2.076.1 to 2.077.
January 25, 2018
On Thursday, 25 January 2018 at 12:06:07 UTC, Jonathan M Davis wrote:
> Actually, assert on a pointer to a struct or a reference to a class checks for null _and_ calls the invariant, and that hasn't changed. But you have to actually assert the pointer or reference if you want to do that, and the OP didn't do that. He asserted whether it == null.

I mean the compiler implicitly inserted a check like:
struct S
{
    auto fun()
    {
    	assert(&this!=null);
    	return 42;
    }
}
January 25, 2018
See https://ideone.com/VZ97dh
« First   ‹ Prev
1 2