Reputation: 45
I wrote a c++-class that represents a mathematical matrix of arbitrary dimension NxM. Furthermore I also wrote a vector-class, deriving from it...
template<size_t N, size_t M>
class matrix{ ... };
template<size_t N>
class vector : public matrix<N,1>{ ... };
...so that an N-vector can be treated as an Nx1-matrix, for example when it comes to multiplying with integral values or addition/subtraction of equally dimensioned matrices (or vectors in this regard). The idea behind this is to avoid repeating code - which generally is a noble goal, I think. But here is the problem arising from it:
Here is your operator-overload for the addition, which only exists in the matrix-class:
matrix<N,M> operator+(const matrix<N,M>& right){
//calculate some result and use it to construct a new instance
return matrix<N,M>(result);
}
Making sure, the vector-class offers a copy-constructor for it's matrix-representation, it should be possible to say something like this:
vector<3> a(1,2,3);
vector<3> b(3,2,1);
a = a+b;
but you can't say this:
(a+b).some_vector_instance_method();
...because (a+b) isn't a vector.
QUESTION: Is it possible to implement the matrix-operator+, so that it makes the return-type dependent on it's source of invocation? So, basically, if you invoke the + on a matrix, it should return a matrix; if invoked on a vector, it should return a vector.
Now you can do this:
template<typename D>
D operator+(const D& right){
//calculate result as usual, relying on 'right' to have what it takes
return D(result);
}
... but it is unsafe as hell.
Any ideas?
Upvotes: 0
Views: 95
Reputation: 153820
The simple approach to implementation is to implement a member operator+=()
for both matrix<M, N>
and for vector<M>
where the latter simply delegates to the former an the matrix operator has the actual operation. Using a bit of tagging the operator+()
is then implemented as a non-member operator in terms of these operator. Here is a brief sketch:
#include <iostream>
namespace matrix_operators
{
struct tag {};
template <typename T>
T operator+ (T const& lhs, T const& rhs) {
return T(lhs) += rhs;
}
}
template<size_t N, size_t M>
class matrix
: matrix_operators::tag
{
public:
matrix<N, M>& operator+= (matrix<N, M> const&) {
std::cout << "matrix<" << N << ", " << M << "::operator+=()\n";
return *this;
}
};
template<size_t N>
class vector:
public matrix<N,1>
{
public:
vector<N>& operator+= (vector<N> const& other) {
matrix<N, 1>::operator+= (other);
return *this;
}
void some_other_method() {
std::cout << "vector<" << N << ">::some_other_method()\n";
}
};
int main()
{
vector<3> a, b;
(a + b).some_other_method();
}
Upvotes: 2