Почему не работает шаблон?

kolax

Мне нужно написать шаблон, который меняет местами диагонали матрицы. При компиляции выдает ошибку и не знаю как исправить. Подскажите.

#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
template <typename t="">
T diagonal(T **array, int size) {
    T buf;
    for(int i=0;i<size;i++){ buf="array[i][i];" array[i][i]="array[i][(size-1)-i];" array[i][(size-1)-i]="buf;" }="" return="" buf;="" int="" main()="" {="" setlocale(lc_all,"russian");="" size="3;" m[size][size];="" for(int="" i="0;i<size;++i){" j="0;j<size;++j){" cout="" <<="" "ВВод="" "="" <<"="" ":";="" cin="">>m[i][j];
              }
}
     diagonal(m,size);

      for(int i=0;i</size;i++){></typename></iostream>
3 ответа

kolax

Основная ошибка не имеет отношения к шаблонам вообще. Вы, очевидно, полагаете, что к массиву вида T a[m][n] можно доступаться через "двойной указатель" T **p. Это не так. Эти типы никак не связаны вообще. Встроенный двухмерный массив в С/С++ никак не совместим с "двойным указателем".

А что желать дальше зависит от ваших намерений. Можно вообще написать просто

template <typename t="">
void diagonal(T &array, int size) {
    std::decay_t<decltype(array[0][0])> buf;
    for(int i=0;i</decltype(array[0][0])></typename>

или

template <typename t="">
void diagonal(T &array, int size) 
{
  using std::swap;
  for (int i = 0; i < size; ++i)
    swap(array[i][i], array[i][size - 1 - i]);
}
</typename>

тем самым соблюдя принцип "duck typing" шаблонного программирования: все, что нас интересует, это чтобы аргумент поддерживал lvalue выражения вида array[i][j], а уж какой конкретно тип имеет array и как он внутренне устроен нам не интересно.

(Кстати, зачем вы возвращаете последний buf из функции мне не совсем ясно.)

Но если вы хотите использовать именно T **, то от встроенного массива T a[m][n] в качестве аргумента придется отказаться. Придется строить вручную jagged array, т.е. массив указателей на массивы.

Это во-первых. Во-вторых, в С++ нет и никогда не было такого

int size=3;
int m[size][size];

Размер массива в С++ обязан быть константой времени компиляции. Даже если ваш компилятор поддерживает подобные расширенные объявления, мой вариант выше но позволить использовать такой нестандартный тип массива в качестве параметра шаблона.


kolax

T** реализуется как массив указателей на одномерные массивы, а T[][] как массив длиной size*size, отсюда два варианта на скорую руку

  1. Изменить m на динамический массив

    int **m = new int*[size];
    for (int i = 0; i < size; i++) m[i] = new int[size];
  2. Поправить шаблон и вызов

    template <typename t,="" int="" size=""> void diagonal(T array[size][size]) {...}
    diagonal<int, size="">(m);
    </int,></typename>

Может есть варианты по красивее, но на ночь не вспомнил.

  1. Можно сделать template <typename T> void diagonal(T *array, int size) { и работать с адресацией типа i*size+j


kolax

Для начала следует избавится от массивов в стиле С. Вместо них следует использовать ::std::array. Тогда функцию можно записать вот так (тип и размер выводятся):

#include <array>
#include <cstddef>

template<typename t,="" ::std::size_t="" size=""> void // ничего не возвращаем
diagonal(::std::array<::std::array<t, size="">, size> & mat)
...
constexpr const ::std::size_t size{3}; // размер массива должен быть константой времени компиляции в любом случае
::std::array<::std::array<int, size="">, size> m;
</int,></t,></typename></cstddef></array>

Если же хочется непременно с обычными массивами, то можно модифицировать так:

template<typename t,="" ::std::size_t="" size=""> void
diagonal(T ( & mat )[size][size])
</typename>

licensed under cc by-sa 3.0 with attribution.