А) Это работает:
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, оба, похоже, не работают, как я ожидал, во всех случаях.
или стандартная функция 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]
- Для выражения
е
тип обозначен
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];
* a — указатель на int, поэтому не могу вызвать typeof для него таким образом
int *a = new int[5];
работает, потому что вы показываете целое число и объявляете новый массив размера 5 на месте, где показывает
может быть, вы хотели:
typeof(new typeof(int *)[5])a;
вместо
int * a = new typeof(*a)[5];