56

I'm reading code of a C++ project and it contains some code of the following form:

namespace ns {
    class A {};
    class B {};
}

struct C {
    typedef ns::A* ns::B::* type;
};

Can someone explain the meaning of the typedef line? type seems to be some kind of pointer to member of ns::B which points to ns::A, but I'm not sure.

Class A and B in the real code are not empty, but I think it's not relevant here. And here is a live example.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Tien
  • 583
  • 5
  • 14
  • How is this type used? Can you some some example of that too? – Some programmer dude Nov 17 '15 at 18:41
  • 1
    [strange stuff](http://ideone.com/qFMwRW) indeed! @JoachimPileborg – πάντα ῥεῖ Nov 17 '15 at 18:44
  • 1
    looks like pointer to member function, but the parameters are missing. Maybe it is equivalent to `typedef ns::A* ns::B::* () type;` – 463035818_is_not_an_ai Nov 17 '15 at 18:44
  • @tobi303 Good guess! Pointer to member (not necessarily function) could be as well. – πάντα ῥεῖ Nov 17 '15 at 18:45
  • It appears to be a pointer to class `B` member variable of type `A*`; Not a function. The `type` in the end if just the name for that whole thing. – Raxvan Nov 17 '15 at 18:45
  • @πάνταῥεῖ Oops I didn't see your comment and edited to add another live example :) – Tien Nov 17 '15 at 18:55
  • 3
    @xovano No problem. Another live example just improves your question more. You hit a great question about this confusing syntax already (not so easy nowadays), unless someone finds an appropriate duplicate. Congrats. Your question title might be improved though. – πάντα ῥεῖ Nov 17 '15 at 19:02
  • 1
    More info: https://msdn.microsoft.com/en-us/library/f2wbycwh.aspx – 001 Nov 17 '15 at 19:08
  • 2
    Splitting it into two lines and utilizing the C++11 `using` statement make this a little more palatable but not very much more. [Here](http://cpp.sh/2tdf) is a slightly modified version of @πάνταῥεῖ's example. – crayzeewulf Nov 17 '15 at 19:12
  • @πάνταῥεῖ Feel free to edit the title. My English is not fluent enough to find a better title. And after reading the answers, the code is suddenly not confusing anymore. – Tien Nov 17 '15 at 19:50

2 Answers2

39
ns::B::*

is a pointer-to-member-variable of B. Then ns::A* is its type.

So the whole declaration means

pointer-to-member-variable of B of type ns::A*

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • So the code seems to be not so hard to understand. I need to study more about pointer-to-member :) – Tien Nov 17 '15 at 19:40
  • 1
    @xovano The namespace specifiers is what makes it look nasty. Otherwise something like `int Foo::*` is understood by everyone. – vsoftco Nov 17 '15 at 20:07
27

The answer by @vsoftco already answers the core of the question. This answer shows how one might use such a typedef.

#include <iostream>
#include <cstddef>

namespace ns {

   struct A {};

   struct B
   {
      A* a1;
      A* a2;
   };
}

struct C {
   typedef ns::A* ns::B::*type;
};

int main()
{
   C::type ptr1 = &ns::B::a1;
   C::type ptr2 = &ns::B::a2;

   ns::B b1;
   b1.*ptr1 = new ns::A; // Samething as b1.a1 = new ns::A;

   return 0;
}
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    `b1.*ptr1` Woah. So it's essentially local pointer offsets? (That is, you're dereferencing `ptr1` with the address of `b` as the initial point?) – JAB Nov 17 '15 at 21:43