Templates and casting - c++

I created a matrix class with templates:
template <typename T>
class Matrix
{
static_assert(std::is_arithmetic<T>::value,"");
public:
Matrix(size_t n_rows, size_t n_cols);
Matrix(size_t n_rows, size_t n_cols, const T& value);
// Functions
// Operators
Matrix<T>& operator*=(const T& value)
private:
size_t rows;
size_t cols;
std::vector<T> data;
};
I created the following two (external) operators to multiply my matrix with a number:
// Inner operator used by the externals ones
template <typename T>
inline Matrix<T>& Matrix<T>::operator*=(const T& value)
{
for(size_t i(0); i < data.size(); i++)
{
data[i] *= value;
}
return *this;
}
template <typename T>
inline Matrix<T> operator*(const T& value, const Matrix<T>& matrix)
{
Matrix<T> tmp(matrix);
return tmp *= value;
}
template <typename T>
inline Matrix<T> operator*(const Matrix<T>& matrix, const T& value)
{
return value * matrix;
}
The problem is that if I declared the matrix as a double, I can multiply the matrix only by doubles and so on...
Matrix<double> m1(3,3,1.);
5. * m1; // Works
5 * m1; // Doesn't work (5 is an int and not a double)
How can I fix this behave? It is possible to let doubles be multiplied by others arithmetic types?

Sure, just allow two parameters to your templated free functions and member functions.
For example:
template <typename T> class Matrix {
/* ... */
template <typename U>
inline Matrix<T>& operator*=(const U& value)
{
for(size_t i(0); i < data.size(); i++)
{
data[i] *= value;
}
return *this;
}
};
template <typename T, typename U>
inline Matrix<T> operator*(const U& value, const Matrix<T>& matrix)
{
Matrix<T> tmp(matrix);
return tmp *= value;
}
This will trigger compiletime errors if you try to multiply your Matrix with something nonsensical, that is, if T*U is undefined.

Yes. Declare the function in the Matrix class as
template <typename T>
class Matrix
{
public:
/* ... */
template <typename S>
inline Matrix & operator*=( const S & value );
/* ... */
};
The definition looks like
template <typename T>
template <typename S>
inline Matrix<T>& Matrix<T>::operator*=(const S& value)
{
for(size_t i(0); i < data.size(); i++)
{
data[i] *= value;
}
return *this;
}
for the member function. You need to write template twice. A bit odd, but that's C++ syntax.
In case of the free functions you can write
template <typename T, typename S>
inline Matrix<T> operator*(const S& value, const Matrix<T> &mat)
{
Matrix<T> tmp(mat);
return tmp *= value;
}

The problem that you are seeing is that template type deduction requires a perfect match of all of the deduced types. In your case you have a template that takes a single type argument T that is both the scalar and the matrix types. When the compilers sees the operation: 5 * m1, it deduces T == int for the first argument but T == double for the second argument, and type deduction fails.
There are multiple approaches around this, as it has been suggested, you can add a second template argument:
template <typename T, typename S>
Matrix<T> operator*( Matrix<T> m, S scalar ) {
return m*=scalar;
}
[Note: both arguments by value, the second one because for arithmetic types it is more efficient and idiomatic to pass by value; the first one because by moving the copy to the interface of the function you allow the compiler to elide copies]. This approach is simple, but will generate one operator* for each combination of S and T in the program, even though the actual multiplication in operator*= is always performed on T.
Another approach would be to fix the type of the scalar that you want to multiply by, for example, make it double, generating only one operator* per T type that is multiplied:
template <typename T>
Matrix<T> operator*( Matrix<T> m, double scalar ) {
return m*=scalar;
}
In this approach there is a single operator*, the one taking a double as argument. As in the previous example, it might require two type conversions on the scalar (say you multiply Matrix<int> by 5, it will then convert 5 into a double, which will then be converted back to int to match the signature of operator*=.
The third approach is to create a non-templated function that takes your Matrix and another argument of the same type. This will be the closest to your original code, with the slight advantage that not being a template, it will allow conversions for the scalar argument. Theoretically you could define all such functions yourself manually:
Matrix<int> operator*( Matrix<int>, int ) { ... }
Matrix<double> operator*( Matrix<double>, double ) { ... }
But this becomes a maintenance problem very easily. Luckily, there is a feature in the language that allows for the definition of all those non-template functions generically. Although the syntax might not be the most natural. You just need to declare the free function as a friend of your template, and define it inside the class template definition:
template <typename T>
class Matrix {
// ...
friend Matrix operator*( Matrix m, T scalar ) { return m*=scalar; }
};
As we are inside the class template Matrix, we can use Matrix (without arguments) to refer to the current instantiation (Matrix<int>, Matrix<double...) [This might not seem obviously important, but it is, it is important to realize when Matrix refers to the template, and when it refers to the class generated from the template]. The second argument to the function is T. Again, this is not the generic T of the class template, but the current instantiating type (int, double...).
The language allows for the definition of a friend function inside the class that has the declaration, and that will define the function at namespace level, although the declaration will only be found through Argument Dependent Lookup.
Whenever you instantiate a particular instance of your template (say Matrix<int>) and call the operator, the compiler will generate the free function for you. Because the function is not templated, it will allow conversions on the arguments, and thus for Matrix<int> m it will allow you to call m * 5. by converting 5. into an int.

Related

c++ operator-overloading for a template struct

I have a template struct "point as follows:
template<typename T>
struct point
{
T x, y, z;
template<typename T1>
inline point<T> operator*(const point<T1>& p) const // multiply by another point.
{
return point<T>{this->x*p.x, this->y*p.y, this->z*p.z};
}
template<typename T1>
inline point<T> operator*(const T1& v) const // multiply by constant from right side
{
return point<T>{this->x*v, this->y*v, this->z*v};
}
}
template<typename T1, typename T2>
inline point<T1> operator*(const T2& v, const point<T1>& p) // multiply by a constant from the left side.
{
return point<T1>{p.x*v, p.y*v, p.z*v};
}
The two operator overloading functions that declared as member functions, the first one is supposed to multiply by another point, and the other to multiply a point by a constant from the right side, where the one declared outside the struct is to do the same thing but from the left side.
And now when I go to compile the following code:
point<double> p1{1,2,3};
point<float> p2{1,2,3};
point<double> p3 = p1*p3;
The compiler calls the one declared outside the struct instead of the one declared as a member function, and produces and error:
error: cannot convert ‘point<double>’ to ‘float’ in initialization
return point<T1>{p.x*v, p.y*v, p.z*v};
And that makes sense, because the both arguments are template variables and can be interpreted as point variables. Now the second one can be only a point variable, but the first one can be anything!
To solve this I can go and write several copies of that function, when declaring the first argument once as int, float, double, long double .. et cetera. This works fine for me, but I'm still wondering if there is a better way to deal with this, and if I can write only one copy as above?
Do not unnecessarily overload operators as member functions,
follow the rules described here.
Having operator* for two point instances return the type of the left one does not make sense, in my opinion. Better consider both types in the deduction of the return type, since the function is defined as commutative.
template<typename T>
struct point
{
T x, y;
};
template<typename T1, typename T2>
auto operator*(const point<T1>& lhs, const point<T2>& rhs)
-> point<decltype(std::declval<T1>() * std::declval<T2>())>
{
return {lhs.x*rhs.x, lhs.y*rhs.y};
}
template<typename T1, typename T2>
point<T1> operator*(const point<T1>& p, const T2& v)
{
return {p.x*v, p.y*v};
}
template<typename T1, typename T2>
point<T1> operator*(const T2& v, const point<T1>& p)
{
return p * v;
}
Try to do the same with the overloads for multiplication by a scalar as an exercise.

Overloading operators in C++ with template classes

I have the following template class:
template <class T>
class Matrix {
public:
Matrix(size_t rows, size_t columns, const T elements = 0);
// scalar multiplication
Matrix<T> operator*(const T& rhs){
Matrix<T> result(rows, columns);
for(size_t index = 0; index < rows * columns; ++index){
result.elements[index] = elements[index] * rhs;
}
return result;
}
Matrix <T> operator*(const T& lhs, const Matrix<T>& rhs);
const size_t rows;
const size_t columns;
private:
std::vector<T> elements;
};
and the following implementation of the operator* :
// scalar multiplication
template <class T>
Matrix<T> Matrix<T>::operator*(const T& lhs, const Matrix<T>& rhs){
Matrix<T> result(rhs.rows, rhs.columns);
for(size_t index = 0; index < rhs.rows * rhs.columns; ++index){
result.elements[index] = elements[index] * lhs;
}
return result;
}
when I try to compile clang says: error: overloaded 'operator*' must be a unary or binary operator (has 3 parameters)|
And I don't quite understand, what I am missing in this. In general template classes give me a hard time when it comes to overloading operators and I don't know why. There have been some posts on here on SO on this topic and I tried a few variations of the code but none of them worked.
The simple and reasonably efficient way to solve this problem is as follows:
Implement Matrix& operator *=(SomeType const&) and similar operations first. These are mutating operations that change an instance of the class, then return a reference to *this.
Implement other operations as inline friends in terms of *=, where the lhs (usually) argument is taken by-value, modified and returned.
This tends to be really simple and quite often more efficient than starting with operator* instead of operator*=.
So you'll have:
template<class T, etc>
struct Matrix{
Matrix& operator*=(T const&);
Matrix& operator*=(Matrix const&);
Matrix& operator+=(Matrix const&);
which you implement traditionally. Then:
friend Matrix operator*(T const& t, Matrix m){ m*=t; return m; }
friend Matrix operator*(Matrix m, T const& t){ m*=t; return m; }
friend Matrix operator*(Matrix lhs, Matrix const& rhs){ lhs*=rhs; return lhs; }
friend Matrix operator+(Matrix lhs, Matrix const& rhs){ lhs+=rhs; return lhs; }
and now you only need to implement a few, traditional, methods.
These friend operators are non-template inline non-method functions that are auto-generated for each template instance of Matrix.
Your immediate problem was your non-static operator actually took an implicit this in addition to its two explicit parameters, and binary operators cannot take 3 arguments.
The complex and even more efficient solution involves a technique often called "expression templates". The disadvantage is that expression templates are more complex to write, and have a few points of fragility around the auto keyword and similar situations.
As an example:
Matrix m = m1 * m2 + m3 * m4 + m5 + m6;
An expression template will do the above with only one allocation of the internal data of a matrix.
My above code will copy m1, multiply the result by m2. Then it will copy m3, then multiply that by m4. Then it will add up everything without making any additional copies. Finally, this result will be moved into m.
So two matrices will be created instead of 1 in the expression template case.
A more-naive solution (like the OP's design) would create 5 Matrices instead of 2.
You're declaring Matrix <T> operator*(const T& lhs, const Matrix<T>& rhs); as member function, which has an implicit parameter this, that why compiler complains it "has 3 parameters".
You can make it a free template function,
template <class T>
class Matrix {
...
template <class Z>
friend Matrix<Z> operator*(const Z& lhs, const Matrix<Z>& rhs);
...
};
and
// scalar multiplication
template <class Z>
Matrix<Z> operator*(const Z& lhs, const Matrix<Z>& rhs){
Matrix<Z> result(rhs.rows, rhs.columns);
for(size_t index = 0; index < rhs.rows * rhs.columns; ++index){
result.elements[index] = elements[index] * lhs;
}
return result;
}
Your function is a member function. Member functions have a hidden parameter, the this pointer.
You either need to make your operator* a non-member function or you need to get rid of one of the arguments to your operator* function (which will then multiply the data in "this" with the data in the incoming Matrix<T>.)

How to overload an operator with a friend function in a generic class?

I have written a matrix class. I have overloaded the operator+, so that the user can write: matrix + 2. I would like the user to also write: 2 + matrix.
For the standard format (i.e. the object invoking 2) I have written a standard operator overloading function. It works.
template<typename T>
Matrix<T> Matrix<T>::operator+(const T& rhs) const
{
Matrix result(rows, cols, 0.0);
for (unsigned i = 0; i < rows; ++i)
{
for (unsigned j = 0; j < cols; ++j)
{
result(i,j) = (*this)(i, j) + rhs;
}
}
return result;
}
Now for the other order (i.e. 2 + matrix), I have written the friend function:
// Friend Functions that allow the user to write expressions in a different order
template<typename T>
friend Matrix<T> operator+(const T& type, const Matrix<T>& matrix);
and implementation as:
template<typename T>
Matrix<T> operator+(const T& type, const Matrix<T>& matrix)
{
return matrix + type;
}
When I try to write 2 + matrix (in main()), I get some errors.
I have always had problems using friend functions with generic classes and frankly, I have never understood why it never works for me.
Could someone please explain what I am doing wrong here?
Errors I get:
IntelliSense: no operator "+" matches these operands operand types are: int + Matrix
Severity Code Description Project File Line Error C2244 'Matrix::operator +': unable to match function definition to an existing declaration
It looks like it's just a template deduction error; that is to say that your compiler can't deduce the proper function based on the templated friend function.
Since your friend function is a simple function, you could just declare it in your class/header and the compiler should be able to deduce it properly (as well as possibly inline it if optimizations are turned on); just declare the friend function in your header like such:
friend Matrix operator+(const T& type, const Matrix& matrix)
{
return matrix + type;
}
You don't need to specify the template keyword since it's within your template specialized class.
Hope that can help.
You can fix the problem simply by changing the member function to const.
template<typename T>
Matrix<T> Matrix<T>::operator+(const T& rhs) const
{
...
}

About the return type of an unbound template friend function of a template class

Suppose I have a template class which has a template friend function hoping to implement the function of a value multiplying an array(myArray):
template<typename T, int size>
class myArray{
T *_array;
public:
...
template<typename Val, typename Array>
friend myArray<T,size> operator*(const Val &lhs, const Array &rhs){
myArray<T,size> mat_t;
for(int i = 0;i < size; i++)
mat_t._array[i] = lhs * rhs._array[i];
return mat_t;
}
...
};
It works on VS2013. Then I move the definition of the unbound template friend function outside:
template<typename Val, typename Array>
myArray<T,size> operator*(const Val &lhs, const Array &rhs){
myArray<T,size> mat_t;
for(int i = 0;i < size; i++)
mat_t._array[i] = lhs * rhs._array[i];
return mat_t;
}
It is incorrect! I suppose the problem is with the return type of the friend function. But I can't not figure it out.
So how to define a friend template function like this outside the class declaration?
friend functions declared like the first example are strange beasts. Each instance of myArray<T,Size> creates a distinct friend function that can only be found via argument dependent lookup on myArray<T,Size>.
A free operator* not declared that way does not work that way.
You can get your code to work like this:
template<class Val, class T, int size>
myArray<T,size> operator*(const Val &lhs, const myArray<T,size> &rhs){
myArray<T,size> mat_t;
for(int i = 0;i < size; i++)
mat_t._array[i] = lhs * rhs._array[i];
return mat_t;
}
here all of the template parameters are listed in the template<> list, and they are all deducible from the arguments to *.
Remember to put your operator* in the same namespace as myArray.
However, personally, I'd go with:
friend myArray operator*(const T&lhs, const myArray &rhs){
myArray mat_t;
for(int i = 0;i < size; i++)
mat_t._array[i] = lhs * rhs._array[i];
return mat_t;
}
a non-template friend operator*. Again, one of these is "spawned" for each myArray<T,size>, but it itself is not a template. This has certain advantages, such as it behaves nicer with conversion constructors.
Going a step further, we get:
friend myArray& operator*=(myArray&mat, const T&scalar){
for(int i = 0;i < size; i++)
mat._array[i] *= scalar;
return mat;
}
friend myArray operator*(const T&scalar, myArray mat){
mat *= scalar;
return mat;
}
friend myArray operator*(myArray mat, const T&scalar){
mat *= scalar;
return mat;
}
where we first create a *=, then write * in terms of it. Notice that * takes myArray by-value (because I need to return a copy anyhow, might as well have it happen outside the method), and I support both mat*scalar and scalar*mat and mat*=scalar.
Also note that matrices of matrices ... just work.
The reason why this friend operator is a good idea is illustrated here. Note the code does not compile. Now #define ADL to move the operator* into the class as friends and it compiles. Koenig operators let operator* operate on a template class without being a template, and argument matching rules for templates are hard to get right without being overly narrow, overly broad, or using nasty SFINAE.
Next step, operator*= can be improved via: (C++14 used for brevity)
template<class Array
class=std::enable_if_t<std::is_same<std::decay_t<Array>,myArray>>
>
friend Array operator*=(Array&&mat, const T&scalar){
for(int i = 0;i < size; i++)
mat._array[i] *= scalar;
return std::forward<Array>(mat);
}
which is more complex, but does fun things with perfect forwarding. A temporary myArray gets moved into the return value (which allows for reference lifetime extension to work), while non-temporary myArray return a reference.
This provides a reason why even *= should be a friend. It allows both r and lvalues to be implemented in the same method.
On the other hand, possibly you don't want *= to work with rvalues. In that case, use a regular method with a & reference-category qualifier to eliminate that choice.
T and size are template parameters of myArray. If you put a definition of a function that containse those template parameters outside of the defintion of myArray, you have to state again, that they are template parameters, e.g.
template <typename T, int size, typename Val, typename Array>
However, that won't help you much, even if you get it to compile, because you won't be able to actually call the operator correctly, since the compiler can not deduce the template arguments T and size. The call would have to be something awkward like
auto a = operator*<double, 4>(22, someArray);
You probably want to make a function that only returns the same type as its second argument - anything else would not make much sense anyways. To avoid difficulties with template friend declarations (which are hard to get right) and the tight coupling you get with friends, you could relay the operator to a public multiplication function or, better yet, operator*=
template<typename T, int size>
class myArray {
T *_array;
public:
myArray() : _array(new T[size]{22}) {}
//...
template<typename Val>
myArray& operator*=(const Val &val) {
for (int i = 0; i < size; ++i)
_array[i] *= val ;
return *this;
}
};
template <typename Val, typename T, int size>
myArray<T,size> operator*(const Val &lhs, myArray<T, size> tmp) {
tmp *= lhs;
return tmp;
}
For a rationale why operator*= should be a member function and not a free friend function see this link

Multiplying an object with a constant from left side

I have a Matrix class and it has overloaded * operators for scalar and matrix multiplications.
template <class T> class Matrix
{
public:
// ...
Matrix operator*(T scalar) const;
// ...
}
// ...
template <class T>
Matrix<T> Matrix<T>::operator*(T RightScalar) const
{
Matrix<T> ResultMatrix(m_unRowSize, m_unColSize);
for (uint64_t i=0; i<m_unRowSize; i++)
{
for (uint64_t j=0; j<m_unColSize; j++)
{
ResultMatrix(i, j) = TheMatrix[m_unColSize * i + j] * RightScalar;
}
}
return ResultMatrix;
}
// ...
I can multiply a matrix object with a scalar from right side without any problem:
Matrix<double> X(3, 3, /* ... */); // Define a 3x3 matrix and initialize its contents
Matrix<double> Y; // Define an output matrix
Y = X * 10.0; // Do the linear operation
But, how do I multiply it from left side same way?
Matrix<double> X(3, 3, /* ... */);
Matrix<double> Y;
Y = 10.0 * X;
In arithmetic, it is a common notation to write constants on the left side when doing multiplication. I would like to obey this rule to make my code more readable.
Is it possible to implement this in C++?
If it is possible, how do I modify the class method in my code?
Member functions are matched by their left-hand-side argument which is the this-pointer. Since native types can't have member functions, you have to add right-multiplication with user-defined types through non-member functions (and also for other types you don't have write-access to).
template<typename T>
Matrix<T> operator*(T const& scalar, Matrix<T> rhs)
{
// scalar multiplication is commutative: s M = M s
return rhs *= scalar; // calls rhs.operator*=(scalar);
}
NOTE: I wrote the above non-member operator* implemented in terms of a member operator*=. It is recommended to write all multiplications as non-member functions, and use a member operator*= to implement these multiplications with a lhs Matrix element.
This will a) keep the class interface minimal, and b) prevent hidden conversions. E.g. you could have a Matrix class that is implicitly convertible to scalar if the dimensions are 1x1, and these conversions could silently happen if you don't provide a separate overload that is a direct match.
template<typename T>
Matrix<T> operator*(Matrix<T> lhs, T const& scalar)
{
return lhs *= scalar; // calls lhs.operator*=(scalar);
}
template<typename T>
Matrix<T> operator*(Matrix<T> lhs, Matrix<T> const& rhs)
{
return lhs *= rhs; // calls lhs.operator*=(rhs);
}
Notice on how the lhs Matrix is a copy and not a reference. This allows the compiler to make optimizations such as copy elision / move semantics. Also note that the return type of these operators is Matrix<T> and not const Matrix<T> which was recommended in some old C++ books, but which prevents move semantics in C++11.
// class member
template<typename T>
Matrix<T>& Matrix<T>::operator*=(Matrix<T> const& rhs)
{
// your implementation
return *this;
}
// class member
template<typename T>
Matrix<T>& Matrix<T>::operator*=(T const& scalar)
{
// your implementation
return *this;
}
You'll need a non-member function for that:
template <typename T>
Matrix<T> operator*(T scalar, Matrix<T> const & matrix) {
return matrix * scalar;
}
Non-member operator overloads allow you to specify any type on either side, while member overloads always get the object on the left-hand side.