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

В чем обоснование поведения decltype?

Как я понял в С++ 11 decltype(expression) используется для вывода точного же типа данного выражения. Но когда выражение помещается в круглые скобки, то тип deduces является ссылкой lvalue на тип выражения. Например:

int x;
decltype(x) y = x;

эквивалентно int y = x;, но

int x;
decltype((x)) y = x;

эквивалентно int& y = x;.

Соответственно

 decltype(auto) f1()
 {
   int x = 0;
   return x; // decltype(x) is int, so f1 returns int
 }

но

 decltype(auto) f2()
 {
   int x = 0;
   return (x); // decltype((x)) is int&, so f2 returns int&
 }

Какое обоснование для этого поведения выбирается стандартным комитетом?

Послесловие:

Теперь я заметил, что, по крайней мере, в случае реализации GCC 6.2, когда выражение в круглых скобках более сложное, например decltype((x + x)), выводимый тип T, но не T&, Это еще более запутанно. Я не знаю, стандартное ли это поведение.

4b9b3361

Ответ 1

Они хотели получить тип объявления идентификатора.

Они также хотели, чтобы получить тип выражения, включая информацию о том, является ли он временным или нет.

decltype(x) дает объявленный тип идентификатора x. Если вы передадите decltype то, что не является идентификатором, оно определяет тип, затем добавляет & для lvalues, && для значений x и ничего для prvalues.

Концептуально вы можете думать о нем как о различии между типом переменной и типом выражения. Но это не совсем так, как описывает стандарт.

Они могли бы использовать два разных ключевых слова для обозначения этих двух вещей. Они этого не сделали.

Ответ 2

Существует некоторая необходимость различать сущность и выражение.

Рассмотрим следующий вопрос:

Как долго длится Миссисипи?

На этот вопрос два ответа:

  • Миссисипи длиной 2320 миль.
  • Миссисипи длиной 11 букв.

Аналогично, когда вы спрашиваете о типе x, а x - это идентификатор, неясно, имеете ли вы тип, который использовался для объявления этого идентификатора (т.е. тип, связанный с именем x) или тип выражения, состоящего из единственного упоминания этого идентификатора. Фактически, вместо одного перегруженного decltype могут быть два разных ключевых слова (например, entity_type и expr_type). По какой-то причине комитет решил перегрузить decltype для этих двух разных целей.

Ответ 3

От одного из авторов предложения decltype, J. Jarvi:

Это было какое-то время, но вот что я (думаю, я) помню:

Два отдельных слова для дифференцирования этих двух видов семантики никогда не рассматривался. (Внедрение новых ключевых слов выполняется нелегко).

Что касается изменения семантики decltype((x)), обсуждение в основная рабочая группа сходилась к рассмотрению (x) как выражения, а чем идентификатор, который, возможно, более "внутренне согласован", с языковыми правилами.

Люди знали, что это может случаев, но консенсус (хотя, возможно, не все предпочтения) был в конечном итоге, соответствовать стандартам, что такое идентификатор и что такое выражение.

Пример, который вы ссылаетесь на [этот вопрос] действительно удивителен. В то время, выведя функции возвращают тип из возвращаемого выражения с помощью decltype(auto)еще не был частью языка, поэтому я не думаю, что это конкретное использование случай находился на любом радаре.