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.
Related
it's a test from some company.
overload & to return sum of int[][]
main()
{
int arr[5][5];
// initialization
cout << &arr; // output the sum of arr
}
I try this code but returns compile error:
long operator &(int** arr)
{
// return the sum of arr
}
error: the argument should contains class type or enumeration
currently I understand this error, but how to overload operator for buildin types?
Example of overloading operator &, only for educational use!
I would NOT recommend overloading operator& in any serious code.
#include <iostream>
struct my_array
{
my_array()
{
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
values[i][j] = 1 + i + j;
}
}
}
int operator&()
{
int sum = 0;
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
sum += values[i][j];
}
}
return sum;
}
private:
int values[5][5]{};
};
int main()
{
my_array m;
int sum = &m;
std::cout << sum;
}
I think interviewer may want you to overload operator<< actually, not & and the solution could then be like below. See it live here.
#include <iostream>
using int5x5_t = int[5][5];
std::ostream& operator<<(std::ostream& os, const int5x5_t* parr) {
long sum = 0;
for (auto& vec : *parr) {
for (auto val : vec) {
sum += val;
}
}
return os << sum;
}
int main() {
int arr[5][5] = {
{0, 1, 2, 3, 4},
{0, 1, 2, 3, 4},
{0, 1, 2, 3, 4},
{0, 1, 2, 3, 4},
{0, 1, 2, 3, 4}
};
std::cout << &arr << std::endl;
}
#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.
int* filtrationBiggerValues(int* values, int nrValues, int givenValue) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
return new_array;
}
void main() {
int y[] = { 1,2,100,18,20,94 };
cout<< filtrationBiggerValues(y, 6, 8)<<"\n";
}
I should see the new array with the values bigger than a certain value, but instead I get its address.
That is not how it works. You are returning a pointer from your function not the value. If you want to see the values as output you should iterate on the array and print out each element separately. Also note returning size of your output array from the function for easy iteration.
int* filtrationBiggerValues(int* values, int nrValues, int givenValue, int& outputSize) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
outputSize = j;
return new_array;
}
void main()
{
int y[] = { 1,2,100,18,20,94 };
int outputSize = 0;
int* output = filtrationBiggerValues(y, 6, 8, outputSize);
for(int i=0; i<outputSize; ++i)
{
cout<< output[i] <<"\n";
}
}
Update (If you want to keep signature of the function as it is)
int* filtrationBiggerValues(int* values, int nrValues, int givenValue) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
new_array[j] = 0;
return new_array;
}
void main()
{
int y[] = { 1,2,100,18,20,94 };
int* output = filtrationBiggerValues(y, 6, 8);
for(int i=0; output[i]>0; ++i)
{
cout<< output[i] <<"\n";
}
}
the name of the array is actually a pointer.
if you try this:
int main()
{
int y[] = { 1,2,100,18,20,94 };
cout << y <<endl;
cout<< filtrationBiggerValues(y, 6, 8)<<"\n";
return 0;
}
the output is two address
0x7ffd7ac2bc10
0xfadc30
So much to say:
int* new_array = NULL; C++ uses nullptr. I.e. int* new_array = nullptr;
However, you should inlue the initialization you do next line:
int* new_array = new int[nrValues];
But you just created a new object on the heap, that you don't delete. That is called a memory leak.. Nowadays we use unique pointers to help us there.
std::unique_ptr<int[]> new_array = new int[nrValues];
However, in C++ we have STL containers handle all the C-style array stuff for you. As new_array is a different size then values, you probably want to use std::vector, which has a dynamic size. The STL containers have something called iterators, which can go over the element more efficiently. However, the STL containers don't have default output functions, so you'll have to write your own.
#include<vector>
#include<iostream>
std::vector<int> getBiggerThen(std::vector<int> const& input, int givenValue) {
std::vector<int> output;
for (auto it = input.cbegin(); it != input.cend(); it++) {
if (*it > givenValue) {
output.push_back(*it);
}
}
return output;
}
std::ostream& operator<< (std::ostream& out, std::vector<int> const& vec) {
for (auto const& el : vec) out << el << " ";
return out;
}
int main() {
auto y = std::vector<int>{ 1,2,100,18,20,94 };
std::cout << getBiggerThen(y, 8) << "\n";
}
oh... also important: in C++ main should always return an int.
Finally, what you are doing is required so often, that the STL library has an built-in algorithm for it. Which can reduce everything to
#include<vector>
#include<algorithm>
#include<iostream>
int main() {
auto y = std::vector<int>{ 1,2,100,18,20,94 };
std::vector<int> output{};
int givenValue = 8;
std::copy_if(std::cbegin(y), std::cend(y), std::back_inserter(output),
[givenValue](int val) { return val >= givenValue; });
for (auto const& el : output) std::cout << el << " ";
std::cout << "\n";
}
So I have a little class that implements a matrix. Everything works well, except whatever gave me the reason to post here. I've explained more about the problem in the actual code, using comments. Thanks in advance to anyone that can help! This is not the entire program, but it is big enough so that it can compile on its own.
#include <iostream>
#include <initializer_list>
template<class type_t, unsigned Rows, unsigned Columns>
class matrix
{
private:
std::initializer_list<std::initializer_list<type_t>> elements;
public:
type_t contents[Rows][Columns];
matrix() {}
matrix(const std::initializer_list<std::initializer_list<type_t>> &container)
: elements(container)
{
unsigned i = 0;
for (const auto &el : elements)
{
unsigned j = 0;
for (const auto &num : el)
{
contents[i][j] = num;
j++;
}
i++;
}
}
unsigned rows() { return Rows; }
unsigned columns() { return Columns; }
type_t &operator()(const unsigned &i, const unsigned &j)
{
return contents[i][j];
}
template<unsigned rws, unsigned cls>
auto operator*(matrix<type_t, rws, cls> &mat)
{
matrix<type_t, Rows, 3> ret_mat; //OK, but only in case the return matrix has 3 columns
matrix<type_t, Rows, mat.columns()> ret_mat; //Error. This is the desired result
//The error message tells me it needs to be a compile-time constant
//it's pretty obvious why the first works and what the problem is
//but i still have no idea how to get past this
for (unsigned i = 0; i < this->rows(); ++i)
{
for (unsigned j = 0; j < mat.columns(); ++j)
{
for (unsigned in = 0; in < 2; ++in)
ret_mat.contents[i][j] += this->contents[i][in] * mat.contents[in][j];
}
}
return ret_mat;
}
};
int main()
{
matrix<int, 4, 2> mat = { { 7, 3 },{ 2, 5 },{ 6, 8 },{ 9, 0 } };
matrix<int, 2, 3> mat2 = { { 7, 4, 9 },{ 8, 1, 5 } };
auto mat3 = mat * mat2;
for (unsigned i = 0; i < mat3.rows(); ++i)
{
for (unsigned j = 0; j < mat3.columns(); ++j)
std::cout << mat3(i, j) << " ";
std::cout << std::endl;
}
std::cin.get();
}
template<unsigned rws, unsigned cls>
You already have desired expressions!
matrix<type_t, Rows, cls> ret;
Edit: as mentioned by #juanchopanza, why are you allowing multiplication of N*M on K*L with M != K? Should be
template<unsigned cls>
auto operator*(matrix<type_t, columns, cls> &mat)
{
matrix<type_t, Rows, cls> ret_mat;
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.