I have written a (dynamic) TemplateArray
class, for purposes to be included as a baseline for a library I am working on, and I would like feedback on any of the following:
- How the code can be improved (even if it's just your subjective opinion)?
- How the code can be made more efficient?
- How the functions of the class can be made more intuitive and user-friendly (does it operate like how you anticipate it to)?
namespace TL
{
template<typename TemplateItem>
class TemplateArray
{
protected:
TemplateItem *Array;
SIZE_TYPE Size;
void Clear(){Array = NULL; Size = 0;}
public:
const bool IsEmpty() const { return ((Array == NULL) && (Size == 0)); }
const bool IsValid() const { return ((Array != NULL) && (Size != 0)); }
const bool operator!() const {return IsEmpty();}
operator const bool () const {return IsValid();}
const SIZE_TYPE GetSize() const {return Size;}
const bool SetSize(const SIZE_TYPE S)
{
ERRORCLASSFUNCTION(TemplateArray,SetSize,S < 1,RETURN_BOOL)
if(!IsEmpty())
{
Close();
}
ERRORCLASSFUNCTION(TemplateArray,SetSize,!CREATEB(Array,S),RETURN_BOOL)
Size = S;
return true;
}
const bool CopyArray(const TemplateItem Arr[], const SIZE_TYPE S)
{
ERRORCLASSFUNCTION(TemplateArray,CopyArray,S < 1,RETURN_BOOL);
ERRORCLASSFUNCTION(TemplateArray,CopyArray,S > Size,RETURN_BOOL);
SIZE_TYPE Temp = 0;
while(Temp < S)
{
Array[Temp] = Arr[Temp];
Temp++;
}
return true;
}
const bool SetArray(const TemplateItem Arr[], const SIZE_TYPE S)
{
ERRORCLASSFUNCTION(TemplateArray,SetArray,S < 1,RETURN_BOOL)
ERRORCLASSFUNCTION(TemplateArray,SetArray,!SetSize(S),RETURN_BOOL)
SIZE_TYPE Temp = 0;
while(Temp < S)
{
Array[Temp] = Arr[Temp];
Temp++;
}
return true;
}
const bool SetArray(const TemplateArray &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,SetArray,!ItemCopy,RETURN_BOOL)
ERRORCLASSFUNCTION(TemplateArray,SetArray,!SetArray(ItemCopy.Array,ItemCopy.Size),RETURN_BOOL)
return true;
}
const bool SetArray(const std::vector<TemplateItem> &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,SetArray,ItemCopy.empty(),RETURN_BOOL)
ERRORCLASSFUNCTION(TemplateArray,SetArray,!SetArray(&ItemCopy[0],ItemCopy.size()),RETURN_BOOL)
return true;
}
TemplateItem * const GetArray() { return Array; }
const TemplateItem * const GetArray() const { return Array; }
void TransferFrom(TemplateArray &ItemCopy)
{
Close();
Array = ItemCopy.Array;
Size = ItemCopy.Size;
ItemCopy.Array = NULL;
ItemCopy.Size = 0;
}
const bool Reverse()
{
ERRORCLASSFUNCTION(TemplateArray,Reverse,!IsValid(),RETURN_BOOL)
TemplateArray<TemplateItem> Temp;
ERRORCLASSFUNCTION(TemplateArray,Reverse,!Temp.SetSize(Size),RETURN_BOOL)
TemplateItem *C_Ptr = Array+(Size-1), *C_Ptr_2 = Temp.GetArray();
while(C_Ptr != Array)
{
*C_Ptr_2 = *C_Ptr;
C_Ptr--; C_Ptr_2++;
}
*C_Ptr_2 = *C_Ptr;
TransferFrom(Temp);
return true;
}
const bool Compare(const TemplateItem Arr[], const SIZE_TYPE S)
{
if(!IsValid())
{
return false;
}
ERRORCLASSFUNCTION(TemplateArray,Compare,S < 1,RETURN_BOOL)
SIZE_TYPE Temp = 0;
while(Temp < S)
{
if(Array[Temp] != Arr[Temp]){return false;}
Temp++;
}
return true;
}
const bool Compare(const TemplateArray &ItemCopy)
{
if(Size != ItemCopy.Size)
{
return false;
}
if(IsEmpty())
{
return true;
}
return Compare(ItemCopy.Array,ItemCopy.Size);
}
const bool Compare(const std::vector<TemplateItem> &ItemCopy)
{
if(ItemCopy.size() != Size)
{
return false;
}
if(ItemCopy.empty())
{
return true;
}
return Compare(&ItemCopy[0],ItemCopy.size());
}
const bool Append(const TemplateItem Data[], const SIZE_TYPE S)
{
ERRORCLASSFUNCTION(TemplateArray,Append,Data == NULL,RETURN_BOOL)
ERRORCLASSFUNCTION(TemplateArray,Append,S < 1,RETURN_BOOL)
TemplateArray<TemplateItem> Temp;
ERRORCLASSFUNCTION(TemplateArray,Append,!Temp.SetSize(Size+S),RETURN_BOOL)
SIZE_TYPE Temp2 = 0;
while(Temp2 < Size)
{
Temp.Array[Temp2] = Array[Temp2];
Temp2++;
}
Temp2 = 0;
while(Temp2 < S)
{
Temp.Array[Temp2+Size] = Data[Temp2];
Temp2++;
}
TransferFrom(Temp);
return true;
}
//Tested
const bool Append(const TemplateArray &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,Append,!ItemCopy.IsValid(),RETURN_BOOL)
return Append(ItemCopy.GetArray(),ItemCopy.GetSize());
}
const bool Append(const std::vector<TemplateItem> &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,Append,ItemCopy.empty(),RETURN_BOOL)
ERRORCLASSFUNCTION(TemplateArray,Append,!Append(&ItemCopy[0],ItemCopy.size()),RETURN_BOOL)
return true;
}
const bool Append(const TemplateItem &ItemCopy)
{
return Append(&ItemCopy,1);
}
const bool Remove(const TemplateItem Data[], const SIZE_TYPE S)
{
ERRORCLASSFUNCTION(TemplateArray,Append,Data == NULL,RETURN_BOOL)
ERRORCLASSFUNCTION(TemplateArray,Remove,S < 1,RETURN_BOOL)
if(!IsValid()){return false;}
if(S > Size){return false;}
SIZE_TYPE Temp = 0, Temp2 = 0;
do
{
Temp2 = 0;
while(Temp < Size)
{
if(Array[Temp] == Data[Temp2])
{
break;
}
Temp++;
}
while(Temp < Size)
{
if(Array[Temp] != Data[Temp2])
{
break;
}
Temp++; Temp2++;
if(Temp2 == S)
{
break;
}
}
if(Temp2 == S)
{
TemplateArray<TemplateItem> DataTemp;
ERRORCLASSFUNCTION(TemplateArray,operator-=,!DataTemp.SetSize(Size-S),RETURN_BOOL)
Temp2 = Temp - S;
Temp = 0;
while(Temp < Temp2)
{
DataTemp.Array[Temp] = Array[Temp];
Temp++;
}
Temp2 += S;
while(Temp2 < Size)
{
DataTemp.Array[Temp] = Array[Temp2];
Temp++; Temp2++;
}
TransferFrom(DataTemp);
return *this;
}
}while(Temp < Size);
return *this;
}
const bool Remove(const std::vector<TemplateArray> &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,Remove,ItemCopy.empty(),RETURN_BOOL)
ERRORCLASSFUNCTION(TemplateArray,Remove,!Remove(&ItemCopy[0],ItemCopy.size()),RETURN_BOOL)
return true;
}
const bool Remove(const TemplateArray &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,Remove,!IsValid(),RETURN_BOOL)
ERRORCLASSFUNCTION(TemplateArray,Remove,!Remove(ItemCopy.Array,ItemCopy.Size),RETURN_BOOL)
return *this;
}
const bool Remove(const TemplateItem &ItemCopy)
{
return Remove(&ItemCopy,1);
}
void Reset()
{
if(Array != NULL)
{
DELETEB(Array);
}
Open();
}
void Open(){ Clear(); }
void Close()
{
if(Array != NULL)
{
DELETEB(Array);
}
Clear();
}
//Tested
TemplateArray(){Open();}
~TemplateArray(){Close();}
//Tested
TemplateArray(const TemplateItem Data[], const SIZE_TYPE S)
{
Open();
ERRORCLASSFUNCTION(TemplateArray,TemplateArray,!SetArray(Data,S),)
}
//Tested
TemplateArray(const TemplateArray &ItemCopy)
{
Open();
ERRORCLASSFUNCTION(TemplateArray,TemplateArray,!SetArray(ItemCopy),)
}
TemplateArray(const std::vector<TemplateItem> &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,TemplateArray,!SetArray(ItemCopy),RETURN_VOID)
}
operator const SIZE_TYPE () const {return Size;}
operator const std::vector<TemplateItem> () const
{
std::vector<TemplateItem> Temp;
if(!IsValid())
{
return Temp;
}
try
{
Temp.resize(Size);
}
catch(...)
{
std::vector<TemplateItem> Temp2;
ERRORCLASSFUNCTION(TemplateArray,std::vector,true,return Temp2;)
}
SIZE_TYPE Temp2 = 0;
while(Temp2 < Size)
{
Temp[Temp2] = Array[Temp2];
Temp2++;
}
return Temp;
}
const bool operator!=(const TemplateArray &ItemCopy){return !((*this) == ItemCopy);}
const bool operator==(const TemplateArray &ItemCopy)
{
return Compare(ItemCopy);
}
const bool operator==(const std::vector<TemplateItem> &ItemCopy)
{
return Compare(ItemCopy);
}
TemplateArray &operator+=(const TemplateItem &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,operator+=,!Append(ItemCopy),RETURN_THIS)
return *this;
}
//Tested
TemplateArray &operator+=(const TemplateArray &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,operator+=,!Append(ItemCopy),RETURN_THIS)
return *this;
}
//Tested
TemplateArray &operator+=(const std::vector<TemplateItem> &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,operator+=,!Append(ItemCopy),RETURN_THIS)
return *this;
}
TemplateArray &operator-=(const TemplateItem &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,operator-=,!Remove(ItemCopy),RETURN_THIS)
return *this;
}
TemplateArray &operator-=(const std::vector<TemplateItem> &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,operator-=,!Remove(ItemCopy),RETURN_THIS)
return *this;
}
TemplateArray &operator-=(const TemplateArray &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,operator-=,!Remove(ItemCopy),RETURN_THIS)
return *this;
}
TemplateArray &operator=(const std::vector<TemplateItem> &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,operator=,!SetArray(ItemCopy),RETURN_THIS)
return *this;
}
TemplateArray &operator=(const TemplateArray &ItemCopy)
{
ERRORCLASSFUNCTION(TemplateArray,operator=,!SetArray(ItemCopy),RETURN_THIS)
return *this;
}
TemplateItem &operator[](const SIZE_TYPE S){ return Array[S]; }
const TemplateItem &operator[](const SIZE_TYPE S) const { return Array[S]; }
};
}
A working example you can paste directly into your compiler is also available here.
The class has to support the following:
To minimise bug tracing times:
- Vocal error reporting.
- Traceable error reporting.
- Fail-safes (quit on first problem attitude).
- Functions that primarily return bool where possible.
For compatibility with other classes:
- Return and accept a standard data-type (in this case, std::vector).
The class should support the following requirements:
- User-friendliness. User should not have to think when using the class.
- Compatibility with future, potentially unknown classes and sub-classes.
Please ignore the macro, printf usage and the fact the functions are inside the class. It's just my personal preference. Please avoid suggesting using std::string
/std::vector
(this is a really old cliche now), as standard classes are generic and don't offer the specific functionality a custom built class can (i.e. bool returning, error-reporting/tracing functions), although it does offer compatibility with such classes.
begin
,end
,rbegin
,rend
, etc., means your class is essentially unusable. IMO, your class also has an almost incredibly bloated external interface. OTOH, your requirement at the end seem (to me) to be saying: "Please tell me how to improve this without fixing any of its problems." \$\endgroup\$