c++ template and its element type - c++

This is my template matrix class:
template<typename T>
class Matrix
{
public:
....
Matrix<T> operator / (const T &num);
}
However, in my Pixel class, I didn't define the Pixel/Pixel operator at all!
Why in this case, the compiler still compiles?
Pixel class
#ifndef MYRGB_H
#define MYRGB_H
#include <iostream>
using namespace std;
class Pixel
{
public:
// Constructors
Pixel();
Pixel(const int r, const int g, const int b);
Pixel(const Pixel &value);
~Pixel();
// Assignment operator
const Pixel& operator = (const Pixel &value);
// Logical operator
bool operator == (const Pixel &value);
bool operator != (const Pixel &value);
// Calculation operators
Pixel operator + (const Pixel &value);
Pixel operator - (const Pixel &value);
Pixel operator * (const Pixel &value);
Pixel operator * (const int &num);
Pixel operator / (const int &num);
// IO-stream operators
friend istream &operator >> (istream& input, Pixel &value);
friend ostream &operator << (ostream& output, const Pixel &value);
private:
int red;
int green;
int blue;
};
#endif

C++ templates are instantiated at the point you use them, and this happens for the Matrix<T>::operator/(const T&), too. This means the compiler will allow Matrix<Pixel>, unless you ever invoke the division operator.

1) You didn't provide body of Matrix operator, so it is possible that Pixel/Pixel operator isn't needed.
2) Afaik, template methods do not generate compile errors unless you call them somewhere in your code. NO idea if this is standard or not, but some versions of MSVC behave this way. Do
Matrix m;
Pixel p;
m = m/p
somewhere in your code, and see what happens.

Related

What is the correct way to overload an operator of a primitive type in C++?

I am trying to write a simple matrix class to use in one of my course projects. The definition of the class is shown below.
#ifndef MATRIX_HH
#define MATRIX_HH
#include <cstdio>
#include <cstdlib>
#include <omp.h>
#include "MatrixException.hh"
#define F77_CALL(x) x ## _
#define F77_NAME(x) F77_CALL(x)
#ifdef __cplusplus
extern "C" {
#endif
extern void F77_NAME(dgemm)(const char *transa,const char *transb,
const int *m, const int *n, const int *k,
const double *alpha, const double *a, const int *lda,const double *b,
const int *ldb, const double *beta, double *c, const int *ldc);
#ifdef __cplusplus
}
#endif
class Matrix {
private:
/** The number of rows. */
int m;
/** The number of columns. */
int n;
protected:
/** The matrix entries, stored in row-major order. */
double *data;
public:
/** The matrix dimensions (as an array). */
int *dims;
Matrix(int m_,int n_);
Matrix(int m_,int n_,double *data_);
~Matrix();
void shape();
void print();
const double &operator()(int i) const;
const double &operator()(int i,int j) const;
double &operator()(int i,int j);
Matrix transpose();
Matrix operator + (const double c);
Matrix operator - (const double c);
Matrix operator * (const double c);
Matrix operator + (const Matrix &B);
Matrix operator - (const Matrix &B);
Matrix operator * (const Matrix &B);
double sum();
};
#endif
An example of how this class is used would be:
// Two random matrices
Matrix A(3,3),B(3,3);
// Matrix addition
Matrix C=A+B;
// Matrix-matrix multiplication
Matrix D=A*B;
// Add a scalar to each entry of A
Matrix E=A+1.;
This is already plenty of functionality, but I would find it useful for my matrix class to have the ability to do something like this:
Matrix A(3,3);
// This should be equivalent to A+1.
Matrix B=1.+A;
How can I overload the + operator of a primitive type like double to accomplish something like this? I tried declaring something like:
Matrix double::operator+(const Matrix&B);
However, this gives an error when I try to compile.
g++-10 -fopenmp -Wall -std=c++11 -O3 -framework Accelerate -c Matrix.cc
In file included from Matrix.cc:1:
Matrix.hh:53:2: error: two or more data types in declaration of 'operator+'
53 | Matrix double::operator + (const Matrix &B);
| ^~~~~~
What would be the correct way to do this?
PS. I know there exist linear algebra libraries like Eigen that provide a lot of functionality "out of the box". However, since this is for a course project, I have chosen to write my own matrix class.
You can add overload operator as non-member function.
Matrix operator+(double c, const Matrix&B) {
return B + c; // calling Matrix::operator + (const double c)
}
PS: Better to mark operators implemented as member-function as const, they're not supposed to perform modification on the object to be called on.
It can be done in this way:
In the class, add:
class Matrix {
...
public:
friend Matrix operator + (double a, const Matrix &B);
...
}
Then, define out of the class:
Matrix operator + (double a, const Matrix &B)
{
...
}
Best regards.

overload greater than operator with or without friend

Suppose I have the following class:
class Point{
private:
int x,y;
public:
int get_x() const {return x;}
int get_y() const {return y;}
Point() :x(0),y(0){}
Point(int x,int y):x(x),y(y){}
Point(const Point& P){
x = P.get_x();
y = P.get_y();
}
Point& operator= (const Point& P) {
x = P.get_x();
y = P.get_y();
return *this;
}
friend ostream& operator<<(ostream& os,const Point& P) {
os<<"["<<P.get_x()<<", "<<P.get_y()<<"]";
return os;
}
Point operator - (const Point &P){
return Point(x-P.get_x(),y-P.get_y());
}
friend bool operator > (const Point &A, const Point &B) {
return A.get_y()>B.get_y();
}
};
Here I used friend function. I can also use function without friend:
class Point{
...
bool operator > (const Point &B) const {
return y>B.get_y();
}
...
};
What are the differences between them in actual implementations? Also in the second method, the code won't compile without 'cont', why is that? Even after I changed the getter function into non-const function, it still won't compile without the 'const'.
As you've already noticed, comparison operator overloads can either be implemented as a member function or as a non-member function.
As a rule of thumb you should implement them as a non-member non-friend function where possible, as this increases encapsulation, and it allows (non-explicit) conversion constructors to be used on either side of the operator.
Say for instance your Point class for whatever reason had an int conversion constructor:
Point(int x);
With a non-member comparison operator you can now do the following:
Point p;
p < 3; // this will work with both a member and non-member comparison
3 < p; // this will **only** work if the comparison is a non-member function
You also seem to be confused about when to use const, again as a rule of thumb for comparison operators you should always use const wherever possible, because comparisons logically do not involve any change to the object.
As Point is a very small class you could also take it by value instead, so in order of most to least preferable your options are:
// Non-member, non-friend
bool operator>(Point const& A, Point const& B);
bool operator>(Point A, Point B);
// Non-member, friend
friend bool operator>(Point const& A, Point const& B);
friend bool operator>(Point A, Point B);
// Member
bool Point::operator>(Point const& B) const;
bool Point::operator>(Point B) const;

"Error: no matching function for call distance::distance()" ...Can´t declare an object from a class in main?

Im new at OOP and I keep having this error in this task. Maybe you can help me out.
This right here is the Class header file:
class Distance : public Magnitude
{
private:
double Cantidad;
char* Unidad;
public:
Distance(double c, char* u);
Distance(const Distance& d);
double getDistance(){return Cantidad;}
void setDistance(double val) {Cantidad=val;}
char* getUnidad(){return Unidad;}
void setUnidad(char* uni) {Unidad=uni;}
virtual ~Distance();
Distance& operator =(const Distance & d);
Distance operator +(const Distance & d);
Distance operator -(const Distance & d);
Distance operator *(const Distance & d);
Distance operator /(const Distance & d);
friend ostream& operator << (ostream &o,const Distance &d);
friend istream& operator >> (istream &o, Distance &d);
};
This over here is the cpp file, where I made the definitions:
#include "Distance.h"
Distance::Distance(double c, char* u)
{
Cantidad=c;
Unidad=u;
}
Distance::Distance(const Distance& d)
{
cout << "[***] NumComplejo -> Constructor por copia " << endl;
Cantidad = d.Cantidad;
Unidad = d.Unidad;
}
Distance::~Distance()
{
//dtor
}
And finally, this is where the error appears, in main, where I try to declare an object from the class Distance.
int main(int argc, char *argv[])
{
Distance d1; **/*right here*/**
EDIT:
If I typed: Distance d1=Distance(1231,"CSDVS"); it does work, but I need an empty objet so I can use the overload on >> operator
The error is caused by the fact that you are trying to initialize an object with a default constructor that you haven't defined.
[...] but I need an empty objet so I can use the overload on >> operator.
You can do this by simply defining a default constructor:
// …
Distance::Distance()
: Cantidad(0)
, Unidad(nullptr)
{}
// …
You, also, probably want to use std::string for strings.

Is it possible to overload the ostream operator for arithmetic expressions?

Is it possible to create an overload for the ostream operator that does an arithmetic operation (addition for example) and then streams out the result? The standard ostream overload that can be found all over the web can only stream from a single variable. I need something that does the following:
std::cout << x+y << std::endl;
or even more complex expressions like:
std::cout << x*y+(3*z)^2 << std::endl;
where x, y, and z are instances of a simple custom-made struct where arithmetic operations are already defined (overloaded).
EDIT:
Here is my code:
struct scalar //complex scalar data structure
{
friend scalar operator^(const scalar&, int); //integer power operator overload
friend scalar exp(const scalar&); //exponential power function
std::ostream& operator<<(std::ostream&, const scalar&)
protected:
double re;
double im;
public:
double real() {return re;} //returns the real part
double imag() {return im;} //returns the imaginary part
scalar(double _re, double _im) {re=_re;im=_im;} //constructor 1
scalar(double _re) {re=_re;im=0.0;} //constructor 2
scalar(const scalar& s): re(s.re), im(s.im) {} //copy constructor
scalar& operator=(const scalar& rhs) //assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=rhs.re; //sets real parts equal
im=rhs.im; //sets imaginary parts equal
return *this;
}
scalar& operator+=(const scalar& rhs) //compound addition-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=re+rhs.re; //adds real parts
im=im+rhs.im; //adds imaginary parts
return *this;
}
scalar& operator*=(const scalar& rhs) //compound multiplication-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
re=x1*x2-y1*y2; //multiplies real parts
im=x1*y2+x2*y1; //multiplies imaginary parts
return *this;
}
scalar& operator-=(const scalar& rhs) //compound subtraction-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=re-rhs.re; //adds real parts
im=im-rhs.im; //adds imaginary parts
return *this;
}
scalar& operator/=(const scalar& rhs) //compound division-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
double n;
n =pow(x2,2)+pow(y2,2);
if (n==0) throw(1);
re=(x1*x2+y1*y2)/n; //multiplies real parts
im=(x2*y1-x1*y2)/n; //multiplies imaginary parts
return *this;
}
const scalar operator+(const scalar& b) //addition operator overload
{
scalar c = *this;
c+=b;
return c;
}
const scalar operator*(const scalar& b) //addition operator overload
{
scalar c = *this;
c*=b;
return c;
}
const scalar operator-(const scalar& b) //addition operator overload
{
scalar c = *this;
c-=b;
return c;
}
const scalar operator/(const scalar& b) //addition operator overload
{
scalar c = *this;
c/=b;
return c;
}
};
scalar i(0.0,1.0);
scalar j(0.0,1.0);
std::ostream& operator<<(std::ostream& out, const scalar& s)
{
out << s.re << '+' << s.im << 'i';
return out;
}
scalar operator^(scalar a, int b) //integer power operator overload
{
double x=a.real(); double y=a.imag();
if (x==0) throw(1);
int r=sqrt(pow(x,2)+pow(y,2));
int arg=atan2(y,x);
scalar c(r*cos(arg),r*sin(arg));
return c;
}
scalar exp(const scalar& s) //exponential power function
{
double x=s.re; double y=s.im;
scalar c(exp(x)*cos(y),exp(x)*sin(y));
return c;
}
Here is my main function:
int main()
{
scalar x(3,4);
scalar y=2;
cout << x*y << endl;
return 0;
}
This is is the output it is supposed to give:
6+8i
And this is the errors it gives instead:
In function 'std::ostream& operator<<(std::ostream&, const scalar&)':|
error: passing 'const scalar' as 'this' argument of 'double scalar::real()'
discards qualifiers|
And if I remove the const as the compiler says, I will get the following error:
error: no match for 'operator<<' in 'std::cout << scalar::operator*(const scalar&)
(((const scalar&)((const scalar*)(& y))))'|
The << operator can't handle the full expression - and why should it?
You need to implement the separate operators (operator+, operator*, ...) for your struct, which take your structs as parameters, do the corresponding operation on it, and return another of your structs. And only then define a operator<< taking a single one of your structs.
How would you even think of passing in such a complex structure to the operator<<, let alone parse it in there? Implement the separate operators, and leave the parsing to the compiler.
e.g. for a simple struct only encapsulating an int, doing that with + operation would look like this:
struct mystruct
{
int value;
};
then define:
mystruct const operator+(mystruct const & a, mystruct const & b)
{
mystruct result;
result.value = a.value + b.value;
return result;
}
and
std::ostream & operator<<(std::ostream& out, mystruct const & a)
{
out << a.value;
return out;
}
then you can do:
mystruct a, b;
a.value = 1;
b.value = 2;
std::cout << a+b;
Edit: With your updated code, there's exactly one problem:
std::ostream& operator<<(std::ostream&, const scalar&)
should be
friend std::ostream& operator<<(std::ostream&, const scalar&);
i.e. you're missing friend and an ;
Though the error you show suggests some different problem (which jrok's answer would have a solution for) - that doesn't seem to result from compiling the code you show! So please get the shown code and error message in sync.
The error is because functions scalar::real and scalar::imag are not const - you can only call const member functions when you've got a reference to a constant scalar.
double real() const {return re;}
double imag() const {return im;}
Why don't you just write std::cout << (x+y) << std::endl;
and be done?
As long as your overloaded operator takes its argument by value:
ostream& operator<<(ostream&, Thing)
or constant reference:
ostream& operator<<(ostream&, const Thing&)
you can use it for any expression with type Thing.
You should put parentheses around complex expressions, to avoid surprises from operator precedence; in particular, the second expression involving ^ won't be parsed as you expect.
You'll only be restricted to a single variable (or, more accurately, an lvalue expression) if the operator requires a non-constant reference; so don't do that.
UPDATE Now we've seen the code, the main issue is the in-class definition of operator<< as a member function; it can't be a member. Perhaps you want it to be a friend, so it can access im and re; or perhaps you should remove the declaration (making it a non-member, non-friend), and just use the public interface. If you do that, you'll need to add const to real() and imag(), so they can be called on a const object. You should do that anyway.
(Looking at the reported error, it seems you've already changed it to use the public interface, but haven't declared the necessary functions const).

should friend functions be represented in UML diagrams?

Also, how exactly are overloaded operator member functions best formatted in a UML diagram?
Here is my class:
class matrix
{
friend ostream& operator << (ostream&, const matrix&);
friend bool operator == (const matrix &, const matrix &);
friend matrix operator - (const matrix &, const matrix &);
private:
int size;
int range;
int array[10][10];
public:
matrix(int);
matrix(int, int);
bool operator != (const matrix &) const;
matrix operator + (const matrix &) const;
const matrix & operator = (const matrix &);
};
and here is what I have of my UML diagram so far:
By placing the stereotype <<friend>> in front of the operation in the UML class diagram.
You will have to do it this way:
<<friend>> ostream& operator << (ostream&, const matrix&)
<<friend>> bool operator == (const matrix &, const matrix &)
<<friend>> matrix operator - (const matrix &, const matrix &)