I like to think I have grasped most aspects of object oriented programming but C++ has yet again presented me with an unexpected result. While creating a static array class in C++ (much like std::array), I added the + operator and it gave me a very strange compiler error.
Has anyone encountered this situation before?
#pragma once
#ifdef NDEBUG
#define __ESL_Array_AssertCorrectInitSize(array, init)
#else
#define __ESL_Array_AssertCorrectInitSize(array, init) if (init.size() != array->Size()) throw ESL::ArrayInitializationException("std::initializer_list size is different than static size");
#endif // NDEBUG
#include<cstdint>
#include<utility>
#include<stdexcept>
namespace ESL
{
class ArrayInitializationException : public std::runtime_error
{
public:
ArrayInitializationException(const std::string &msg): std::runtime_error(msg) {}
};
template <typename T, uint32_t S>
class Array
{
public:
Array(): m_data() {}
Array(const T (&arr)[S]):
m_data()
{
const T *src_itr = arr;
T *dst_itr = m_data;
for (uint32_t i = 0; i < S; ++i)
*(dst_itr++) = *(src_itr++);
}
Array(std::initializer_list<T> list):
m_data()
{
__ESL_Array_AssertCorrectInitSize(this, list)
const T *src_itr = list.begin();
T *dst_src = m_data;
for (uint32_t i = 0; i < S; ++i)
{
*(dst_src++) = *(src_itr++);
}
}
Array(const Array &a):
m_data()
{
const T *src_itr = a.m_data;
T *dst_itr = m_data;
for (uint32_t i = 0; i < S; ++i)
*(dst_itr++) = *(src_itr++);
}
Array(Array &&a):
m_data()
{
T *src_itr = a.m_data;
T *dst_itr = m_data;
for (uint32_t i = 0; i < S; ++i)
*(dst_itr++) = std::forward<T>(*(src_itr++));
}
Array &operator=(const Array &a)
{
const T *src_itr = a.m_data;
T *dst_itr = m_data;
for (uint32_t i = 0; i < S; ++i)
*(dst_itr++) = *(src_itr++);
return *this;
}
Array &operator=(Array &&a)
{
const T *src_itr = a.m_data;
T *dst_itr = m_data;
for (uint32_t i = 0; i < S; ++i)
*(dst_itr++) = std::forward<T>(*(src_itr++));
return *this;
}
constexpr uint32_t Size() const { return S; }
const T &operator[](uint32_t index) const { return m_data[index]; }
T &operator[](uint32_t index) { return m_data[index]; }
const T *begin() const { return m_data; }
T *begin() { return m_data; }
const T *end() const { return m_data + S; }
T *end() { return m_data + S; }
bool operator==(const Array &a) const
{
const T *itr1 = m_data;
const T *itr2 = a.m_data;
for (uint32_t i = 0; i < S; ++i)
{
if (*(itr1++) != *(itr2++)) return false;
}
return true;
}
bool operator!=(const Array &a) const
{
const T *itr1 = m_data;
const T *itr2 = a.m_data;
for (uint32_t i = 0; i < S; ++i)
{
if (*(itr1++) != *(itr2++)) return true;
}
return false;
}
template <uint32_t S2>
Array<T, S + S2> operator+(const Array<T, S2> &a) const
{
Array<T, S + S2> res;
const T *src_itr = m_data;
T *dst_itr = res.m_data;
for (uint32_t i = 0; i < S; ++i)
*(dst_itr++) = *(src_itr++);
src_itr = a.m_data;
for (uint32_t i = 0; i < S2; ++i)
*(dst_itr++) = *(src_itr++);
return res;
}
private:
T m_data[S];
};
}
If you need any more code, I'd be willing to post the entire file. I appreciate any input! Thanks!
EDIT: Just realized I forgot the compiler output:
In instantiation of ‘ESL::Array<T, (S + S2)> ESL::Array<T, S>::operator+(const ESL::Array<T, S2>&) const [with unsigned int S2 = 2; T = double; unsigned int S = 3]’:
[build] /home/joshlengel/Dev/C++/ESL/Main.cpp:10:20: required from here
[build] /home/joshlengel/Dev/C++/ESL/ESL/include/collection/Array.h:135:30: error: ‘double ESL::Array<double, 5>::m_data [5]’ is private within this context
[build] 135 | T *dst_itr = res.m_data;
[build] | ~~~~^~~~~~
[build] /home/joshlengel/Dev/C++/ESL/ESL/include/collection/Array.h:149:11: note: declared private here
[build] 149 | T m_data[S];