I am making an interesting task with the matrix. But now I'm stuck with the code below. I want to make different behavior depending on the enum type.
My types:
using Matrix = std::vector<std::vector<int>>;
using Row = std::vector<int>;
enum class Diagonal {MAIN, ANTI};
First behavior.
This portion of code runs when diagonal == Diagonal::MAIN
:
size_t diagonalSum(const Matrix& matrix, Diagonal diagonal) {
assert(isSquare(matrix));
size_t sum = 0;
auto startRow = matrix.cbegin();
for(auto row = startRow; row != matrix.end(); ++row) {
for(auto column = row->cbegin(); column != row->end(); ++column) {
if(std::distance(firstRow, row) == std::distance(row->cbegin(), column)) {
sum += *column;
}
}
}
return sum;
}
Second behavior.
This portion of code runs when diagonal == Diagonal::ANTI
:
size_t diagonalSum(const Matrix& matrix, Diagonal diagonal) {
assert(isSquare(matrix));
size_t sum1 = 0;
auto startRow = matrix.cbegin();
for(auto row = startRow; row != matrix.cend(); ++row) {
for(auto column = row->crbegin(); column != row->crend(); ++column) {
if(std::distance(startRow, row) == std::distance(row->crbegin(), column)) {
sum1 += *column;
}
}
}
return sum;
}
The only difference in the code snippets shown above is that they use different iterators to traverse the columns.
I thought such a small difference between calculating the sum of the main diagonal and the antidiagonal will help me write neat code, to customise the behavior of the function diagonalSum
easily.
After reading about templates, I understood that it cannot help me. So the only way is to overload the function. Am I right?
But how to do it with the one enum? Should I make more types to perform overloading but unfortunately this is not so neat.
答案 0 :(得分:3)
已经存在累积的算法,因此您可以执行以下操作:
size_t diagonalSum(const Matrix& matrix, Diagonal diagonal) {
assert(isSquare(matrix));
std::size_t i = 0;
switch (diagonal) {
case Diagonal::MAIN:
return std::accumulate(matrix.cbegin(), matrix.cend(), 0u,
[&](std::size_t acc, const auto& row) {
return acc + row[i++];
});
case Diagonal::ANTI:
return std::accumulate(matrix.cbegin(), matrix.cend(), 0u,
[&](std::size_t acc, const auto& row) {
return acc + row[row.size() - i++];
});
}
}
答案 1 :(得分:0)
我决定用矩阵进行某种计算的想法。
因此您可以轻松添加功能。它们打包在Finction商店中。您可以使用enum
解压缩它们。
定义打包到功能库中的功能。
enum class ComputationMode {MAIN_DIAGONAL_SUM, ANTI_DIAGONAL_SUM};
std::size_t calculateMainDiagonalSum(const Matrix& matrix) {
auto firstRow = matrix.cbegin();
auto lastRow = matrix.cend();
std::size_t sum = 0;
for(auto row = firstRow; row != lastRow; ++row) {
auto firstColumn = row->cbegin();
auto lastColumn = row->cend();
for(auto column = firstColumn; column != lastColumn; ++column) {
if(std::distance(firstRow, row) == std::distance(firstColumn, column)) {
sum += *column;
}
}
}
return sum;
}
std::size_t calculateAntiDiagonalSum(const Matrix& matrix) {
auto firstRow = matrix.cbegin();
auto lastRow = matrix.cend();
std::size_t sum = 0;
for(auto row = firstRow; row != lastRow; ++row) {
auto firstColumn = row->crbegin();
auto lastColumn = row->crend();
for(auto column = firstColumn; column != lastColumn; ++column) {
if(std::distance(firstRow, row) == std::distance(firstColumn, column)) {
sum += *column;
}
}
}
return sum;
}
打包到功能库中。
static std::map<ComputationMode, std::function<int(const Matrix&)>> functionStore = {
{ComputationMode::MAIN_DIAGONAL_SUM, &calculateMainDiagonalSum},
{ComputationMode::ANTI_DIAGONAL_SUM, &calculateAntiDiagonalSum}
};
使用上述代码的基本功能。
size_t computeMatrix(const Matrix& matrix, ComputationMode mode) {
size_t result = 0;
if(functionStore.find(mode) != functionStore.end()) {
result = functionStore[mode](matrix);
} else {
std::cerr << "Computation error. No proper computation function with this mode" << std::endl;
assert(false);
}
return result;
}
使用示例。
auto mainDiagonalSum = computeMatrix(matrix, ComputationMode::MAIN_DIAGONAL_SUM);
auto antiDiagonalSum = computeMatrix(matrix, ComputationMode::ANTI_DIAGONAL_SUM);