Шаблоны — Компилирует vs во время выполнения константное назначение переменных и распределение vlas в переполнении стека

Я работал над шаблонной функцией с нетиповыми параметрами (чтобы избежать динамического размещения массивов), когда возник ряд вопросов. Мой первый вопрос касается назначения переменных во время компиляции. Это произошло из-за следующих попыток вызова функции шаблона:

template<int n>
int *getDegrees(int A[][n]) {
//return degrees
}

int main(int argc, char **argv) {
int n = 10;
int A[n][n];
int *degs = getDegrees<n>(A);
}

Здесь у нас есть две ошибки: во-первых, компилятор не может разрешить вызов getDegrees(A):

main.cc:27: error: no matching function for call to ‘getDegrees(int [(((long unsigned int)(((long int)n) + -0x00000000000000001)) + 1)][(((long unsigned int)(((long int)n) + -0x00000000000000001)) + 1)])’

Во-вторых, мы не можем использовать n в вызове шаблона, так как это не постоянное выражение. Просто делая n константа решает проблемы

const int n = 10;

однако, если бы я должен был сделать

int m = 10;
const int n = m;

мы получаем те же ошибки. Хотя второе присваивание может быть разрешено компилятором, считается ли это плохой формой для этого? Кроме того, зачем делать n постоянная разница в разрешении вызова функции?

Мой другой вопрос касается vlas: выделена ли для них память в стеке или куче (и зависит ли это от компилятора)? Похоже, были некоторые противоречия даже в том, чтобы разрешить их в C ++, следует ли их избегать в пользу векторов (или подобных контейнеров)?

Цени любое понимание!

0

Решение

Я постараюсь ответить на все, что смогу получить от вашего вопроса.
Вы можете изменить прототип функции для получения массива по ссылке:

template<size_t n> // see the type
int *getDegrees(int (&A)[n][n]) {  // see the signature
// ...
}

В приведенном выше коде мы используем тот факт, что массив имеет одинаковые размеры.
Однако в общем случае это должно быть:

template<size_t n1, size_t n2> // see the type
int *getDegrees(int (&A)[n1][n2]) {  // see the signature
// ...
}

Если размер слишком велик, то компилятор выдаст сообщение об ошибке. например (из g ++):

ошибка: размер массива «A» слишком велик

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

const int n = 10;

выполняет это требование. Поскольку компилятор может разобрать это, 10 — это буквальное число, присваиваемое n,

В случае,

int m = 10;
const int n = m;

Компилятор узнает, что источник n является не сама константа времени компиляции. И, таким образом, это делает код плохо сформированным.

5

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

Других решений пока нет …

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