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?
decltype returnsIf what we pass to decltype is the name of a variable (e.g. decltype(x) above) or function or denotes a member of an object ( decltype x.i ), then the result is the type of whatever this refers to. As the example of decltype(y) above shows, this includes reference, const and volatile specifiers.
The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a template function whose return type depends on the types of its template arguments.
decltype(auto) is primarily useful for deducing the return type of forwarding functions and similar wrappers, where you want the type to exactly “track” some expression you're invoking.
decltype is a compile time evaluation (like sizeof ), and so can only use the static type.
[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 bye
. If there is no such entity, or ife
names a set of overloaded functions, the program is ill-formed;— otherwise, if
e
is an xvalue,decltype(e)
isT&&
, whereT
is the type ofe
;— otherwise, if
e
is an lvalue,decltype(e)
isT&
, whereT
is the type ofe
;— otherwise,
decltype(e)
is the type ofe
.
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]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With