22

Let us say I have:

// This is all valid in C++11.
struct Foo {
    int i = 42;
    int& j = i;
};

// Let's take a pointer to the member "j".
auto b = &Foo::j; // Compiler is not happy here
// Note that if I tried to get a pointer to member "i", it would work, as expected.
Foo f;
std::cout << f.*b; // Try using the pointer to member

The compiler complains that I cannot take the address of the member because it is a reference. To be precise:

Semantic Issue: Cannot form a pointer-to-member to member 'j' of reference type 'int &'

I know doing this seems pointless, but I am only wondering why it cannot be done.

Why is this impossible?

Anthony
  • 12,177
  • 9
  • 69
  • 105
fronsacqc
  • 320
  • 2
  • 12

4 Answers4

14

It cannot be done because you cannot take a pointer to a reference- period.

If you could take a member pointer to a reference, this would be inconsistent with the behaviour of references on the stack. The attitude of C++ is that references do not exist. As such, you cannot form a pointer to them- ever.

For example, &f::a would have to be different to &f::b. And by de-referencing &f::b, you would effectively be achieving a pointer to a reference, which is not allowed.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • +1. The first statement is *indeed* the precise answer. References to pointers are allowed but pointers to references are not. – Alok Save Dec 01 '11 at 04:06
  • @DeadMG : What do you mean by the "behavior of references on the stack?" – fronsacqc Dec 01 '11 at 04:11
  • But I do `&my_vector[0]` all the time - and I'm sure `operator[]` returns a reference. – Mark Ransom Dec 01 '11 at 04:14
  • 1
    @fronsacqc: If you took a pointer to `int&` that was on the stack, you'd get an `int*`. However, by obtaining a pointer-to-member-reference, you are effectively circumventing that and achieving a pointer to reference. `&f::a` would have to be different to `&f::b`, which is not allowed, since references are not objects. – Puppy Dec 01 '11 at 04:14
  • 1
    @MarkRansom: That does not yield a pointer to a reference, it yields a pointer to the object which was referred to. Different things. – Puppy Dec 01 '11 at 04:15
  • Then I think your first statement is too strong - you *can* take a pointer to a reference, but it doesn't provide a pointer to the reference itself but to the referred object. – Mark Ransom Dec 01 '11 at 04:22
  • 2
    @MarkRansom: You can take the *address of* a reference, which is the address of the reference's object. You can not point to a reference itself. – GManNickG Dec 01 '11 at 04:53
14

C++11 standard:

§8.3.3 p3 [dcl.mptr]
A pointer to member shall not point to a static member of a class (9.4), a member with reference type, or “cv void.”

Also, in general:

§8.3.1 p4 [dcl.ptr]
[ Note: There are no pointers to references; see 8.3.2. [...] —end note ]

§8.3.2 p5 [dcl.ref]
There shall be no references to references, no arrays of references, and no pointers to references.

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 1
    I'm asking WHY is the standard against it. I'd love to the reason. – fronsacqc Dec 01 '11 at 04:25
  • @fronsacqc: Well, then you'll have to mail the standard committee's mailing list `comp.lang.c++.moderated` or hope for Howard Hinnant (a member of the committee roaming around SO) to answer this question. – Xeo Dec 01 '11 at 04:57
  • 3
    @fronsacqc: Because pointers point to objects, but references aren't objects. – fredoverflow Dec 01 '11 at 06:06
  • @Fred: Good point, when I get back from work I'll edit this answer to include that supported by standard quotes. Atleast that should be doable. :) – Xeo Dec 01 '11 at 06:14
7

Member pointer (as opposed to a simple pointer to a member) is simply an offset into the structure, not a pointer at all. You can get data through it only in conjunction with the structure itself (or a pointer to a structure): the value of the offset is added to the address of the structure, and the result is dereferenced to produce the value of the member.

Now suppose a member is a reference, so accessing data through it already requires a dereference (compiler hides it from us, but it needs to spit out the corresponding instructions in its output). If C++ were to allow member pointers to references, they'd be of yet another type: an offset that needs to be added to the base, and then dereferenced twice. It is too much work to improve an already obscure feature; prohibiting it is a much better way out.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • @R.MartinhoFernandes Well, that's pointers to member functions. Pointers to data members are much less sophisticated, because data members cannot be virtual. – Sergey Kalinichenko Dec 01 '11 at 04:22
  • Thanks, this is the best answer I've gotten so far. It explains WHY the feature is not supported. So I'm not crazy of expecting it to work. It only means that it's not supported. – fronsacqc Dec 01 '11 at 04:33
  • 2
    @fronsacqc Sure, this feature can be made to work if you shoehorn it into some meaningful semantic. Unfortunately, doing so for an obscure feature like this belongs to the domain of problems, not solutions. Fortunately, someone on the standardization committee has recognized it early on, and banned the feature before it became a problem. – Sergey Kalinichenko Dec 01 '11 at 04:41
1

Allowing you to make a pointer to a reference does not give you any expressive power. There's nothing you can do with such a beast that you can't easily do with a reference or with a pointer. All you get out of it is added complexity.

And making a pointer to a member that is a reference is not allowed for consistency with the rule that forbids pointers to references, and because it adds even more complexity. The designers of the language probably decided that the little gains you get from these was not worth it.

This is totally just my opinion.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • You can't simultaneously claim that it gives you **no** expressive power, yet claim pointers to reference member have "**little** gains". If B is useful and A allows B, then A must in some ways also be useful. – Eric Jan 19 '18 at 02:45