Каково обоснование поведения decltype?


как я понял в C++11 decltype(expression) используется для вывода точно такого же типа данного выражения. Но когда выражение заключено в скобки само по себе, то выводит тип ссылка 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&. Это еще больше сбивает с толку. Я не знаю, является ли это поведение является стандартным.
3 57

3 ответа:

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

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

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

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

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

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

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

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

на этот вопрос есть два ответа:

  1. Миссисипи составляет 2320 миль в длину.
  2. Миссисипи-это 11 букв.

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

от одного из авторов decltype предложение, Дж. Ярви:

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

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

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

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

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