Why are class static functions not in the scope of the class?

  • Thread starter Shriramana Sharma
  • Start date
S

Shriramana Sharma

Hello. Please see the following code:


struct A { static int i ; } ;
int A::* ip = & A::i ;


I get the following errors with GCC 4.7.3 and Clang 3.2:

GCC: error: cannot convert ‘int*’ to ‘int A::*’ in initialization

Clang: error: cannot initialize a variable of type 'int A::*' with an rvalue of type 'int *'

I thought members of a class are in its scope. Reading §9.4 (class.static) of C++11 doesn't help me any since it doesn't seem to speak about the scope of static members. Even §3.3 (basic.scope) and §3.3.7 (basic.scope.class) doesn't seem to help me.

What am I missing? Please help. Thanks.
 
M

Marcel Müller

Hello. Please see the following code:

struct A { static int i ; } ;
int A::* ip =& A::i ;

First of all you are not talking about functions here. i is a class data
member of A. However, this makes no important difference for the following.
I get the following errors with GCC 4.7.3 and Clang 3.2:

GCC: error: cannot convert ‘int*’ to ‘int A::*’ in initialization

Clang: error: cannot initialize a variable of type 'int A::*' with an rvalue of type 'int *'

Static class members have different types than class instance members.
This has technical reasons, but also a semantic difference.

The type int A::* may point to any integer member within class A or it's
base classes (if there are any). It will never point to any integer
directly. It is a open instance reference to an integer inside A. I.e.
with int A::* you can access a non-static integer in A using a *class
instance* of type A (or a subclass of A).
It is more like an array index, i.e. take the /4th/ integer in A, than
like a pointer.

If you want to dereference a int A::* you will /always/ need an object
of type A (or subclass) because int A::* only tells /which/ integer of A
to access but not of /which instance of A/.
A a;
a.*ip = 7;

In theory one could define a semantic that also allows int A::* to point
to a static member of A. But you would still need an instance of A to
dereference the pointer, because you can't be sure that it refers only
to a static int. C++ avoids things like this because it would only add
more confusion. Furthermore there would be a significant runtime overhead.

The type int* in contrast may point to any single integer outside a
class or to any static integer in a class or also to any integer of a
class *instance.*
I thought members of a class are in its scope.

They are, but this only belongs to name resolution and access modifiers.
It doesn't change the type of the objects.


Marcel
 
S

Shriramana Sharma

This is not about scope. The scope part (&A::i) was resolved just fine.
It is the assignment part which causes problems, as you want to assign
the result to a variable of a wrong type.

Try
auto ip = & A::i ;
or
int* ip = & A::i ;

Um thanks for your reply people. So IIUC int A::* is valid only within an Aobject, and the layout of A actually affects the contents of the pointer because you've called it an offset from the address location of the first byte of the object. So I should read int A::* as "a pointer within A to an integer" rather than "a point to an integer within A".

Further to your feedback I also tried the following code which gave the following errors:

struct A { int i ; static int si ; } ;
int * ip = & A:: i ; // error: can't convert int A::* to int*
int * sip = & A::si ;
int A::* aip = & A:: i ;
int A::* asip = & A::si ; // error: can't convert int* to int A::*

and I understand it now, sort of...
 
M

Marcel Müller

struct A { int i ; static int si ; } ;
int * ip =& A:: i ; // error: can't convert int A::* to int*
int * sip =& A::si ;
int A::* aip =& A:: i ;
int A::* asip =& A::si ; // error: can't convert int* to int A::*

Only for completion, there is a third valid variant:

A a;
int * ip2 =& a.i;

In this case ip2 refer to i in exactly this single instance of A. As
anyy other Pionter it gets invalid as soon as the object it refers to
gets invalid.

In Contrast the int A::* references never get invalid because they refer
to a compile time Objekt, the Declaration of i within A. This is similar
to function pointers. They always refer to compile time objects as well
- as long as you don't write self modifying code, of course.


Marcel
 
B

Bart van Ingen Schenau

Um thanks for your reply people. So IIUC int A::* is valid only within
an A object, and the layout of A actually affects the contents of the
pointer because you've called it an offset from the address location of
the first byte of the object. So I should read int A::* as "a pointer
within A to an integer" rather than "a point to an integer within A".

That is right. The type 'A::*' is called a pointer-to-member (of A), but
it would be more correct to call it a pointer-to-non-static-member (of A).

Bart v Ingen Schenau
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top