I am reading the C++11 draft standard and the section on [expr.typeid] mentions the following (emphasis mine):
[...]
When typeid is applied to an expression other than a glvalue of a polymorphic class type, the result refers to a std::type_info object representing the static type of the expression. Lvalue-to-rvalue (4.1), array-topointer (4.2), and function-to-pointer (4.3) conversions are not applied to the expression. If the type of the expression is a class type, the class shall be completely-defined. The expression is an unevaluated operand (Clause 5).
When typeid is applied to a type-id, the result refers to a std::type_info object representing the type of the type-id. If the type of the type-id is a reference to a possibly cv-qualified type, the result of the typeid expression refers to a std::type_info object representing the cv-unqualified referenced type. If the type of the type-id is a class type or a reference to a class type, the class shall be completely-defined.
Further in p5 of the same section, it goes on to give the following example:
class D { /* ... */ };
D d1;
const D d2;
typeid(d1) == typeid(d2); // yields true
typeid(D) == typeid(const D); // yields true
typeid(D) == typeid(d2); // yields true
typeid(D) == typeid(const D&); // yields true -- (1)
Given the following code sample:
int main()
{
int foo = 42;
int &bar = foo;
bool comp1 = (typeid(int) == typeid(int&)); // Yields true, same as (1) -- (2)
bool comp2 = (typeid(foo) == typeid(bar)); // Yields true, Why? -- (3)
}
My understanding is that [expr.typeid]p4 talks only about the form typeid(type-id) and bar
in typeid(bar)
is an id-expression and not a type-id. Why does (3) above evaluate to true
? Which text in the standard covers this? What have I missed?
The answer is in [expr]
5 If an expression initially has the type “reference to T” ([dcl.ref], [dcl.init.ref]), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.
So when we get into [expr.typeid]
3 When typeid is applied to an expression other than a glvalue of a polymorphic class type, the result refers to a std::type_info object representing the static type of the expression. Lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) conversions are not applied to the expression. If the type of the expression is a class type, the class shall be completely-defined. The expression is an unevaluated operand (Clause [expr]).
The id-expression in question is already of the referenced type when typeid
examines it.