NoQ
NoQ

Reputation: 75

A particular overloaded conversion operator

I'm staring at the following code snippet, trying to understand what's going on, or at least how to name what i'm seeing to google it up.

struct A {
    A *m_ptr; 
    typedef A * (A::*T);
    operator T() const {
        return &A::m_ptr;
    }
};

I figured out that operator T() is an overloaded conversion operator to type T, while type T is a typedef to represent A*(A::*). Now,

Upvotes: 0

Views: 41

Answers (2)

R Sahu
R Sahu

Reputation: 206607

what exactly is A::*?

It's a pointer to a member of A. Type type A* (A::*) is a pointer to a member of A of type A*.

what's the difference between that and A*?

It's a pointer to an object of type A.

and what sense does the A:: in the return statement make?

&(A::m_ptr) is a pointer to the m_ptr member of an object.


An example program that explores the idea a little bit more:

#include <iostream>

struct A {
    A *m_ptr1; 
    A *m_ptr2; 
    typedef A * (A::*T);
    operator T() const {
        return &A::m_ptr1;
    }

    A(int d) : data(d) {}
    int data;
};

int main()
{
   A::T ap1 = &A::m_ptr1;
   A::T ap2 = &A::m_ptr2;

   A a1(10);
   A a2(20);

   a1.*ap1 = &a1; // a1.m_ptr1 points to a1.
   a1.*ap2 = &a2; // a1.m_ptr2 points to a2.

   a2.*ap1 = &a2; // a2.m_ptr1 points to a2.
   a2.*ap2 = &a1; // a2.m_ptr2 points to a1.

   std::cout << "a1.data: " << a1.data << std::endl;
   std::cout << "a1.m_ptr1->data: " << a1.m_ptr1->data << std::endl;
   std::cout << "a1.m_ptr2->data: " << a1.m_ptr2->data << std::endl;

   std::cout << "a2.data: " << a2.data << std::endl;
   std::cout << "a2.m_ptr1->data: " << a2.m_ptr1->data << std::endl;
   std::cout << "a2.m_ptr2->data: " << a2.m_ptr2->data << std::endl;
}

Output:

a1.data: 10
a1.m_ptr1->data: 10
a1.m_ptr2->data: 20
a2.data: 20
a2.m_ptr1->data: 20
a2.m_ptr2->data: 10

Upvotes: 3

Jonathan Wakely
Jonathan Wakely

Reputation: 171303

what's the difference between that and A*?

X* is the address of an X object, whereas X Y::* is a pointer-to-member that points to a member of class Y of type X.

The difference is that a pointer is the address of an object.

A pointer-to-member is more like an offset, because it's not an actual address, it is relative to some object. It tells you how to get a member given some object. You can't dereference a pointer-to-member on its own, you have to combine it with an object to dereference it.

You create a pointer-to-member by using the & operator on a qualified-id, so &x means "take the address of the object x" but &Y::x means get a pointer-to-member for the member x of class Y.

You dereference a pointer-to-member by combining it with an object (or pointer to object) using the .* operator (or ->* operator).

e.g.

struct Y { int i; int j; };

int Y::* memptr = &Y::i;
Y y;
int& i = y.*memptr;
memptr = &Y::j;
int& j = y.*memptr;

Upvotes: 1

Related Questions