Why can't a const T*& bind to a T*?
c++
Solution
From Paragraph 8.5.3/2 of the C++11 Standard:
A reference cannot be changed to refer to another object after initialization. Note that initialization of a reference is treated very differently from assignment to it. Argument passing (5.2.2) and function value return (6.6.3) are initializations.
This basically tells you that returning a value from a function is equivalent to performing an initialization. Therefore, function `f3()` doesn't compile for the same reason the last initialization in the code snippet below doesn't compile:
char c = 'a';
char* x = &c;
const char*& y = x; // ERROR!
The type of the object referenced by `y` is `const char*`, while the type of the expression we are trying to initialize it with (i.e. the type of `x`) is `char*`. Those are different types, and when binding a reference the types of the initializer expression and of the object referenced by the initialized reference must be identical (with an exception for base and derived classes, which are not involved here), apart from top-level cv qualifications.
Here, the `const` qualification in `const char*` is not a top-level qualification, because it applies to the pointed object, and not to the pointer itself: while the pointed `char` value cannot be modified through a `const char*` pointer, the pointer itself can be reassigned.
In Standard terms, this means that the types `const char*` and `char*` are not reference-related:
Given types “`cv1 T1`” and “`cv2 T2`,” “`cv1 T1`” is reference-related to “`cv2 T2`” if `T1` is the same type as `T2`, or `T1` is a base class of `T2`. “cv1 T1” is reference-compatible with “`cv2 T2`” if `T1` is reference-related to `T2` and `cv1` is the same cv-qualification as, or greater cv-qualification than, `cv2`. [...]
On the other hand, function `f2()` compiles, consistently with the fact that the initialization in the last line below is legal:
char c = 'a';
char* x = &c;
char* const& y = x; // OK
Here, the type of the referenced object is `char* const`, which (unlike `const char*`) is reference-compatible with `char*` in the sense defined by the Paragraph quoted above *(the `const` qualification is a top-level qualification in this case).
In Particular, per 8.5.3/5:
A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:
— If the reference is an lvalue reference and the initializer expression
- is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with “cv2 T2,” or
[...]
The omitted part is not relevant to this case. Here, `char* const` and `char*` are reference-compatible, and the initialization is legal (and `f2()` compiles). On the other hand, `const char*` and `char*` are not reference-compatible, and the initialization is illegal (and `f3()` does not compile).
Problem
VS2010 shows error C2440: `'return' : cannot convert from 'char *' to 'const char *&` in `f3` below. Why is it not possible to return a `char*` when the return type is `const char*&`? ``` const char* const& f1() { static char* x = new char[5](); return x; } char* const& f2() { static char* x = new char[5](); return x; } const char* & f3() { static char* x = new char[5](); return x; // error C2440 } char* & f4() { static char* x = new char[5](); return x; } ```