2013-02-24 5 views
35

Я получаю неожиданные результаты от всех компиляторов, на которых я пробовал следующее (GCC 4.7.2, GCC 4.8.0 беты, ICC 13.0.1, Clang 3.2, VC10):Каков результат decltype («Привет»)?

#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") в соответствии с C++ 11 Standard (ссылки высоко оценили)? Что я должен сравнивать с тем, чтобы не приводило к тому, что утверждение времени компиляции не срабатывает?

ответ

29

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

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

Тип строки буквальной изменяется с «массива полукокса» до «массива сопзИте полукокс «[....]

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

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

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

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

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

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

С string literals are lvalues, в соответствии с вышеуказанным пунктом и пунктом из приложения С, результатом decltype("Hello") является именующей ссылка на массив размера 6 постоянных узких символы:

#include <type_traits> 

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

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

+0

Эти правила имеют смысл, когда вы думаете о написании 'decltype (expr) &&'. –

+1

@KerrekSB: Да. Я просто нашел это удивительным, потому что я как бы привык думать в грубых терминах «строковый литерал имеет тип' const char [] ',' decltype (x) 'возвращает тип' x', поэтому 'decltype (" hello ")' должен возвращать 'const char [6]' ", забывая детали. Выученный урок (надеюсь) –

+3

+1 как на вопрос, так и на ответ. Я обещаю, что больше не буду использовать компилятор C++. – 2013-02-24 00:28:26

 Смежные вопросы

  • Нет связанных вопросов^_^