Что такое decltype (0 + 0)? - PullRequest
13 голосов
/ 08 мая 2011

(По запросу ответ .)

Учитывая N3290, §7.1.6.2p4, где элементы списка ненумерованы, но здесь для нашего удобства пронумерованы:

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

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

Какой тип указан в decltype (0 + 0)?

Пункт 1 не применяется, 2 могут, но если нет, то 3 не применяются, и 4 будет результатом. Итак, что такое xvalue, и 0 + 0 это xvalue?

§3.10p1:

Значение xvalue (значение «eXpiring») также относится к объекту, обычно ближе к концу его срока службы (например, чтобы его ресурсы могли быть перемещены). Xvalue - это результат некоторых видов выражений, включающих ссылки на rvalue (8.3.2).

Я не вижу в §8.3.2 ничего, что могло бы быть здесь полезным, но я знаю, что "0 + 0" не содержит ссылок на rvalue. Литерал 0 является prvalue, который является «rvalue, который не является xvalue» (§3.10p1). Я считаю, что «0 + 0» - это тоже значение. Если это правда, "decltype (0 + 0)" будет int (не int &&).

Я что-то пропустил в своей интерпретации? Правильно ли сформирован этот код?

decltype(0 + 0) x;  // Not initialized.

Код компилируется на GCC 4.7.0 20110427 и Clang 2.9 (транк 126116). Это не будет правильно сформировано, если в decltype указан тип int &&, например.

Ответы [ 5 ]

10 голосов
/ 08 мая 2011

0 + 0 - это выражение двух значений (n3290, пар. 3.10), которое применяет встроенный operator+, который в соответствии с 13.6 / 12 равен LR operator+(L,R), который, следовательно, является функцией, которая возвращает что-то, чтоне ссылка.Следовательно, результат выражения также является prvalue (согласно 3.10).

Следовательно, результат 0 + 0 является prvalue, 0 является int, поэтому результат 0 + 0 являетсяint

5 голосов
/ 08 мая 2011

Это определенно int:

#include <iostream>
#include <typeinfo>

template<typename T>
struct ref_depth
{
        enum { value = 0 };
};

template<typename T>
struct ref_depth<T&>
{
        enum { value = 1 };
};

template<typename T>
struct ref_depth<T&&>
{
        enum { value = 2 };
};

int main() {

  std::cout
    << "int: " << typeid(int).name() << "\n"
       "decltype(0 + 0): " << typeid(decltype(0 + 0)).name() << "\n"
       "int&&: " << typeid(int&&).name() << "\n";
  std::cout 
    << "ref_depth: int: " << ref_depth<int>::value << "\n"
       "ref_depth: decltype(0 + 0): " << ref_depth<decltype(0 + 0)>::value << "\n"
       "ref_depth: int&&: " << ref_depth<int&&>::value << "\n";

}

Вывод:

int: i
decltype(0 + 0): i
int&&: i
ref_depth: int: 0
ref_depth: decltype(0 + 0): 0
ref_depth: int&&: 2
2 голосов
/ 30 мая 2011

Начиная с 5.19 [expr.const], каждое буквенное константное выражение является prvalue.

A выражение константы литерала - это постоянное базовое выражение константы литерального типа, но не типа указателя. целочисленное константное выражение является буквенным константным выражением целочисленного или незаданного типа нумерации.

Следовательно, правило 4 применяется ко всем буквальным константным выражениям.

2 голосов
/ 08 мая 2011

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

decltype(0 + 0) x;

равно

decltype(0) x;

, что равно

int x;
0 голосов
/ 08 мая 2011

GCC говорит: int -

Код:

#include <iostream>
#include <typeinfo>

int
main ()
{
  int n;
  decltype(0 + 0) x;
  std::cout << "Type of `n': " << typeid(n).name() << std::endl;
  std::cout << "Type of `x': " << typeid(x).name() << std::endl;
}

Выход:

i

i

Изменить: Это имеет смысл в соответствии с пунктом 4, но я не могу точно сказать, что пункт 2 на самом деле не тот, который действует.Из того, что я могу сказать, 0 + 0 оценивается как 0, а тип 0 равен int, так что это объявленный тип.

...