Re: member func is best choice for pointers?

2023-04-07 Thread Ali Çehreli via Digitalmars-d-learn

On 4/6/23 07:26, a11e99z wrote:
> ```d
> import std, core.lifetime;
>
> struct Node {
>  Node* pNext;
>  void func() { "Node::func %s".writeln( pNext); }

That's a member function, which works with the obj.func() syntax.

However, there is another feature of D that is in play here: Members can 
directly be accessed through pointers without dereferencing.


  pn.func()

has the same effect as

  (*pn).func()

(That's why D does not use C's -> operator).

> }
> void func( Node* p ) { "::func %s(%s)".writeln( p, p == null ? p :
> p.next); }

Ok, that function can be called normally as

  func(pn)

or with UFCS as

  pn.func()

However, UFCS takes place only when there is no such member.

I understand how this can be surprising but it is still within spec: 
There does exist a member with the name 'func', so UFCS is not applied.


One can rightly argue that automatic pointer dereferencing should take 
place after UFCS consideration but apparently that's not the case. If 
that were the case, I suspect there would be other programmers who would 
be looking for the current behavior.


Ali



Re: member func is best choice for pointers?

2023-04-06 Thread Salih Dincer via Digitalmars-d-learn

On Thursday, 6 April 2023 at 14:26:01 UTC, a11e99z wrote:
member func has invariant that **this** is not null (programmer 
thinks so).
global func hasn't the one and programmer should check for it 
before doing something ...


I understand what you mean.  When you try to access the last node 
of a linked list, you will get the segmentation fault if you are 
using a built-in viewer (toString).  For example:


```d
struct Node
{
  int item;
  Node * back;

  string toString()
  {
import std.format : format;

return format("Node::%s (back)-> %s", item,
 back.item);
  }
}

void main()
{
  import std.stdio : writeln;

  auto node1 = Node(41);
  auto node1Ptr = 

  //printNode(node1Ptr);/* NOT COMPILE!
  node1.writeln;//* Main::41 (back)-> null */

  auto node2 = Node(42);
  node2.back = node1Ptr;

  printNode(); // Main::42 (back)-> 41
  node2.writeln; // Node::42 (back)-> 41
}

void printNode(Node * p)
{
  import std.stdio : writefln;

  if(p.back is null)
  {
writefln("Main::%s (back)-> null", p.item);
  } else {
writefln("Main::%s (back)-> %s", p.item,
p.back.item);
  }
}
```

If you don't remove the comment line (just remove the // sign: 
toggle-comment) the above code will not compile.  Because it is 
not connect to any node.


@SDB


member func is best choice for pointers?

2023-04-06 Thread a11e99z via Digitalmars-d-learn

```d
import std, core.lifetime;

struct Node {
Node* pNext;
void func() { "Node::func %s".writeln( pNext); }
}
void func( Node* p ) { "::func %s(%s)".writeln( p, p == null ? p 
: p.next); }


void main()
{
Node n;
auto pn =  //cast( Node* )0;
pn.func(); // prints: Node::func
// WTF?
// why called Node::func for Node* when ::func is right 
choice for it?

}
```

problem:
member func has invariant that **this** is not null (programmer 
thinks so).
global func hasn't the one and programmer should check for it 
before doing something.


when pn is null u've got AccessViolation/Signal_11 with no 
stacktrace.


workaround:
avoid overloaded UFCS for pointers