I have already brought my code to working form, but there are several questions left. So the code (the idea is that in the array it would be possible to store both some data and a subarray of the data):
#include <iostream>
using namespace std;
template <typename T>
class Array {
public:
Array () {;}
Array(T const &a) {*this = a;}
Array(Array const &a) {Resize(SZ+1); M[SZ-1] = a;}
T& operator [] (int i) const {return M[i % SZ];}
operator T& () {return M[IX % SZ];}
Array& operator = (T const &a) {
Resize(SZ+1);
M[SZ-1] = a;
return *this;
}
Array& operator = (Array const &a)
{
Resize(a.SZ);
if (M != nullptr) {
for (int i = 0; i < SZ; i++) M[i] = a[i];
}
return *this;
}
Array<T>& operator = (Array * const p)
{
Resize(SZ+1);
M[SZ-1] = p;
return *this;
}
friend ostream& operator<<(ostream& os, const Array<T> &a)
{
for (int i = 0; i < a.SZ; i++) os << a.M[i] << ",";
return os;
}
protected:
T *M = nullptr;
int SZ = 0, IX = 0;
private:
Array& Resize(int s)
{
if (s != 0) {
int S = SZ;
if (S > s) S = s;
T *A = new T[s];
if (A != nullptr) {
int i;
for (i = 0; i < S; i++) A[i] = M[i];
delete M;
M = A;
SZ = s;
}
} else {
delete M;
SZ = 0;
}
return *this;
}
};
struct S {
enum class TP {
INT,
ARR
} type;
int data = 0;
Array<S> *ptr = nullptr;
S() {;}
S(int d) {type = TP::INT; data = d;}
S(float d) {type = TP::INT; data = d;}
S(Array<S>* p) {type = TP::INT; ptr = p;}
int operator = (int d) {type = TP::INT; return data = d;}
int operator = (float d) {type = TP::INT; return data = d;}
Array<S>* operator = (Array<S>* p) {type = TP::ARR; return ptr = p;}
friend ostream& operator << (ostream& os, const S &s)
{
switch (s.type) {
case TP::INT:
os << s.data;
break;
case TP::ARR:
os << "[" << *s.ptr << "]";
break;
default:
os << "ERROR";
}
return os;
}
};
int main()
{
Array<S> arr0, *arr1 = new Array<S>;
arr0 = 10;
arr0 = 20;
arr0 = 30;
*arr1 = 40;
*arr1 = 50;
*arr1 = 60;
arr0 = arr1;
cout << arr0;
return 0;
}
now i will comment out the lines
S(int d) {type = TP::INT; data = d;}
S(float d) {type = TP::INT; data = d;}
S(Array<S>* p) {type = TP::INT; ptr = p;}
int operator = (int d) {type = TP::INT; return data = d;}
int operator = (float d) {type = TP::INT; return data = d;}
Array<S>* operator = (Array<S>* p) {type = TP::ARR; return ptr = p;}
and I will uncomment them sequentially. At first I get error messages:
main.cpp:34: error: no viable overloaded '=' main.cpp:34: error: no match for 'operator=' (operand types are 'S' and 'Array* const')
M[SZ-1] = p;
~~~~~~~~^~~
So far, everything is clear. if I uncomment the line
S(float d) {type = TP::INT; data = d;}
Then I will receive the same message. But, if I uncomment the line
S(int d) {type = TP::INT; data = d;}
I get error message:
main.cpp:34: error: invalid conversion from 'Array<S>*' to 'int' [-fpermissive]
M[SZ-1] = p;
~~~~~~~~^~~
Why doesn't the compiler try to cast Array to float, but tryes to int ?
Then, I can remove line:
int operator = (int d) {cout << "=int" << endl;type = TP::INT; return data = d;}
and it will be ok. Then I thought than the constructor and the operator "=" are interchangeable and I could delete the operator "=" in the Array class:
Array& operator = (T const &a) {
Resize(SZ+1);
M[SZ-1] = a;
return *this;
}
But I can't, it leads to an error! But I can remove the Array class constructor:
Array(Array const &a) {Resize(SZ+1); M[SZ-1] = a;}
and this will work. The other way round, if I remove the structure constructor but leave the assignment operator, then there is an error.
I have some guesses, but I'm confused. Can someone explain clearly why this behavior?
Sorry if I didn't explain it clearly.