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 initializationconst 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 '
*
' tokenerror: '
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.
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...).