2

I am reading "C++ Templates. The Complete Guide. Second Edition", by David Vandevoorde, Nicolai M. Josuttis, Douglas Gregor. And, there is something that I don't understand.

This is one code example in pg. 59:

// define binary tree structure and traverse helpers:
struct Node {
    int value;
    Node* left;
    Node* right;
    Node(int i=0) : value(i), left(nullptr), right(nullptr) {}
    // ...
};

auto left = &Node::left;
auto right = &Node::right;

// traverse tree, using fold expression:
template<typename T, typename... TP>
Node* traverse (T np, TP... paths) {
    return (np ->* ... ->* paths);
}
// np ->* paths1 ->* paths2 ...

int main()
{
    // init binary tree structure:
    Node* root = new Node{0};
    root->left = new Node{1};
    root->left->right = new Node{2};
    // ...
    // traverse binary tree:
    Node* node = traverse(root, left, right);
    //...
}

What I don't understand is:

auto left = &Node::left;
auto right = &Node::right;

These are global variables of type (according to the llvm compiler): Node *Node::*. With value, for example the first one, left: &Node::left

The question is, being the variable left a pointer, how can I take the address (operator&) of a non-instantiated struct?

Jarod42
  • 203,559
  • 14
  • 181
  • 302
José Otero
  • 119
  • 1
  • 7
  • 3
    That is [pointer to member](https://stackoverflow.com/questions/670734/pointer-to-class-data-member) syntax – Cory Kramer Dec 13 '21 at 12:38
  • See [What are the Pointer-to-Member ->* and .* Operators in C++? - Stack Overflow](https://stackoverflow.com/questions/6586205/what-are-the-pointer-to-member-and-operators-in-c) for explanation (although it's not a "what is this" question. A "what is" question is [c++ - What does void (M :: *pf)(int,int) = &M :: set_xy; do? - Stack Overflow](https://stackoverflow.com/questions/66040711/what-does-void-m-pfint-int-m-set-xy-do)) – user202729 Dec 13 '21 at 12:48

1 Answers1

2

This is not an "a non-instantiated struct".

This is an address of a class member.

left is a member of the Node class. This takes its "address", and not the actual address of some instance of some Node class. This does not take the left pointer of some particular class instance, but of the left itself.

The address of a class member cannot be used just like that, by itself, but requires a specific instance of the class.

auto member_address = &Node::left;

// ...

Node *p;

// ...

Node *ptr=p->*member_address;

Whatever p is, this fetches p's left. If member_address was &Node::right, ptr gets set to p->right.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148