pointers, functions, and uniform call syntax

Era Scarecrow rtcvb32 at yahoo.com
Wed Sep 5 15:50:52 PDT 2012


On Wednesday, 5 September 2012 at 11:01:50 UTC, Artur Skawina 
wrote:
> On 09/04/12 20:19, Era Scarecrow wrote:
>>  I ask you, how do you check if it's a null pointer? &s?
>
> Yes, obviously. If you need to do that manually.

  But you shouldn't have to.

>>   int getx(ref S s)
>>   //How does this make sense?? it looks wrong and is misleading
>>   in {assert(&s); }
>>   body {return s.x); }
>
> It looks correct and is perfectly obvious. But see below - you 
> don't need to do this manually - the compiler does it for you 
> when calling methods and could handle the UFCS case too.

  How I'm understanding references in D (And perhaps I'm repeating 
myself in two different topics) is they point to live variables 
(IE guaranteed pointers), and remains this way until you return 
from that function.

  This is entirely valid and simplifies things. Remember in D we 
want the language to 'do the right thing', but if you make 
references where it works to 'sometimes works' then it becomes a 
problem (pointers 'sometimes' work and are not @safe, while ref 
is @safe). Checking the address of a reference shouldn't be 
needed, since it should be dereferenced at where it was called at 
if need be (throwing it there).

  Any side effects that may rely on the validity of the 'pointer' 
(once the function ends) are compromised afterwards (I'm always 
assume you pass local variables for this logic, since it's likely 
80% of the time).

  Would you REALLY want to mark every single function that uses 
ref as @trusted? You're then blindly telling the compiler to 
'shut up' so you can use the code and ignoring the checking; Or 
am I wrong?

int getItem(string[] inp, string cmp) @safe {
   //foreach not @safe!
   //only works not @safe or blindly adding @trusted
   foreach(i, ref s; inp) {
     if (s == cmp)
       return i;
   }

   //still might not compile, if foreach calls opApply
   //(Even if it doesn't use the reference).
   foreach(i, s; inp) {
   }
}

>>  More importantly, if it's now a possibility do we have to 
>> start adding checks everywhere?
>> 
>>   int getx(S *s)
>>   in {assert(s); } //perfectly acceptable check, we know it's 
>> a pointer
>>   body {return s.x); }

>    struct S { int i; auto f() { return i; } }
>    int main() {
>       S* s;
>       return s.f();
>    }
>
> This program will assert at runtime (and (correctly) segfault 
> in a release-build). The compiler inserts not-null-this checks 
> for "normal" methods in non-release mode, and could also do 
> that before invoking any UFCS "method". So you wouldn't need to 
> check for '!!&this' yourself.

  I thought those checks weren't added (via the compiler) since if 
it causes a seg fault the CPU would catch it and kill the program 
on it's own (just add debugging flags); If you added the checks 
they would do the same thing (More buck for the same bang).

> The problem w/ these checks is that they can not be disabled 
> per-type - which prevents certain valid uses. The 
> compiler-inserted assertions fire also when the methods can 
> deal with null-this themselves (happens eg. when dealing with 
> 'C' APIs and libraries, when you want to keep the C part as 
> unmodified as possible). But that is a different issue.




More information about the Digitalmars-d mailing list