Why do primitive and user-defined types act differently when returned as 'const' from a function?
Because const
part is removed from primitive types returned from functions. Here's why:
In C++11 from § 5 Expressions [expr]
(p. 84):
8
Whenever a glvalue expression appears as an operand of an operator that
expects a prvalue for that operand, the lvalue-to-rvalue (4.1),
array-to-pointer (4.2), or function-to-pointer (4.3) standard conversions are
applied to convert the expression to a prvalue. [Note: because cv-qualifiers
are removed from the type of an expression of non-class type when the
expression is converted to a prvalue, an lvalue expression of type
const int can, for example, be used where a prvalue expression of type
int is required. —end note]
And similarly from § 5.2.3 Explicit type conversion (functional notation) [expr.type.conv]
(p. 95):
2
The expression T(), where T is a simple-type-specifier or
typename-specifier for a non-array complete object type or the
(possibly cv-qualified) void type, creates a prvalue of the specified
type,which is valueinitialized (8.5; no initialization is done for the
void() case). [Note: if T is a non-class type that is cv-qualified, the
cv-qualifiers are ignored when determining the type of the resulting
prvalue (3.10). —end note]
What that means is that const int
prvalue returned by g2()
is effectively treated as int
.