В чем обоснование поведения 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&
, Это еще более запутанно. Я не знаю, стандартное ли это поведение.
Ответы
Ответ 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)
еще не был частью языка, поэтому я не думаю, что это конкретное использование случай находился на любом радаре.