The basic error is not related to patterns at all. You obviously believe that an array of the form T a[m][n] can be accessed through the "double pointer" T **p . This is not true. These types are not related at all. The built-in two-dimensional array in C / C ++ is not compatible with "double pointer" at all.
And what to wish further depends on your intentions. You can even write just
template <typename T> void diagonal(T &array, int size) { std::decay_t<decltype(array[0][0])> 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; } }
or
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]); }
thus, following the principle of "duck typing" of template programming: all that interests us is that the argument supports lvalue expressions of the form array[i][j] , and what type exactly has an array and how it is internally organized is not interesting for us.
(By the way, why are you returning the last buf from the function is not entirely clear to me.)
But if you want to use T ** , then the built-in array T a[m][n] as an argument will have to be abandoned. You have to build the jagged array manually, i.e. array of pointers to arrays.
This is the first. Secondly, in C ++ there is never such a thing.
int size=3; int m[size][size];
The size of the array in C ++ must be a compile-time constant. Even if your compiler supports such extended declarations, my option is higher, but allow using such a non-standard array type as a template parameter.