Вот пример реализации. Это может быть возможно сделать еще короче или элегантнее, но это отправная точка. На самом деле, я только что понял, что ваши матрицы квадратные, поэтому определенно можно отбросить некоторые параметры шаблона в приведенном ниже коде.
Как я уже упоминал в своем комментарии, для C ++ 17 и выше, скорее всего, нет это вообще необходимо.
Сначала давайте определим шаблон, который мы создадим и индексируем последовательность с одним пропущенным значением (то есть строкой, которую вы хотите пропустить):
#include <utility>
// Based on https://stackoverflow.com/a/32223343.
template <size_t Offset, class T1, class T2>
struct offset_sequence_merger;
template <size_t Offset, size_t... I1, size_t... I2>
struct offset_sequence_merger<Offset, std::index_sequence<I1...>, std::index_sequence<I2...>>
: std::index_sequence<I1..., (Offset + I2)...>
{ };
template <std::size_t Excluded, std::size_t End>
using make_excluded_index_sequence = offset_sequence_merger<Excluded + 1,
std::make_index_sequence<Excluded>,
std::make_index_sequence<End - Excluded - 1>>;
Теперь давайте использовать это для извлечения подматриц:
#include <array>
template <class T, std::size_t N, std::size_t... Indices>
constexpr std::array<T, sizeof...(Indices)> extract_columns (
std::array<T, N> const & source, std::index_sequence<Indices...>) {
return { source.at(Indices)... };
}
template <class T, std::size_t N>
constexpr std::array<T, N - 1> drop_first_column (
std::array<T, N> const & source) {
return extract_columns(source, make_excluded_index_sequence<0, N>());
}
template <class T, std::size_t Rows, std::size_t Cols, std::size_t... RowIndices>
constexpr auto create_sub_matrix (
std::array<std::array<T, Cols>, Rows> const & source,
std::index_sequence<RowIndices...>)
-> std::array<std::array<T, Cols - 1>, sizeof...(RowIndices)> {
return { drop_first_column(source.at(RowIndices))... };
}
template <std::size_t ExcludedRow, class T, std::size_t Rows, std::size_t Cols>
constexpr auto create_sub_matrix (
std::array<std::array<T, Cols>, Rows> const & source)
-> std::array<std::array<T, Cols - 1>, Rows - 1> {
return create_sub_matrix(source,
make_excluded_index_sequence<ExcludedRow, Rows>());
}
И наконец, вот некоторый код, показывающий, что вышеприведенное, кажется, делает то, что должно. Вы можете увидеть это в действии на Wandbox :
#include <iostream>
#include <string>
template <class T>
void print_seq (std::integer_sequence<T> const & /* seq */) {
std::cout << '\n';
}
template <class T, T Head, T... Tail>
void print_seq (std::integer_sequence<T, Head, Tail...> const & /* seq */) {
std::cout << Head << ' ';
print_seq(std::integer_sequence<T, Tail...>{});
}
template <class T, std::size_t N>
void print_array (std::array<T, N> const & src) {
std::string sep = "";
for (auto const & e : src) {
std::cout << sep << e;
sep = " ";
}
std::cout << '\n';
}
template <class T, std::size_t N, std::size_t M>
void print_matrix (std::array<std::array<T, N>, M> const & src) {
for (auto const & row : src) { print_array(row); }
}
int main () {
auto indexSeqA = make_excluded_index_sequence<0, 3>(); print_seq(indexSeqA);
auto indexSeqB = make_excluded_index_sequence<1, 3>(); print_seq(indexSeqB);
auto indexSeqC = make_excluded_index_sequence<2, 3>(); print_seq(indexSeqC);
std::cout << '\n';
std::array<int, 3> arr = { 1, 7, 9 };
print_array(arr); std::cout << '\n';
std::array<std::array<int, 3>, 3> matrix = {{
{ 0, 1, 2 }
, { 3, 4, 5 }
, { 6, 7, 8 }
}};
print_matrix(matrix); std::cout << '\n';
print_matrix(create_sub_matrix<0>(matrix)); std::cout << '\n';
print_matrix(create_sub_matrix<1>(matrix)); std::cout << '\n';
}
Надеюсь, этого достаточно, чтобы помочь вам полностью реализовать функцию determinant
. (PS: нет необходимости явно предоставлять аргумент шаблона size_t определителю при его вызове, он будет автоматически выведен из размера его аргумента std :: array).