Reputation:
I have a banded matrix class, which inherits from a abstract matrix class
template <typename T, std::size_t R, std::size_t B>
class BMatrix : public Matrix<T, R, R> {
...
};
I want to have a tridiagonal matrix class, how I have done this is as follows (using inheritance)
template <typename T, std::size_t R>
class TriMatrix : public BMatrix<T, R, 3> {
...
}
Now I am not sure whether this is the best thing to do (As there are VERY efficient methods for tridiagonal matrices but not so much general banded matrices). While the above works, I would like to use a template specialisation. However I am mixing template types and variables.
Is there a way in which I can do this without using inheritance ?
For instance something like
template <typename T, std::size_t R, >
class BMatrix<T, R, 3> {
...
} typedef TMatrix ??
Upvotes: 0
Views: 91
Reputation: 1376
You are correct in asserting that with specialization, you'll need to reimplement everything. There are some workaround using inheritance (both the generic BMatrix and specialized BMatrix could inherit from a common base), but I'd like to point out some alternative patterns.
Firstly, if you want to stick with your current class design using member functions for certain operations, you could simply implement everything in the generic class, and use static_assert
to stop someone from using a specific method when B!=3
. As class template member functions are not instantiated before they are actually used, you can safely have these functions in the generic case where they are not applicable. You can use if constexpr
(or simply just if
if both alteratives will compile) if you want to provide an more optimal implementation for an algorithm where a less optimal version already exists for the generic case.
template<int W, int H>
class Ellipse
{
int Radius() const
{
static_assert(W==H); // only applies to circles
return W;
}
float Circumference() const
{
if (W == H)
return 2*PI*W;
else
return ... // ellipse circumference is not trivial
}
};
// Handy type alias
template<int R> using Circle = Ellipse<R,R>;
Secondly, you could choose to not implement all the operations as class members, but rather use regular non-member functions. That way, you can fix certain parameters and use overloading:
// Radius, only for circles
template<int R>
int Radius(Ellipse<R,R> e) { return R; }
// Circumference, generic case
template<int W, int H>
int Circumference(Ellipse<W,H> e) { return /* ... */; }
// Circumference, specific case for circles
template<int R>
int Circumference(Ellipse<R,R> e) { return 2*PI*R; }
Upvotes: 0
Reputation: 217145
If I understand correctly, you might have your partial specialization:
template <typename T, std::size_t R>
class BMatrix<T, R, 3> {
// ...
};
and an using
facility
template <typename T, std::size_t R>
using TriMatrix = BMatrix<T, R, 3>;
Upvotes: 4