I was trying to validate this statement (my emphasis) in paragraph §5.1.1/8 (page 87) of the C++11 Standard
A nested-name-specifier that denotes a class, optionally followed by the keyword template (14.2), and then followed by the name of a member of either that class (9.2) or one of its base classes (Clause 10), is a qualified-id; 3.4.3.1 describes name lookup for class members that appear in qualified-ids. The result is the member. The type of the result is the type of the member. The result is an lvalue if the member is a static member function or a data member and a prvalue otherwise.
with the following snippet:
#include <iostream>
namespace N {
class A {
public:
int i;
void f();
};
}
int main()
{
std::cout << &N::A::f << '\n';
std::cout << &N::A::i << '\n';
}
clang
and gcc
compile this code and VS2013
requires the definition of the member function f
.
All three of them print
1
1
but I have no idea where these numbers come from.
According to the paragraph highlighted above the expressions N::A::f
is a prvalue, as f
is not a static member function. Nonetheless, I was able to take its address in the code.
At the same time, in §5.3.1/3 one reads (emphasis mine):
The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C::m.
which gives the impression that neither N::A::f
nor N::A::i
are lvalues, as they are qualified-ids.
but I have no idea where these numbers come from.
Pointer-to-members aren't pointers. No operator<<
can output their original value, the best and only match is the one that outputs bool
values. Thus they are converted to bool
(which obviously yields true
) and the output is 1
. Try to insert std::boolalpha
and check the output again.
Nonetheless, I was able to take its address in the code.
How is that a surprise to you? You quoted the part that allows and explains this exact construct. It clearly states that taking the adress of a qualified-id that names a non-static member designates that member.
qualified-ids are not only lvalues or rvalues. It completely depends on context. If they designate non-static members from outside that members class or any subclass of it, they have to be prvalues as they don't designate any specific object but rather a value (or information, in other words -- the type and an offset).