Подтвердить что ты не робот

Каков результат decltype ( "Hello" )?

Я получаю неожиданные результаты от всех компиляторов, на которых я пробовал следующее (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!"
        );
}

Я бы ожидал, что утверждение времени компиляции не должно срабатывать, но это так. В конце концов, этого нет (как и ожидалось):

#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!"
        );
}

Итак, каков результат decltype("Hello") в соответствии со стандартом С++ 11 (ссылки высоко ценятся)? Что я должен сравнивать с тем, чтобы не было выполнено утверждение времени компиляции?

4b9b3361

Ответ 1

[Примечание: Первоначально это не было вопросом для ответа на вопрос; Мне просто удалось найти ответ сам, пока я описывал свои попытки расследовать, и я подумал, что было бы неплохо поделиться им.]

В соответствии с Приложением C (2.14.5) стандарта С++ 11:

Тип строкового литерала изменяется от "array of char" до " массива const char." [....]

Кроме того, в пункте 7.1.6.2/4 указано (о результате decltype):

Тип, обозначенный символом decltype(e), определяется следующим образом:

- если e является несвязанным id-выражением или несвязанным доступом к члену класса (5.2.5), decltype(e) - это тип объекта с именем e. Если такой объект отсутствует или если e называет набор перегруженных функций, программа плохо сформирована;

- в противном случае, если e является значением x, decltype(e) является T&&, где T является типом e;

- в противном случае, если e является lvalue, decltype(e) является T&, где T является типом e;

- в противном случае decltype(e) является типом e.

Поскольку строковые литералы являются lvalues ​​, согласно вышеприведенному абзацу и абзацу из приложения C, результат decltype("Hello") является lvalue ссылается на массив размером 6 постоянных узких символов:

#include <type_traits>

int main()
{
    // This will NOT fire
    static_assert(
        std::is_same<decltype("Hello"), char const (&)[6]>::value, 
        "Error!"
        );
}

Наконец, хотя переменная hello также является lvalue, второе утверждение времени компиляции из текста вопроса не срабатывает, потому что hello - это unparenthesized id-expression, что заставляет его попадать в первый элемент вышеупомянутого перечня из пункта 7.1.6.2/4. Следовательно, результатом decltype(hello) является тип объекта с именем hello, который равен char const[6].