I'm getting unexpected results from all compilers on which I tried the following (GCC 4.7.2, GCC 4.8.0 beta, ICC 13.0.1, Clang 3.2, VC10):
#include <type_traits>
int main()
{
// This will fire
static_assert(
std::is_same<decltype("Hello"), char const[6]>::value,
"Error!"
);
}
I would have expected the compile-time assertion above not to fire, but it does. After all, this one does not (as expected):
#include <type_traits>
int main()
{
char const hello[6] = "Hello";
// This will not fire
static_assert(
std::is_same<decltype(hello), char const[6]>::value,
"Error!"
);
}
So what is the result of decltype("Hello")
according to the C++11 Standard (references are highly appreciated)? What should I compare it to so that the compile-time assertion above doesn't fire?
[Note: Originally, this was not meant to be a self-answered question; I just happened to find the answer myself while I was describing my attempts to investigate, and I thought it would have been nice to share it.]
According to Annex C (2.14.5) of the C++11 Standard:
The type of a string literal is changed from “array of char” to “array of const char.” [....]
Moreover, Paragraph 7.1.6.2/4 specifies (about the result of decltype
):
The type denoted by decltype(e)
is defined as follows:
— if e
is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e)
is the type of the entity named by e
. If there is no such entity, or if e
names a set of overloaded functions, the program is ill-formed;
— otherwise, if e
is an xvalue, decltype(e)
is T&&
, where T
is the type of e
;
— otherwise, if e
is an lvalue, decltype(e)
is T&
, where T
is the type of e
;
— otherwise, decltype(e)
is the type of e
.
Since string literals are lvalues, according to the above Paragraph and the Paragraph from Annex C, the result of decltype("Hello")
is an lvalue reference to an array of size 6 of constant narrow characters:
#include <type_traits>
int main()
{
// This will NOT fire
static_assert(
std::is_same<decltype("Hello"), char const (&)[6]>::value,
"Error!"
);
}
Finally, even though the hello
variable is also an lvalue, the second compile-time assertion from the question's text does not fire, because hello
is an unparenthesized id-expression, which makes it fall into the first item of the above list from Paragraph 7.1.6.2/4. Therefore, the result of decltype(hello)
is the type of the entity named by hello
, which is char const[6]
.