Ошибка компилятора при определении массива с использованием typeof и decltype

А) Это работает:

int main() {
int * a = new int[5];
delete[] a;
return 0;
}

Б) Это ошибки:

int main() {
int * a = new typeof(*a)[5];
delete[] a;
return 0;
}

с ошибкой: недопустимые типы ‘int [int]’ для индекса

В) это работает:

int main() {
int * a = new typeof(a)[5];
delete[] a;
return 0;
}

Я не могу понять, почему B терпит неудачу, потому что после раскрытия оператор должен выглядеть так:

int *a = new int[5];

так как typeof(*a) это инт.

Вот эксперимент с decltype:

D) Это не работает:

int main() {
int * a = new decltype(a)[5];
delete[] a;
return 0;
}

с ошибкой: невозможно преобразовать int ** в int * при инициализации. Это ожидается, учитывая, что decltype (a) имеет тип int *, поэтому он переводится в int *a = new int*[5]; что неверно.

E) Но это не работает:

int main() {
int * a = new decltype(*a)[5];
delete[] a;
return 0;
}

с ошибкой: новый нельзя применить к ссылочному типу

Так что, будь то расширение GCC или стандартная функция C ++ 11, оба, похоже, не работают, как я ожидал, во всех случаях.

4

Решение

или стандартная функция C ++ 11, и то и другое, похоже, не работает согласно моим ожиданиям во всех случаях.

Тогда у вас неправильные ожидания — по крайней мере, в случае decltype, Я не знаю, как ГКК typeof работает, поэтому я не могу ответить, почему B) работает, но C) не делает, но D) и E) ведут себя в соответствии со стандартом.

D) Выражение, данное decltype в этом примере a, a это имя переменной. Другими словами, это id-выражение. В случае id-выражения decltype разрешается к типу объекта. Тип a является int*, Следовательно new decltype(a)[5]; создает массив int*, Потому что тип a не int**, он не может указывать на массив int*,

E) выражение, данное decltype в этом примере *a, Тип (T) выражения int, Но *a не является именем переменной. Это не id-выражение вроде a является. Ценовая категория *a это значение. В случае lvalue-выражения, decltype решает в T& где T тип выражения. Следовательно, decltype(*a) является int&, Массивы ссылок не допускаются, поэтому new decltype(*a)[5] не допускается.

Вот цитата из стандарта (черновик):

§ 7.1.6.2 [dcl.type.simple]

  1. Для выражения
    е
    тип обозначен
    decltype (е)
    определяется следующим образом:


если
е
это без скобок
ID-выражение
или доступ к элементу класса без скобок (
5.2.5
),
decltype (е)
это тип объекта, названный
е
, Если такой организации нет, или если
е
называет набор перегруженных функций
программа плохо сформирована;


в противном случае, если
е
это xvalue,
decltype (е)
является
T&&
, где
T
это тип
е
;


в противном случае, если
е
это значение,
decltype (е)
является
T&
, где
T
это тип
е
;


иначе,
decltype (е)
это тип
е

Это было бы правильно:

int * a = new std::remove_pointer<decltype(a)>::type[5];

а также это:

int * a = new std::remove_reference<decltype(*a)>::type[5];

Конечно, оба они довольно бессмысленно сложны. Если ваша цель состоит в том, чтобы избежать повторения типа, то decltype это не тот инструмент, который вы должны искать. Инструмент, который соответствует вашим потребностям auto:

auto a = new int[5];
2

Другие решения

* a — указатель на int, поэтому не могу вызвать typeof для него таким образом

int *a = new int[5];

работает, потому что вы показываете целое число и объявляете новый массив размера 5 на месте, где показывает

может быть, вы хотели:

typeof(new typeof(int *)[5])a;

вместо

 int * a = new typeof(*a)[5];
1

По вопросам рекламы [email protected]