Look at this simple example:
template <typename T>
const T const_create() {
return T();
}
struct Foo { };
int main() {
auto &x = const_create<Foo>(); // compiles
// auto &x = const_create<int>(); // doesn't compile
}
Why does the version with Foo
compile, but with int
doesn't? In other words, why does const
get removed from the return type of const_create<int>
? It works like if it returned int
, not const int
. Isn't this an inconsistency in the language?
Where does the standard mandate this behavior?
[expr]/6 says:
If a prvalue initially has the type ācv
T
ā, whereT
is a cv-unqualified non-class, non-array type, the type of the expression is adjusted toT
prior to any further analysis.
Therefore, the const Foo
prvalue is just const Foo
, but const int
prvalue is adjusted to int
.
This rule was changed in C++14 by CWG 1261 to exclude array types. Previously, N3337 [basic.lval]/4 read:
Class prvalues can have cv-qualified types; non-class prvalues always have cv-unqualified types. Unless otherwise indicated ([expr.call]), prvalues shall always have complete types or the
void
type; in addition to these types, glvalues can also have incomplete types.