Reputation: 121
I'm writing a templated matrix class using C++14. This class has three template parameters: the type of data stored (dtype), the number of rows (N) and the number of columns (M).
The class signature is
template<class dtype, size_t N, size_t M>
class Matrix
I've written a determinant member function that calls specific cases when a template parameter has a certain value. For example, when the number of rows is 1 it returns a copy of the matrix itself. Alternatively, when the number of rows is 2 or 3 it returns a 1x1 matrix of the same datatype with the determinant. Finally, when the number of rows is more than 3 it uses a recursive method to calculate the determinant based on the cofactor expansion of the determinant.
I am doing this as an exercise to better learn C++14 so I'd be very grateful for some help.
The code snippet causing issues is this part right here:
Matrix<dtype, 1, 1> det() const {
if (N != M || N >= 12) {
return Matrix<dtype, 1, 1>();
} else if (N == 1) {
return this->copy();
} else if (N == 2) {
return Matrix<dtype, 1, 1>(this->get(0, 0) * this->get(1, 1) - this->get(0, 1) * this->get(1, 0));
} else if (N == 3) {
return Matrix<dtype, 1, 1>(
this->get(0, 0) * (this->get(1, 1) * this->get(2, 2) - this->get(1, 2) * this->get(2, 1)) -
this->get(0, 1) * (this->get(1, 0) * this->get(2, 2) - this->get(1, 2) * this->get(2, 0)) +
this->get(0, 2) * (this->get(1, 0) * this->get(2, 1) - this->get(1, 1) * this->get(2, 0)));
} else if (N < 12) {
Matrix<dtype, 1, 1> determinant;
Matrix<dtype, N - 1, N - 1> sub_matrix;
for (size_t i = 0; i < N; ++i) {
sub_matrix = this->drop_cross(i, i);
Matrix<dtype, 1, 1> sub_det(sub_matrix.det());
if (i % 2 == 0) determinant = determinant + (this->get(0, i) * sub_det);
else if (i % 2 == 1) determinant = determinant - (this->get(0, i) * sub_det);
}
return determinant;
}
}
This function is called by this code:
#include "lin_alg_classes.h"
int main() {
Matrix<double, 3, 3> test3(1.0, true);
std::cout << std::endl;
std::cout << test3.det();
return 0;
}
And gives the following output:
In file included from C:\Users\ekin4\CLionProjects\mt_grav\main.cpp:5:0:
C:\Users\ekin4\CLionProjects\mt_grav\lin_alg_classes.h: In instantiation of 'Matrix<dtype, 1ull, 1ull> Matrix<dtype, N, M>::det() const [with dtype = double; long long unsigned int N = 3ull; long long unsigned int M = 3ull]':
C:\Users\ekin4\CLionProjects\mt_grav\main.cpp:29:28: required from here
C:\Users\ekin4\CLionProjects\mt_grav\lin_alg_classes.h:132:31: error: could not convert 'Matrix<dtype, N, M>::copy<double, 3ull, 3ull>()' from 'Matrix<double, 3ull, 3ull>' to 'Matrix<double, 1ull, 1ull>'
return this->copy();
What I don't understand is why it is calling the N = 1 case when it should be calling the N < 12 case. I have checked braces, parentheses and semicolons, and they are all correct, but for the life of me I don't understand what is happening.
Upvotes: 0
Views: 90
Reputation: 66190
Pre c++17 (if constexpr
) you can use SFINAE and enable/disable different versions of det()
according the values of N
and M
.
Something like (sorry: not tested)
template <std::size_t A = N, std::size_t B = M>
std::enable_if_t<(A != B) || (A > 11U), Matrix<dtype, 1, 1>> det() const
{ return Matrix<dtype, 1, 1>(); }
template <std::size_t A = N, std::size_t B = M>
std::enable_if_t<(A == B) && (A == 1U), Matrix<dtype, 1, 1>> det() const
{ return this->copy(); }
// other cases
Upvotes: 1