Does const pointer-to-member default to pointing to an int?

Viewed 2483

While playing with pointers-to-member I encountered a behaviour that seems slightly inconsistent and somewhat counterintuitive to me. Consider the following dummy structure:

struct foo {
    int x;
    double d;
};

and the following main():

int main() {
    int foo::* ptr = &foo::x;
    double foo::* ptr2 = &foo::d;
}

Here we have nothing unusual - two pointers to const members. The code compiles fine.

What caught my attention is that when we add const, the situation changes a little bit. Consider the following code:

int main() {
    // no int or double after const
    const foo::* ptr = &foo::x;
}

The code compiles fine on GCC 8.2.01. Notice that I did not specify to what data type the pointer will point.

However, this code:

int main() {
    // notice the only change - "d" instead of "x"
    const foo::* ptr = &foo::d;
}

fails to compile with the following error:

error: cannot convert 'double foo::*' to 'const int foo::*' in initialization const foo::* ptr = &foo::d;

Which is interesting - it suggests that, by default, a const pointer-to-member is implicitely declared to point to some int member. Is this correct, standard behaviour?

It's worth noting that if we drop the const, both of these lines produce errors:

int main() {
    foo::* ptr1 = &foo::x;
    foo::* ptr2 = &foo::d;
}

in the forms of:

error: expected unqualified-id before '*' token

error: 'ptr1' | 'ptr2' was not declared in this scope

So the question is - does the standard specify that const pointer-to-member implicitly points to int if we do not specify otherwise, or is it a non-standard behaviour? (either a GCC extension or GCC bug).


1EDIT: I am using GCC from MinGW - this particular build.

2 Answers

The code is incorrect in ISO C++, but the "implicit int" behaviour is enabled by -fms-extensions which gcc enables automatically for targeting Microsoft ABI.

You can turn it off with -fno-ms-extensions.


I checked the source code (gcc-9.1.0/gcc/cp/decl.c), it turns out that in ms-extensions mode the warning for implicit int is disabled -- anything that would have generated the message ISO C++ forbids declaration of %qs with no type is actually admitted, with int being used for the type.

This is probably a bigger hammer than was necessary to solve whatever problem it was trying to solve. You can also see the discrepancy with const *x; or const f(); for example.

I tried adding -fno-ms-extensions to the build for some of my "large" Windows projects that I use mingw-w64 for and got no errors, so perhaps it'd be good practice to give this flag as a matter of habit (or even submit a patch to mingw-w64 to have it off by default...).

So the question is - does the standard specify that const pointer-to-member implicitly points to int if we do not specify otherwise

No. GCC normally will give you the answer in plain English and refuse to compile (or emit a warning if you are using -fpermissive):

error: ISO C++ forbids declaration of 'ptr' with no type

It is not an extension. It's allowed in -fpermissive mode in order to keep very old legacy code compilable.

It seems that GCC as shipped by MinGW-w64 does not catch this error though. I don't know if it's intentional or not.

Related