Причина, по которой вы не можете этого сделать, заключается в том, что new int[3]
уже выделяет именно то, что вам нужно, объект типа int[3]
.Просто то, что new-выражение возвращает , является указателем на его первый элемент.5.3.4 / 1:
Если объект не является объектом массива, выражение new возвращает указатель на созданный объект.Если это массив, новое выражение возвращает указатель на начальный элемент массива.
Возвращение указателя на первый элемент - это то, что позволяет 3
быть неизвестным до времени выполнения,поэтому я предполагаю, что, зная это заранее, вы опрокинули гибкость, которой не пользуетесь.
Полагаю, что для этого нужно переосмыслить обратно в нужный вам тип указателя (не обязательно переносимый)или выделить структуру, содержащую int[3]
(и использовать указатель на его член данных).
[Edit: er, yes или идея FredOverflow, которая не имеет ни недостатка, но требует использования delete[]
вместо delete
.]
Полагаю, мораль в том, что если вы пишете шаблоны, которые наивно выделяют какой-то неизвестный тип T
с помощью new
, то шаблон не будет работать, когда кто-то передает массиввведите T
.Вы будете назначать его неверному типу указателя, и если вы исправите это (возможно, с помощью auto
), вы удалите его неправильно.
Отредактируйте в ответ на вопрос j_kubik:
Вот один из способов различения массивов и не массивов.Если вы напишите такую функцию, которая возвращает объект, который содержит указатель и способен его правильно удалить, то у вас есть универсальный новый / удалить для любого типа T.
#include <iostream>
template <typename T>
void make_thing_helper(T *) {
std::cout << "plain version\n";
}
template <typename T, int N>
void make_thing_helper(T (*)[N]) {
std::cout << "array version\n";
}
template <typename T>
void make_thing() {
make_thing_helper((T*)0);
}
int main() {
typedef int T1;
typedef int T2[3];
make_thing<T1>();
make_thing<T2>();
}