I have a very simple code where I am trying to create class template. Unfortunately, I am getting error with my code for the friend function.
In the following code 'myArray' as a template class. How can I handle the friend function operator *(...) in this scenario? With my current code, I get following error:
compilation error:error: invalid use of template-name 'myArray'
without an argument list myArray operator * (myArray &a1, myArray &a2)*/
Here is the code:
#include<iostream>
using namespace std;
const int sz = 3;
template <typename T>
class myArray
{
T *arr;
const static int size = 3;
public:
myArray()
{
arr = new T[size];
for (int i=0; i<size; i++)
arr[i] = 0;
}
myArray(T *actArray)
{
arr = new T[size];
for (int i=0; i<size; i++)
arr[i] = actArray[i];
}
void prArray()
{
cout<<endl<<endl;
for (int i=0; i<size; i++)
cout << "arr [" << i << "] = " << arr[i] << endl;
}
friend myArray operator * (myArray &arr1, myArray &arr2);
};
myArray operator * (myArray &a1, myArray &a2)
{
myArray product;
for (int i=0; i<sz; i++)
product.arr[i] = a1.arr[i] * a2.arr[i];
return product;
}
int main()
{
int xi[3] = {1, 2, 3};
int yi[3] = {5, 5, 5};
float xf[3] = {1.1, 2.1, 3.1};
float yf[3] = {5.5, 5.5, 5.5};
//considering template class as integer
myArray <int>a1;
myArray <int>a2;
a1 = xi;
a2 = yi;
a1.prArray();
a2.prArray();
cout<<"Interger class..."<<endl;
myArray <int>a3;
a3 = a1 * a2;
a3.prArray();
/*//considering template class as float
myArray <float>b1, <float>b2;
b1 = xi;
b2 = yi;
b1.prArray();
b2.prArray();
cout<<"Float class..."<<endl;
myArray <float>b3;
b3 = b1 * b2;
b3.prArray();*/
}
Move the body of operator* into the body of the class:
friend myArray operator * (myArray &arr1, myArray &arr2) {
myArray product;
for (int i=0; i<sz; i++)
product.arr[i] = a1.arr[i] * a2.arr[i];
return product;
}
Also:
myArray operator*=(myArray const& arr2)& {
for (int i=0; i<sz; i++)
arr[i] *= a2.arr[i];
return *this;
}
friend myArray operator * (myArray arr1, myArray const& arr2) {
arr1*=arr2;
return arr1;
}
with efficient move this reduces temporary objects created.
//Finally I define the friend function in the class itself along with the suggestions made by Peter.... so the final code is...Thanks all for your help
But still didn't understand why we made it as const parameters...?
#include<iostream>
using namespace std;
template <typename T>
class myArray
{
T *arr;
const static int size = 3;
public:
myArray()
{
arr = new T[size];
for (int i=0; i<size; i++)
arr[i] = 0;
}
myArray(T *actArray)
{
arr = new T[size];
for (int i=0; i<size; i++)
arr[i] = actArray[i];
}
void prArray()
{
cout<<endl<<endl;
for (int i=0; i<size; i++)
cout << "arr [" << i << "] = " << arr[i] << endl;
}
friend myArray<T> operator* (const myArray<T>& a1, const myArray<T>& a2)
{
myArray <T> product;
for (int i=0; i<size; i++)
product.arr[i] = a1.arr[i] * a2.arr[i];
return product;
}
};
int main()
{
int xi[3] = {1, 2, 3};
int yi[3] = {5, 5, 5};
float xf[3] = {1.1, 2.1, 3.1};
float yf[3] = {5.5, 5.5, 5.5};
//considering template class as integer
myArray <int>a1;
myArray <int>a2;
a1 = xi;
a2 = yi;
a1.prArray();
a2.prArray();
cout<<"Interger class..."<<endl;
myArray <int>a3;
a3 = a1 * a2;
a3.prArray();
//considering template class as float
myArray <float>b1;
myArray <float>b2;
b1 = xf;
b2 = yf;
b1.prArray();
b2.prArray();
cout<<"Float class..."<<endl;
myArray <float>b3;
b3 = b1 * b2;
b3.prArray();
}
Related
I have this code of overloaded operator for vectors class, which is a class of vector of dimension 3:
class Vectors
{
//private:
// double* vector;
public:
double* vector;
Vectors(double*);
Vectors();
Vectors(const Vectors&);
~Vectors();
void print_vector();
};
Class Methods:
Constructors:
Vectors::Vectors(double* value)
{
this->vector = new double[3];
for (auto i = 0; i < 3; i++)
{
this->vector[i] = value[i];
}
}
Vectors::Vectors()
{
this->vector = new double[3];
for (auto i = 0; i < 3; i++)
{
this->vector[i] = 0.0;
}
}
Copy Constructors:
Vectors::Vectors(const Vectors& copy)
{
this->vector = new double[3];
for (auto i = 0; i < 3; i++)
{
this->vector[i] = copy.vector[i];
}
}
Destructor:
Vectors::~Vectors()
{
//cout << "desctructor called \n";
delete[] vector;
}
void Vectors::print_vector(){
for (int i=0; i<3 ;i++){
cout << this->vector[i];
cout << '\t';
}
cout << endl;
}
Overloaded Operator:
Vectors operator+(const Vectors& obj1,const Vectors& obj2)
{
Vectors *res = new Vectors;
for (int i = 0; i < 3; i++){
//cout << obj1.vector[i] << '\t' << obj2.vector[i] << '\t' << obj1.vector[i] + obj2.vector[i] << endl;
res->vector[i] = obj1.vector[i] + obj2.vector[i];
//cout << res->vector[i] << endl;
}
//res->print_vector();
return *res;
}
int main()
{
double a[3] = {3.5,4.10,5.30};
double b[3] = {7.0,8.0,9.0};
Vectors* A = new Vectors(a);
Vectors* B = new Vectors(b);
Vectors* C = new Vectors();
*C = *A+*B; // This does not work
(*A+*B).print_vector(); // This works
C->print_vector();
Vectors D = *A+*B; // This works
D.print_vector();
}
When creating a pointer to an object Vectors, I get different results when compared to creating direct objects.
Output is:
1st Output:
0 4.68558e-310 14.3
2nd Output:
10.5 12.1 14.3
3rd Output:
10.5 12.1 14.3
This version works, but I have still got memory leak using valgrind. Can somebody point out where?
#include <iostream>
using namespace std;
class Vectors
{
//private:
// double* vector;
public:
double* vector;
Vectors(double*);
Vectors();
Vectors(const Vectors&);
~Vectors();
void print_vector();
Vectors operator=(const Vectors&);
};
Vectors::Vectors(double* value)
{
this->vector = new double[3];
for (auto i = 0; i < 3; i++)
{
this->vector[i] = value[i];
}
}
Vectors::Vectors()
{
this->vector = new double[3];
for (auto i = 0; i < 3; i++)
{
this->vector[i] = 0.0;
}
}
Vectors::Vectors(const Vectors& copy)
{
this->vector = new double[3];
for (auto i = 0; i < 3; i++)
{
this->vector[i] = copy.vector[i];
}
//this->vector = (copy.vector);
}
Vectors::~Vectors()
{
//cout << "desctructor called \n";
delete[] vector;
}
void Vectors::print_vector(){
for (int i=0; i<3 ;i++){
cout << this->vector[i];
cout << '\t';
}
cout << endl;
}
Vectors Vectors::operator=(const Vectors& obj1)
{
this->vector = new double[3];
if (this != &obj1)
{
for (int i = 0; i < 3; i++) {
this->vector[i] = obj1.vector[i];
}
}
return *this;
}
Vectors operator+(const Vectors& obj1,const Vectors& obj2)
{
Vectors res;
for (int i = 0; i < 3; i++){
res.vector[i] = obj1.vector[i] + obj2.vector[i];
}
return res;
}
int main()
{
double a[3] = {3.5,4.10,5.30};
double b[3] = {7.0,8.0,9.0};
Vectors* A = new Vectors(a);
Vectors* B = new Vectors(b);
Vectors* C = new Vectors();
*C = *A+*B;
C->print_vector();
//(*A+*B).print_vector();
//cout << C->vector[1]<<endl;
//double a[3] = {3.5,4.10,5.30};
//double b[3] = {7.0,8.0,9.0};
//Vectors A(a), B(b);
Vectors D = *A+*B;
//Vectors C = A-B;
//Vectors C = A*B;
//Vectors C = 5*A;
//Vectors C = 5.5*A;
//Vectors C = A/B;
//Vectors C = 5/A;
//Vectors C = 5.5/A;
D.print_vector();
delete[] A;
delete[] B;
delete[] C;
}
#include <iostream>
using namespace std;
template<class T>
class Array {
public: // should be private, big ignore that
int n;
T *arr;
public:
Array(int sz, T initValue) {
n = sz;
arr = new T[n];
for (int i=0; i<n; i++) arr[i] = initValue;
}
Array& operator = (const Array& b) {
if (this!=&b) {
delete[] arr;
n = b.n;
arr = new T[n];
for (int i=0;i<n;i++) arr[i] = b.arr[i];
}
return *this;
}
Array operator + (const Array& b) {
Array res(n, 0);
for (int i=0; i<n;i++) res.arr[i] = arr[i] + b.arr[i];
return res;
}
};
int main()
{
Array<double> a(10, 1); //Array<double> b(10, 2); // this works
Array<int> b(10, 2);
a = b; // error
for (int i=0; i<10; i++) cout << i << " " << a.arr[i] << "\n";
Array<double> c(10,0);
c = a + b; // error if b is <int>, runs if b is <double>
c = a - b;
c = a * b;
}
So I have a template class that can takes int, float, double, ...
Intuitively, Array<double> a; Array<int> b; a = b; should be possible because element-wise, we can do a[i] = b[i]. However, I have the conversion error because something is missing.
How can I make a = b; possible? Thank you.
Edit: the point is not about making an Array. It can be a Matrix, 3dArray, etc. It's about assignment of a float template and int template. You can also replace int with float, and float with highPrecisionFloat, for example.
Edit 2: I forgot to mention, I not just only need operator =, but operator + (and - * /, etc) as well. If I user #churill answer, I need to do so for each operator. How can I make conversion from Array to Array implicit?
In the class template
template<class T>
class Array { ... }
The identifier Array refers actually to Array<T>. You will have to make operator== a template and you probably want to add an explicit cast:
template<typename TOther>
Array<T> &operator = (const Array<TOther>& b) {
if constexpr (std::is_same<T, TOther>::value) {
// only check for self-assignment T and TOther are the same type
if (this == &b)
{
return *this;
}
}
delete[] arr;
n = b.n;
arr = new T[n];
for (int i=0;i<n;i++)
arr[i] = static_cast<T>(b.arr[i]);
return *this;
}
Note that std::is_same is from the type_traits-header.
Hello everyone i'm trying to write an assignment operator for this class so i can assign an array like thisint[] = {0, 1, 2, 3} to my Tableau class
originally i wanted to do this
Tableau<T>& operator=(T arr[])
{
return Tableau(tab, sizeofarray);
}
because i already wrote a constructor that takes and array and the size as its argument
and i ran into a problem with the size of the the array i don't know how to find it
how can i find the size of the array or is there a better way to do this
template<typename T>
class Tableau
{
public:
Tableau(int s = 0) : size(s), ptr(new T[size])
{
for (int i = 0; i < size; i++)
{
ptr[i] = 0;
}
}
Tableau(T tab[], int s = 0) : size(s), ptr(new T[size])
{
for (int i = 0; i < size; i++)
{
ptr[i] = tab[i];
}
}
~Tableau()
{
delete[] ptr;
}
Tableau<T>& operator=( T tab[])
{
}
T commule()
{
T com = 0;
for (int i = 0; i < size; i++)
{
com += ptr[i];
}
return com;
}
T& operator[](const int index)
{
return ptr[index];
}
private:
int size;
T* ptr;
};
int main()
{
int k[] = { 8, 12, 5, 9, 55};
Tableau<int> TI(k, 2);
TI = k;
return 0;
}
You can use:
template <std::size_t N>
Tableau<T>& operator=(T (&arr)[N])
{
// This is not right.
// The returned value is a temporary.
// return Tableau(arr, N);
// Update the contents of the object.
// ...
// Then, return a reference to this object.
return *this;
}
With that member function template, when you invoke:
int k[] = { 8, 12, 5, 9, 55};
Tableau<int> TI(k, 2);
TI = k;
The operator= function is instantiated with N = 5 and k as the value of arr. Hence, you get the size of the array as well as the contents of the array.
However, it is worth pointing out that if you use:
int k[] = { 8, 12, 5, 9, 55};
int* k2 = k;
Tableau<int> TI(k, 2);
TI = k2;
it won't work. k2 is not an array. It is a pointer to an int, which happens to point to the first element of k.
This is example from a text book. We are creating vector using templates. in main function we copy the predefined array into vectors. Finally, we multiply two vectors. Although program compiles nicely the program fails to execute. Whats wrong with the code.
#include <iostream>
const int size = 3;
template<class T>
class vector
{
T* v;
public:
vector()
{
v = new T[size];
for (int i = 0; i < size; i++){
v[i] = 0;
}
}
vector(const T* a)
{
for (int i = 0; i < size; i++){
v[i] = a[i];
}
}
T operator * (const vector& y)
{
T sum = 0;
for (int i = 0; i < size; i++){
sum += this->v[i] * y.v[i];
}
return sum;
}
};
int main()
{
int x[3] = { 1, 2, 3 };
int y[3] = { 4, 5, 6 };
vector<int> v1;
vector<int> v2;
v1 = x;
v2 = y;
int R = v1 * v2;
std::cout << R;
return 0;
}
First of all in this constructor
vector(T *a)
{
for(int i=0;i<size;i++){
v[i]= a[i];
}
}
you did not allocate the array pointed to by v. Pointer v is not initialized. So the constructor has undefined behaviour.
And another potential problem is that you did not define the copy assignment operator.
In these statements
v1 = x; v2 = y;
temporary objects of type vector are created and after the assignment they will be deleted. Thus the new created objects will have invalid pointer v.
You have to define at least copy constructor, copy assignment operator and destructor.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Operator[][] overload
I have made class which contains an array containing (in one row) all the numbers from the given 2d array. For example given: {{1,2}{3,4}} the b field in the object of class T contains {1,2,3,4}. I would like to overload[][] operator for this class so it will work like that
T* t.....new etc.
int val = (*t)[i][j]; //I get t->b[i*j + j] b is an 1dimension array
class T{
public:
int* b;
int m, n;
T(int** a, int m, int n){
b = new int[m*n];
this->m = m;
this->n = n;
int counter = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
b[counter] = a[i][j];
counter++;
}
}
}
int main()
{
int m = 3, n = 5, c = 0;
int** tab = new int*[m];
for(int i = 0; i < m; i++)
tab[i] = new int[n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
tab[i][j] = c;
c++;
cout<<tab[i][j]<<"\t";
}
cout<<"\n";
}
T* t = new T(tab,3,5);
};
You cannot. You have to overload operator[] to return a proxy object, that in turn, overloads operator[] to return the final value.
Something like:
class TRow
{
public:
TRow(T &t, int r)
:m_t(t), m_r(r)
{}
int operator[](int c)
{
return m_t.tab[m_t.n*m_r + c];
}
private:
T &m_t;
int m_r;
};
class T
{
friend class TRow;
/*...*/
public:
TRow operator[](int r)
{
return TRow(*this, r);
}
};
Instead of saving a T& in TRow you could save directly a pointer to the row, that's up to you.
A nice feature of this solution is that you can use the TRow for other things such as operator int*().
In the case of a 2d array, you don't need to create a proxy type. Just use int*:
#include <iostream>
class T {
public:
int m, n;
int *b;
T(int m, int n) : m(m), n(n), b(new int[m*n]) {
}
int*operator[](std::size_t i) {
return &b[i*m];
}
};
int main () {
T t(2,2);
t[0][0] = 1;
t[0][1] = 2;
t[1][0] = 3;
t[1][1] = 4;
std::cout << t.b[0] << t.b[1] << t.b[2] << t.b[3] << "\n";
}