C++ Overloading Array Operator

C++ overloading array operator

It is idiomatic to provide couple of overloads of the operator[] function - one for const objects and one for non-const objects. The return type of the const member function can be a const& or just a value depending on the object being returned while the return type of the non-const member function is usually a reference.

struct Heap{
int H[100];
int operator [] (int i) const {return H[i];}
int& operator [] (int i) {return H[i];}
};

This allows you to modify a non-const object using the array operator.

Heap h1;
h1[0] = 10;

while still allowing you to access const objects.

Heap const h2 = h1;
int val = h2[0];

How to overload + operator for arrays in C++?

T operator+(const T& a1, const T& a2) takes two Ts as parameter and returns a T. That is not what you want.

This is how you can concatenate two arrays by using operator+:

#include <iostream>
#include <array>


template <typename T,size_t M,size_t N>
std::array<T,M+N> operator+(const std::array<T,M>& a1, const std::array<T,N>& a2) {
std::array<T,M+N> a;
for (size_t i = 0; i < M; ++i) {
a[i] = a1[i];
}
for (size_t i = 0; i < N; ++i) {
a[i + M] = a2[i];
}
return a;
}

int main() {
std::array<int,3> a1 = { 1, 3, 4 };
std::array<int,4> a2 = { 2, 3, 5, 6 };
std::array<int,7> a3 = a1 + a2;

for (const auto& e : a3){
std::cout << e << " ";
}

std::cout << "\n";
}

Your code somehow mixes elementwise addition and concatenation. And there were some typos in the implementation of operator+ (eg size instead of size() and accessing a2 out of bounds).

And another question, does this code use generic class?

No. Your operator+ (and the one above) is a free function. std::array is a generic container and std::array<int,N> is a class.

Overloading operator += with array c++

no match for operator[] (operand types are 'int [0]' and 'const
bitArray')|

The error is crystal clear that the operator[] expecting an interger type and what you passing a bitArray class type. Simple fix is to change it to integer.

However, here:

private:
int sortie[];
int n;

it is highly recommended to use std::vector, which gives a contiguous dynamic array whereas sortie[]is static allocation. Something like this:

See live here

#include <iostream>
#include <vector>
#include <cstddef>

class bitArray
{
private:
std::vector<int> sortie;
public:
explicit bitArray(int size): sortie(size) {}
bitArray& operator+=(const std::size_t i)
{
if (0 <= i && i < sortie.size()) // check for (0 <= index < size) of the array
{
this ->sortie[i] = 1;
return *this;
}
else
{
// do your logic! for instance, I have done something like follows:
std::cout << "out of bound" << std::endl;
if(sortie.size() == 0) sortie.resize(1,0); // if the size of array == 0
}
return *this;
}
int operator[] (const std::size_t index)
{
return (0 <= index && index < sortie.size()) ? sortie[index] : -1;
}
};
int main ()
{
bitArray obj(3);
obj += 0; std::cout << obj[0] << std::endl;
obj += -2; std::cout << obj[-2] << std::endl;
obj += 22; std::cout << obj[22] << std::endl;
return 0;
}

Update: Using C++17 feature std::optional, modified the above solution with the optional return type, which should be more readable.

See output in wandbox

#include <iostream>
#include <vector>
#include <cstddef>
#include <optional>

class bitArray
{
private:
std::vector<int> sortie;
public:
explicit bitArray(int size): sortie(size) {}
// optional is used as the return type
std::optional<bitArray> operator+=(const std::size_t i)
{
if (i < sortie.size()) // check for (0 <= index < size) of the array
{
this -> sortie[i] = 1;
return std::optional<bitArray>{*this};
}
std::cout << "out of bound operation+= \t";
return std::nullopt; // std::nullopt to create any (empty) std::optional
}
std::optional<int> operator[] (const std::size_t index)
{
if(index < sortie.size()) return std::optional<int>{sortie[index]};
else
{
std::cout << "out of bound operator[]: ";
return std::nullopt;
}
}
};
int main ()
{
bitArray obj(3);
obj += 0; std::cout << obj[0].value_or(-1) << std::endl;
obj += -2; std::cout << obj[-2].value_or(-1) << std::endl;
bitArray obj1(0);
obj1 += 22; std::cout << obj1[22].value_or(-1) << std::endl;
return 0;
}

how overload operator for an array in C++?

You could do this:

template <typename T, unsigned int N>
std::ostream & operator<<(std::ostream & os, const T (&arr)[N])
{
// ..
return os;
}

This works only for compile-time arrays, of course. Note that you are not allowed to instantiate this template when T is a built-in type or a type in the std namespace!

Probably best to make this inline if possible, since you'll cause a separate instantiation for every N. (The pretty printer has an example of this.)

You will notice, though, that the blanket template introduces an ambiguity, because os << "Hello" now has two possible overloads: the template matching const char (&)[6], and the (non-template) overload for the decay-to-pointer const char *, which both have identical conversion sequences. We can resolve this by disabling our overload for char arrays:

#include <ostream>
#include <type_traits>

template <typename T, unsigned int N>
typename std::enable_if<!std::is_same<T, char>::value, std::ostream &>::type
operator<<(std::ostream & os, const T (&arr)[N])
{
// ..
return os;
}

In fact, to be even more general you can also make the basic_ostream parameters template parameters:

template <typename T, unsigned int N, typename CTy, typename CTr>
typename std::enable_if<!std::is_same<T, char>::value,
std::basic_ostream<CTy, CTr> &>::type
operator<<(std::basic_ostream<CTy, CTr> & os, const T (&arr)[N])
{
// ..
return os;
}

In view of the fact that T must be a user-defined type, you could even replace is_same<T, char> with is_fundamental<T> to get a bit more checking (but users still must not use this for arrays of standard library types).

Overload operator '+' to add two arrays in C++

This is probably wrong, but it appears to work (C++11):

#include <iostream>
#include <array>

using namespace std;

template <class T>
T operator+(const T& a1, const T& a2)
{
T a;
for (typename T::size_type i = 0; i < a1.size(); i++)
a[i] = a1[i] + a2[i];
return a;
}

int main()
{
array<int,5> a1 = { 1, 2, 3, 4, 5 };
array<int,5> a2 = { 2, 3, 4, 5, 6 };
array<int,5> a3 = a1 + a2;

for (int i = 0; i < 5; i++)
cout << a1[i] << '+' << a2[i] << '=' << a3[i] << ' ';

cout << endl;
return 0;
}

Output (ideone):

1+2=3 2+3=5 3+4=7 4+5=9 5+6=11 

Overloading operator + in c++ to add two arrays

Let's consider your operator implementation step by step.

For starters the right hand operand is not changed within the operator. So the function should be declared at least like

Array& operator+( const Array& a );

The function crates a new object of the type Array within its body.

Array res;

So as the object is a local variable of the function you may not return a reference to it. It means that the operator should be declared like

Array operator+( const Array& a );

or

const Array operator+( const Array& a );

This code snippet

if (this->m >= a.m) {
res.setM(this->m);
for (int i=0; i<this->m; i++){
res.data[i] = this->data[i] + a.data[i];
}
}

can invoke undefined behavior when a.m is less than this->m.

As the member function does not change the left operand then the function should be a constant member function.

const Array operator +( const Array& a ) const;

Usually such operators are declared as separate friend functions of class.

friend const Array operator+( const Array &a, const Array &b );

Taking into account the algorithm that you are using within the operator it can be defined (outside the class definition. Or if you want to define it within the class definition then you need to use the specifier friend) the following way

const Array operator+( const Array &a, const Array &b )
{
int m = std::min( a.m, b.m );
Array res( m );

for ( int i = 0; i < m; i++ )
{
res.data[i] = a.data[i] + b.data[i];
}

return res;
}

Pay attention to that the function setM can produce memory leaks because it does not delete early allocated memory for an object of the type Array

void Array::setM(int m){
this->m = m;
this->data = new int[this->m];
}

That is the function is unsafe.

Also bear in mind that the constructor with parameter should be declared with the function specifier explicit. Otherwise you can encounter unexpected conversions of an integer to the type Array.

As you are dynamically allocating arrays you need to write explicitly at least the destructor, copy constructor and copy assignment operator.

C++, operator [], and tracking a change

You could set the flag to 'changed' inside your existing operator[] method, and add a second version with const returning an int (= not as a reference):

int operator [](int i) const {return mData[i];}

The compiler would pick the right one - modifying or not, as needed!



Related Topics



Leave a reply



Submit