Что такое decltype (0 + 0)?

(Запрос .)

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

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

  • Если e - это неравномерное id-выражение или unparenthesized class member access (5.2.5), decltype (e) - это тип объекта, названного e. Если такой объект отсутствует или если e называет набор перегруженных функций, программа плохо сформирована;
  • в противном случае, если e является значением x, decltype (e) является T & &, где T - тип e;
  • в противном случае, если e является lvalue, decltype (e) является T &, где T - тип e;
  • иначе, decltype (e) - тип e.

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

Пункт 1 не применяется, 2 может, но если нет, то 3 не применяется, а 4 - результатом. Итак, что такое xvalue и равно 0 + 0 xvalue?

§3.10p1:

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

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

Я что-то пропустил в своей интерпретации? Является ли этот код хорошо сформированным?

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

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

Ответ 1

Из 5.19 [expr.const] каждое литеральное постоянное выражение является prvalue.

Литеральное постоянное выражение представляет собой выражение константы основного значения типа prvalue типа literal, но не тип указателя. Интегральное постоянное выражение представляет собой литеральное постоянное выражение интегрального или неперечисленного типа перечисления.

Поэтому правило 4 применяется ко всем литералам с постоянными выражениями.

Ответ 2

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

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

Ответ 3

Это определенно 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

Ответ 4

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

decltype(0 + 0) x;

равно

decltype(0) x;

который равен

int x;

Ответ 5

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;
}

Вывод:

я

я

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