Why Doesn't Reference-To-Member Exist in C++

Why doesn't reference-to-member exist in C++?

In the standard (e.g. N3337 - not the latest but fine for this) there is a note at the end of section 8.3.3.3 that reads:

[ Note: See also 5.3 and 5.5. The type “pointer to member” is distinct
from the type “pointer”, that is, a pointer to member is declared only
by the pointer to member declarator syntax, and never by the pointer
declarator syntax. There is no “reference-to-member” type in C++. —
end note ]

Also, of course, there are no "reference to member" type operators (which, hypothetically, the best I can come up with would be something like ->& and .&, although these are not consistent with dereferencing of data and function references, which require no special operator).

Why?

As for why; after a fun little historical investigation and failing to find any existing notes on it (I went all the way back to Cfront 2.0 where pointer-to-member was first supported -- edit: according to a far more credible document, the feature was actually first supported in Cfront 1.2), I asked the man himself and here is the reply:


Date: Sat, 22 Feb 2014 10:12:51 -0500
From: Bjarne Stroustrup <...>
Subject: Re: On lack of reference-to-member and CFront 2.0

On 2/22/2014 6:40 AM, Jason C wrote:
> My question is: C++ very clearly disallows the concept of
> "reference-to-member". Why is this? I have been doing a lot of
> research, and I traced the origin of "pointer-to-member" back (I
> think) to 1989 CFront 2.0. I read through the product reference manual
> and other documentation hoping to find an explanation of some sort but
> could not.

I don't really remember. It was 25+ years ago and the ARM is silent on
this. I added pointers to members to eliminate the need for a rare
breakage of the type system. I suspect that I didn't add references to
members because it did not seem worth the effort: there was no use case.

To be honest, I was expecting something far more arcane and complicated.

So there you have it: The next time somebody asks why there's no reference-to-member, you can confidently say, "Because there isn't!" (Note: See my ramblings in the comments; there is still some historical investigation to be done to get to 100% confidence.)

Personally, I've never once found a use for pointers-to-members in my own code, but a distinct rationale for their existence is given in Stroustrup's The Evolution of C++: 1985-1989, pp. 222-223.


By the way, your syntax for calling the hypothetical reference-to-member function:

object.method();

... does not make much sense, as there is no way to distinguish that syntactically from a call to an actual member named method().

hvd brings up a good point below: As you can see from the above, syntactically, there wouldn't really be a consistent way to dereference a reference-to-member. You have to distinguish it from normal member access, but at the same time you want to make it consistent with dereferencing of object and function references (which require no special operator), and I can't really think of anything that accomplishes both.

C++: why can't we have references to references or array of references?

Pointers are mutable (if non-const), references never. Thus there is no point having a pointer or reference to a reference.

Also, a reference must always refer to something - there is no such thing as a null reference. This is why there can be no arrays of references, as there is no way to default instantiate references inside an array to a meaningful value.

Reference to member function?

There is no such a thing called reference to member in C++.

The language specification explicitly says in a note (§8.3.3/3 - 2003) that,

A pointer to member shall not point to a static member of a class (9.4), a member with reference type, or “cv void.” [Note: see also 5.3 and 5.5. The type “pointer to member” is distinct from the type “pointer”, that is, a pointer to member is declared only by the pointer to member declarator syntax, and never by the pointer declarator syntax. There is no “reference-to-member” type in C++.

How come we can return references to member variables of a class

You are confusing scope and lifetime. Those are two related, but ultimately different concepts.

The scope of the name x is the class scope. You can only use the unqualified name x for the member inside members functions (and some other minutia, irrelevant here) of the class.

The lifetime of the member object named x is the same as the enclosing class object. In this case, the lifetime of obj.x is the same as obj. Since you return a reference to an object within its lifetime, everything checks out.


The reason for your confusion may stem from learning that objects with automatic storage duration, like the following:

{
int x;
}

Have their lifetime bound to their lexical scope (they can only be named inside those curly braces, their scope). But while it's true for those objects, it is not something that holds in general. Class objects can live independently of the scope of their name (as you saw). And some objects can have a lifetime but no scope and name. Consider:

auto* p = new Foo();

The new expression creates an object, but it has no name! So there is no scope to even speak of. Here p is the name of a pointer, not of the newly created object.

Why is it impossible to have a reference-to-void?

If you did have a reference to void, what would you do with it? It wouldn't be a number, or a character, or a pointer, or anything like that. Your hypothetical generic function couldn't perform any operation on it, except taking its address (and not its size).

"void" has two uses: to disclaim any knowledge of type (as in void *), and to specify nothing as opposed to something (void function return). In neither case is it possible to say anything about a void something except that it may have an address.

If you can't think of a way something can be useful, and I can't, that is at least evidence that something is useless, and that may well be at least part of the rationale here.

C++ reference to class data member

No, there are no references to class members, nor are there values of type "class member". The only thing you can have is a pointer to a non-static class member (to either a data member or a member function).

The std::is_member_pointer trait summarizes this nicely: a pointer-to-member is a type T U::*, where U is a class type and T is an object or function type. (As always, there are no pointers to references.)

How to declare a reference to a member in the same class?

warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 int& rtest = test;

You need to pass the flag -std=c++11 to your compiler, otherwise it defaults to an older version of C++ which doesn't allow you to initialize class members in that way.

In function ‘int main()’: error: expected primary-expression before ‘.’ token std::cin >> Test.rtest;
error: expected primary-expression before ‘.’ token std::cout << "\n" << Test.rtest << "\n";

This is because the . operator wants an instance of your class, not the class itself (that's what :: would be for). Declare e.g. Test test; and use test.rtest instead.

C++ reference to volatile object - reasons and effects

The member function must be volatile qualified to be called from a volatile object:

int not_a_member;

struct vClass {
int i;
void set(int j) {
i=j; //i is not accessed as a volatile
static_assert(std::is_same_v<decltype((i)),int&>);
}
void set_v(int j) volatile{
i=j; //here i is accessed as a volatile
static_assert(std::is_same_v<decltype((i)),volatile int&>);
not_a_member=j;//here not a volatile access because "not_a_member" is
// not a member.
//To understand what happen, since you are a C programmer it is going to be simple.
//The volatile qualifier is actualy apply to the "this" pointer,
// which is a pointer to the object from which this member function is
// called. So inside this function "this" as the type "volatile vClass"
//Inside a member function, all access to member data, as "i" are
//actualy short ends for "this->i". So in this access, "i"
//adopt the volatile qualifier of "this".
//So the volatile qualifier just applies to the data member of the object.
}
}

void use_vClass(){
volatile vClass x;
x.set(10); //Do not compile: "Error:try to access volatile object as non volatile"
x.set_v(10); //Compile
}

So since from a volatile object or reference, you can just call volatile qualified member function, all data member access will be "volatile".



Related Topics



Leave a reply



Submit