I am trying to implement a Matrix class with linear algebraic operations. I want to make the class available for a few value types like uint, uchar, float, double.
The header looks as follows:
template<typename T>
class Matrix{
public:
Matrix(int width, int height);
Matrix(const Matrix<T> & other);
virtual ~Matrix();
unsigned int width() const { return width_; }
unsigned int height() const { return height_; };
T * data() const { return data_ptr_; };
private:
T * data_ptr_;
unsigned int width_;
unsigned int height_;
}
The source file looks as follows.
template<typename T>
Matrix<T>::Matrix(int width, int height ): width_(width), height_(height)
{
data_ptr_ = new T[width * height];
}
template<typename T>
Matrix<T>::Matrix(const Matrix<T> & other): Matrix(other.width(), other.height() )
{
memcpy(data_ptr_, other.data(), width_ * height_ * sizeof(T);
}
template<typename T>
Matrix<T>::~Matrix()
{
delete []data_ptr_;
}
template class Matrix<double>;
template class Matrix<float>;
...
Now I want to define an operator + which will return a Matrix of the type which an ordinary c++ conversion does when adding two values, i.e.
Matrix<double> + Matrix<float> => Matrix<double>
Matrix<int> + Matrix<float> => Matrix<float>
and I want to be able to do this without explicit conversions. For example
Matrix<float> float_matrix(10,20);
Matrix<int> int_matrix(10,20);
auto sum_matrix = float_matrix + int_matrix;
so the sum should have type float.
I tried 2 methods with no success, however.
Method 1
Define operator + as
//inside class definition
Matrix<T> operator+(const Matrix<T> &other) const;
and define implicit constructors like
//inside the class declaration
template<typename K>
Matrix(const Matrix<K> & other);
and instantiate them only in the obvious hierarchical order:
uchar-> uint->float->double, however I still have to manually cast operands of different types.
Method 2
Define operator + as
//inside the class declaration
template<typename K, typename R>
Matrix<R> operator+(const Matrix<K> &other) const;
and write specializations for each case, however, I could not get the compiler to correctly deduce the template arguments.
Neither of methods seem to be correct.
Can anyone point me a direction?
You can use method 3 and use C++11's auto return type deduction to figure out the type for you. Using
template<typename K>
auto operator+(const Matrix<K> &other) const -> Matrix<decltype(std::declval<T>() + std::declval<K>())>;
This says that the matrix returned will have the type of whatever a T added to a K would be.
You won't be able to make custom rules with this but it will follow the standard promotion/conversion rules.
Variant of the method 3 from MathanOliver: define operator+() (off topic suggestion: ever define operator+=() as method and operator+() as external function) not as method but as external function (you can make it friend to Matrix if needed).
template <typename T1, typename T2,
typename Tr = decltype(std::declval<T1>() + std::declval<T2>())>
Matrix<Tr> operator+ (Matrix<T1> const & m1, Matrix<T2> const & m2)
{
// something useful
return {m1.width(), m1.height()};
}
The following is a full compiling example
#include <cstring>
#include <utility>
template <typename T>
class Matrix
{
public:
Matrix(unsigned int width, unsigned int height)
: width_(width), height_(height)
{ data_ptr_ = new T[width * height]; }
Matrix(const Matrix<T> & other)
: Matrix(other.width(), other.height() )
{ std::memcpy(data_ptr_, other.data(), width_ * height_ * sizeof(T)); }
virtual ~Matrix()
{ delete []data_ptr_; }
unsigned int width() const
{ return width_; }
unsigned int height() const
{ return height_; };
T * data() const
{ return data_ptr_; };
private:
T * data_ptr_;
unsigned int width_;
unsigned int height_;
};
template <typename T1, typename T2,
typename Tr = decltype(std::declval<T1>() + std::declval<T2>())>
Matrix<Tr> operator+ (Matrix<T1> const & m1, Matrix<T2> const & m2)
{
return {m1.width(), m1.height()};
}
int main ()
{
Matrix<int> m1{1, 2};
Matrix<float> m2{1, 2};
auto m3 = m1 + m2;
auto m4 = m2 + m1;
static_assert( std::is_same<decltype(m3), Matrix<float>>{}, "!" );
static_assert( std::is_same<decltype(m4), Matrix<float>>{}, "!" );
return 0;
}
Obtaining the type of the returned matrix as default template value (Tr) you can explicit a different type, if you want, as follows
auto m5 = operator+<int, float, int>(m1, m2);
static_assert( std::is_same<decltype(m5), Matrix<int>>{}, "!" );
Related
Imagine you have a simple 2D Point object with two setters and getters.
template <typename T>
class Point
{
public:
Point(T x, T y);
T getX() const;
T getY() const;
void setX(T x);
void setY(T y);
private:
T _x;
T _y;
};
But I want to work with this class in more 'scriptable-like' syntax. Something like :
auto point = Point<double>(10, 10);
point.x = 20;
point.y = point.x + 10;
You will say, just use a struct with public variable :
template <typename T>
struct Point
{
T x;
T y;
};
Yes, but I want to keep the privacy of the parameters and extend the class with some methods. So another idea is to make a wrapper helper that add operator alias to the setters/getters :
template <typename T, typename Get, Get(T::*Getter)() const,
typename Set, void(T::*Setter)(Set)>
struct ReadWrite
{
ReadWrite(T& ptr) : ptr(ptr) {}
inline void operator= (Set const& rhs)
{
(ptr.*Setter)(rhs);
}
inline Get operator()()
{
return (ptr.*Getter)();
}
private:
T& ptr;
};
OK, I just modify my Point class to do the work :
template <typename T>
class Point
{
public:
Point(T x, T y);
T getX() const;
T getY() const;
void setX(T x);
void setY(T y);
private:
T _x;
T _y;
public:
ReadWrite<Point<T>, T, &Point<T>::getX, T, &Point<T>::setX> x;
ReadWrite<Point<T>, T, &Point<T>::getY, T, &Point<T>::setY> y;
};
By adding some arithmetics operators ( + - * / ), I can use it like that:
auto point = Point<double>(10, 10);
point.x = 20;
point.y = point.x + 10;
Here, point.x is ok in case of operator overloading in the form:
template <typename T, typename V> inline T operator+(ReadWrite<T> const& lhs, V const& rhs) { return lhs() + rhs; }
template <typename T, typename V> inline T operator-(ReadWrite<T> const& lhs, V const& rhs) { return lhs() - rhs; }
template <typename T, typename V> inline T operator*(ReadWrite<T> const& lhs, V const& rhs) { return lhs() * rhs; }
template <typename T, typename V> inline T operator/(ReadWrite<T> const& lhs, V const& rhs) { return lhs() / rhs; }
If I want use this syntax, but without parenthesis on point.x getter :
auto point = Point<double>(10, 10);
auto x = point.x();
I extend the ReadWrite helper with:
template <typename T, typename Get, Get(T::*Getter)() const,
typename Set, void(T::*Setter)(Set)>
struct ReadWrite
{
ReadWrite(T& ptr) : ptr(ptr) {}
inline void operator= (Set const& rhs)
{
(ptr.*Setter)(rhs);
}
inline Get operator()()
{
return (ptr.*Getter)();
}
inline operator auto() -> Get
{
return operator()();
}
private:
T& ptr;
};
Now with no parenthesis:
double x = point.x; // OK, x is my x value (Point).
auto x = point.x; // Wrong, x is my ReadWrite<T> struct.
What is wrong with the overloading of the auto operator?
Thank you very much for your answer.
There is nothing wrong with your class. The problem is how auto deduces types. The thing you have to remember about auto is it basically follows the rules for template argument deduction and the main thing about that is no implicit conversion will be done. This means that in
auto x = point.x;
You say compiler, give me a variable named x that has the type of the initialization expression. In this case point.x is a ReadWrite<Point<T>, T, &Point<T>::getX, T, &Point<T>::setX> so that is the type x gets. The only way to change that is to change what the initialization expression returns.
Unfortunately I'm not sure how you could do that. Proxy objects don't play well with auto type deduction as we pick up their type, not what they are mimicking.
I have a Matrix class
template <typename T>
class Matrix
{
public:
const size_t rows;
const size_t cols;
const std::map<std::array<int, 2>, T> data;
Matrix(int a, int b) : rows(a), cols(b)
{
}
};
which is initialized like this:
Matrix<double> M(5,5);
creating a 5x5 matrix.
I want to assign values to the map like so:
M[{1,2}] = 1;
How would I go about doing that in the most readable way? I'm not sure how to get the subscript and assignment operator working together.
Let's add some helper aliases to Matrix while we are at it
template <typename T>
class Matrix
{
// rather than stoping people changing the members via const
// make them private
size_t rows;
size_t cols;
map_type data;
public:
using key_type = std::array<size_t, 2>;
using mapped_type = T;
using map_type = std::map<key_type, mapped_type>;
Matrix(size_t r, size_t c) : rows(r), cols(c) { }
const T& operator [](key_type key) const { return data[key]; }
T& operator [](key_type key) { return data[key]; }
// other operations as appropriate
};
You have to provide members:
const T& operator [](std::pair<std::size_t, std::size_t>) const;
T& operator [](std::pair<std::size_t, std::size_t>);
I'm having some problem with my std::forward constructor for my template "matrix" class. Basically i want to set a matrix of type float and size 4 equal to the sum of 2 matrices of type float and size 3. I do this inside of my struct 'matrix_struct' in the function 'test'. However, MSVC error tells me that "'static_cast': cannot convert from 'matrix' to 'float'" and whenever I inspect the error it takes me to the 3rd matrix constructor with std::forward.
///////////////////////////////////
somefile.hpp
#pragma once
#include "matrix.hpp"
using matrix3 = matrix<float, 3>;
using matrix4 = matrix<float, 4>;
struct matrix_struct {
matrix4 sum;
void test(const matrix3& a, const matrix3& b)
{
sum = a + b;
}
}
///////////////////////////////////
matrix.hpp
#pragma once
#include <array>
template <typename t, size_t dim>
class matrix
{
public:
matrix() { data.fill(static_cast<t>(0) }
explicit matrix(const std::array<t, dim>& a) : data(a) {}
template <typename... args_t>
matrix(args_t... args) : data{ static_cast<t>(std::forward<args_t>(args))... } }
public:
t& at(const size_t index)
{
return data.at(index >= dim ? dim - 1 : index);
}
const t& at(const size_t index) const
{
return data.at(index >= dim ? dim - 1 : index);
}
public:
matrix& operator = (const matrix<t, dim>& other)
{
for (size_t i = 0; i < dim; ++i) {
at(i) = other.at(i);
}
return *this;
}
matrix& operator = (const std::array<t, dim>& other)
{
for (size_t i = 0; i < dim; ++i) {
at(i) = other.at(i);
}
return *this;
}
matrix& operator = (const t& other)
{
for (size_t i = 0; i < dim; ++i) {
at(i) = other;
}
return *this;
}
public:
matrix operator + (const matrix<t, dim>& other) const
{
matrix<t, dim> ret;
for (size_t i = 0; i < dim; ++i) {
ret.at(i) = at(i) + other.at(i);
}
return ret;
}
matrix operator + (const std::array<t, dim>& other) const
{
matrix<t, dim> ret;
for (size_t i = 0; i < dim; ++i) {
ret.at(i) = at(i) + other.at(i);
}
return ret;
}
matrix operator + (const t& other) const
{
matrix<t, dim> ret;
for (size_t i = 0; i < dim; ++i) {
ret.at(i) = at(i) + other;
}
return ret;
}
private:
std::array<t, dim> data;
};
Template constructors are problematic. They often create code that is a better candidate than your other constructors.
The general solution is to disable the template if its decayed type matches the class you are writing.
example:
struct MyClass
{
template
<
class Arg,
class...Rest,
std::enable_if_t
<
! std::is_same
<
std::decay_t<Arg>,
MyClass
>::value
>* = nullptr
>
MyClass(Arg&& arg, Rest&&...rest)
{
// code to construct from something that's not MyClass
// this will no longer hijack copy constructors etc.
}
};
The first problem of your code sample is addressed by #RichardHodges's answer.
Assuming you include his solution to overcome tricky copy/move constructor selection, another problem remains: you do not offer a matrix promotion/demotion service through your constructors/assignment operators.
Therefore, the following line in your test function:
sum = a + b; // a + b is a matrix<float, 3>, sum a matrix<float, 4>
Will trigger a call to the variadic template constructor and fail.
Starting from Richard's solution, you need to tweak a bit the SFINAE condition to extend it to matrices of any size. To do so, we will need a little is_matrix trait:
template <typename T, size_t Dim>
class matrix;
template <typename T>
struct is_matrix : std::false_type {};
template <typename Num, size_t Size>
struct is_matrix<matrix<Num, Size> > : std::true_type {
using value_type = Num;
};
Now the variadic template constructor becomes:
template <typename t, size_t dim>
class matrix
{
/* ... */
public:
/* ... */
template
<
class Arg,
class...Rest,
std::enable_if_t
<
! std::is_matrix
<
std::decay_t<Arg>
>::value
>* = nullptr
>
matrix(Arg&& arg, Rest&&...rest)
{
// code to construct from something that's not a matrix
// this will no longer hijack copy constructors etc.
}
};
Then, we need to add the proper matrix constructor along with the proper friend declaration:
template <typename t, typename dim>
class matrix {
public:
template <typename OtherT, size_t OtherDim>
friend class matrix;
template <size_t OtherDim>
matrix(matrix<t, OtherDim> const& other) {
size_t i = 0;
for (; i < min(OtherDim, dim); ++i) {
data[i] = other.data[i];
}
for(; i < dim; ++i) {
data[i] = t();
}
}
template <typename OtherT,
size_t OtherDim>
matrix(matrix<OtherT, OtherDim> const&) {
static_assert(std::is_same<t, OtherT>::value,
"value_type mismatch between matrices!");
}
/* ... */
};
Note: You need the friend declaration because matrix<Type1, Dim1> and matrix<Type2, Dim2> are completely different types whenever Type1 != Type2 or Dim1 != Dim2 and as such, you cannot access matrix<OtherT, OtherDim>'s private/protected members in matrix<t, dim> without that friend declaration.
This implementation will initialize the target matrix by filling its data member with the content of the given matrix when the value types match:
If the given matrix is bigger, it will be truncated.
If the given matrix is smaller, the remaining elements will be 0 initialized
If the value types don't match, the less specialized matrix<OtherT, OtherDim> constructor is the only available overload and it triggers a compiler error through a static_assert.
You would also need to define the equivalent assigment operators... Which I left as exercises.
A demo of these constructors in action can be found on Coliru
I have a 3x3 Matrix and a 3x1 Vector classes. I have two multiplication operators; one for multiplying a matrix with a scalar, another for multiplying a matrix with a vector object. The matrix-scalar multiplication operator is member inside the Matrix class and the matrix-vector multiplication operator is global.
#include <initializer_list>
#include <array>
template <class T>
class Matrix
{
public:
Matrix(std::initializer_list<T> List);
Matrix() : Matrix({0,0,0,0,0,0,0,0,0}) {}
template <class S> // THE COMPILER TRIES TO USE
Matrix<T> operator*(const S & Scalar); // THIS OPERATOR IN BOTH CASES.
const T & operator()(size_t i, size_t j) const;
private:
static constexpr size_t SIZE = 3;
static constexpr size_t AREA = SIZE * SIZE;
std::array<T, AREA> E;
};
template <class T>
Matrix<T>::Matrix(std::initializer_list<T> List)
{
if (List.size() != AREA) throw("Error!");
for (size_t i=0; i<AREA; i++)
{
E[i] = *(List.begin() + i);
}
}
template <class T>
const T & Matrix<T>::operator()(size_t i, size_t j) const
{
return E[SIZE * j + i];
}
template <class T>
template <class S>
Matrix<T> Matrix<T>::operator*(const S & Scalar)
{
const T ScalarT = static_cast<T>(Scalar);
Matrix<T> Result;
for (size_t i=0; i<AREA; i++)
{
Result.E[i] = E[i] * ScalarT;
}
return Result;
}
template <class T>
class Vector
{
public:
Vector(std::initializer_list<T> List);
Vector() : Vector({0,0,0}) {};
const T & operator()(size_t i) const;
T & operator()(size_t i);
private:
static constexpr size_t SIZE = 3;
std::array<T, SIZE> E;
};
template <class T>
Vector<T>::Vector(std::initializer_list<T> List)
{
if (List.size() != SIZE) throw("Error!");
for (size_t i=0; i<SIZE; i++)
{
E[i] = *(List.begin() + i);
}
}
template <class T>
const T & Vector<T>::operator()(size_t i) const
{
return E[i];
}
template <class T>
T & Vector<T>::operator()(size_t i)
{
return E[i];
}
template <class T> // THE COMPILER NEVER TRIES USING THIS GLOBAL OPERATOR.
Vector<T> operator*(const Matrix<T> & Mat, const Vector<T> & Vec)
{
Vector<T> Result;
Result(0) = Mat(0,0) * Vec(0) + Mat(0,1) * Vec(1) + Mat(0,2) * Vec(2);
Result(1) = Mat(1,0) * Vec(0) + Mat(1,1) * Vec(1) + Mat(1,2) * Vec(2);
Result(2) = Mat(2,0) * Vec(0) + Mat(2,1) * Vec(1) + Mat(2,2) * Vec(2);
return Result;
}
int wmain(int argc, wchar_t *argv[]/*, wchar_t *envp[]*/)
{
Matrix<float> Mat1({2, 0, 0,
0, 2, 0,
0, 0, 2});
Vector<float> Vec1({1,
2,
3});
Matrix<float> Mat2 = Mat1 * 2; // Matrix-Scalar Multiplication
Vector<float> Vec2 = Mat1 * Vec1; // Matrix-Vector Multiplication
return 0;
}
The problem is, when I try to do a matrix-vector multiplication, the compiler chooses and tries to use the matrix-scalar multiplication operator, and gives a compiler error.
If I delete the matrix-scalar multiplication operator and the line where I use it, the program runs successfully. In reverse, if I delete the matrix-vector multiplication operator, it again runs successfully. They just don't get along. And when it runs (in either case), it makes the all calculations correctly.
What is going wrong here?
Compiler & IDE: Microsoft Visual Studio 2015 Community Edition
The language doesn't specify that when searching for overloads to examine all possible scopes. As soon as one candidate is found, only the overloads in that scope are used to select the best candidate. If that candidate fails to compile for other reasons, it still won't examine additional scopes.
So in your case since the scalar is a template parameter it will match any type so as long as the left-hand operand of the operator is a Matrix<T>, the scalar multiplication will match any right-hand operand.
You could:
Just make both operator* at the same scope so they're both considered for overload resolution.
Change the scalar operator to take for example a Scalar<T> that's a thin wrapper around a scalar type rather than a generic template type.
I have a fairly simple template class as follows. It is essentially an extension on the std::shared_ptr in C++11 where I would like to overload various operators. For this question the multiplication operator*(), and I would like it to be commutative.
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
assert(Variable != 0x0);
return (*Variable);
}
template < typename U >
friend T operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
}
The issue with this implementation is when I utilize this PoolVar class with my Vector and Quaternion classes defined as follows. Both of which define the multiplication operator such that it is commutative to any user of the classes.
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const;
}
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const;
}
What I want is for the PoolVar overloaded operator to essentially just be a pass through for any data type, such that I can do something like the following. Assume I allocated and initialized the Variable in the PoolVar objects correctly.
PoolVar<Vector> v;
PoolVar<Quaternion> q;
/* Stuff to create and initialize correctly. */
Vector v1 = v*q; // works currently
Vector v2 = q*v; // does not
Quaternion q1 = q*q; // ambiguous
The moment I attempt to add another friend operator as follows to PoolVar to achieve the pattern that does not work above, I get a bunch of error messages at compile time for ambiguous operators as marked above.
template < typename U >
friend T operator*(const PoolVar<U> & lhs, const PoolVar<T> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
The only thing I have found to work is to explicitly define the various combinations of the operators outside the PoolVar class, such as:
inline Vector operator*(PoolVar<Vector> & lhs, PoolVar<Quaternion> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
inline Vector operator*(PoolVar<Quaternion> & lhs, PoolVar<Vector> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
I really do not want to do this, if I can at all help it, because it is a serious limitation on the PoolVar class and would increase the maintenance of the code-base for any new special class like Vector and Quaternion.
The issue is not so much that I can create a commutative operator (I think) as it is that the return type for both definitions is the same (invariant), which leads to ambiguous overloading unless explicitly defined.
Is there any way to set up a template class to have commutative operators with invariant return types, such as this multiplication operator? Also, I should note that I do not have the luxury of utilizing C++11, if that perchance would have helped.
I'm not 100% sure, since I haven't tried out all the new C++11 features but it seems like this could be solved with trailing return type thus allowing the compiler to deduce the return type. I put together an example from your snippets:
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
return (*Variable);
}
template <typename U>
friend auto operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) -> decltype(lhs * rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
};
class Quaternion;
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const;
};
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const;
};
int main(int argc, char** argv)
{
PoolVar<Vector> v;
PoolVar<Quaternion> q;
/* Stuff to create and initialize correctly. */
Vector v1 = v*q;
Vector v2 = q*v;
return 0;
}
Since I'm on Windows and Visual Studio 2012 does not seem to support this I tried to compile it with gcc on Ubuntu VM and on http://gcc.godbolt.org/ but in both cases the compilers crash. Can anyone hint if this is an appropriate/inappropriate use of trailing return types in context of this question?
EDIT
I understood what was bad with the initial example, it introduces in infinitely deep recursion since the evaluation of the multiplication operator will yield evaluation of the same template. However when I tried:
template <typename U>
friend auto operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) -> decltype(lhs.GetValue() * rhs.GetValue()) {
return (lhs.GetValue() * rhs.GetValue());
}
which gave errors about accessing incomplete type PoolVar, so I moved the operator outside of the class scope:
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
return (*Variable);
}
};
template <typename T, typename U>
auto operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) -> decltype(lhs.GetValue() * rhs.GetValue()) {
return (lhs.GetValue() * rhs.GetValue());
}
class Quaternion;
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const;
};
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const;
};
int main(int argc, char** argv)
{
PoolVar<Vector> v;
PoolVar<Quaternion> q;
/* Stuff to create and initialize correctly. */
Vector v1 = v*q;
Vector v2 = q*v;
return 0;
}
This seemed to compile fine, so I guess my initial idea was right, thanks for the great question, so far I did not have a good example to try the trailing return types on.
EDIT 2
GCC has a built in extension called typeof that can solve this without C++11, but then again it is GCC specific:
template<typename T, typename U>
class EvaluateResult
{
static T m_a;
static U m_b;
public:
typedef typeof(m_a * m_b) Result;
};
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
return (*Variable);
}
};
template <typename T, typename U>
typename EvaluateResult<T,U>::Result operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
class Quaternion;
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const;
};
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const;
};
int main(int argc, char** argv)
{
PoolVar<Vector> v;
PoolVar<Quaternion> q;
/* Stuff to create and initialize correctly. */
Vector v1 = v*q;
Vector v2 = q*v;
}
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
return (*Variable);
}
template < typename U >
friend typename T::type operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
// to handle equl types :)
friend T operator*(const PoolVar<T> & lhs, const PoolVar<T> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
};
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const{ return Vector(); }
Vector operator*(const Vector & q) const{ return Vector(); }
typedef Vector type;
};
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const {return Vector();};
Quaternion operator*(const Quaternion & v) const {return Quaternion();};
typedef Vector type;
};
int main()
{
PoolVar<Vector> v;
PoolVar<Quaternion> q;
Vector v1 = v * q; // good
Vector v2 = q * v; // good
Quaternion qq = q * q; // good
Vector vv = v * v; // good
return 0;
}
try this