Infinite dimensional array C + + template class implementation, source sharing

Posted by mmcb on Thu, 30 Jan 2020 16:58:58 +0100

This is an infinite dimensional array template of any object, which can realize multiple functions and do many things. The explicit dynamic construction or analysis of the generic instantiated object has a micro memory recycling method that can be used to efficiently multi-dimensional operations, such as neural network, proof calculation, and share the code.
The macro CLArrayObj is used to define the array of class type, and CLArrayV is used to define the array of basic value type;
Let's see the app first!

class B {//A demonstration class B defined first, standby
public:
	double a = RAND_F_0_1();//Generate 0-1 random number
	double b = RAND_F_0_1();
	int* p;
	class _A {
		_A() { RAND_SET_SEED(); }
	};
	static _A seed;
	B() { 
		p = new int[15]; 
	}
	B(const B& tag) {//Pay attention to the influence of assignment construction on dynamic pointer
		p = new int[15];
		*this = tag;
	}
	B& operator=(const B& tag) {//Pay attention to the influence of assignment function on dynamic pointer
		a = tag.a;
		b = tag.b;
		return *this;
	}
	~B() { 
		delete[] p; 
	}
	B& operator=(VT v) { return a = b = v, *this; }
};

//Instantiate template class with macro reality
CLArrayObj(B, ArrObj);//B is the previously defined class, instantiated to the multidimensional array class named ArrObj, the same below
//CLArrayV(VT, ArrV);
CLArrayV(double, ArrB);//Instantiate an array class of type double
CLArrayV(double, CDouble);
CLArrayV(int, CInt);
CLArrayV(long long, CLonglong);

void main() {
	ArrObj obj1 ;
	//Define an array of any dimension. If the number is less than 0, it will be counted as 0. Without defining the object size and dimension in advance, you can specify it at will. The subscript will be automatically rounded
	obj1[-1][1][5][3][2][12][2.5][5][6][1][9][8][66][-25][66][5][0][77] = 3.1415926;
	CDouble cd1;
	CLonglong cd2 = (int)1;
	CInt cd3 = 1.5;
	cd1[1] = 3;
	cd1[2] = 2;
	cd1[3] = cd1[1] * cd2[2];
	cd1++;
	++cd1;
	cd1--;
	++cd1--;
	int a11 = 1 + ++cd2-- + 2.5 - cd1 + 50;
	cd1 = 1 + cd2 + 2.5 - cd1 + 50;
	double ii2 = 0;
	ii2 = cd1 + 2;
	ii2 = cd1 - 2;
	ii2 = cd1 * 2;
	ii2 = cd1 / 2;
	ii2 = cd1 % 2;
	ii2 = 2 + cd1;
	ii2 = 2 - cd1;
	ii2 = 2 * cd1;
	ii2 = 2 / cd1;
	ii2 = 2 % (int)cd1;
	CDouble* p = (CDouble*)malloc(sizeof(CDouble));
	p->CDouble::CLArrayTemplateV();
	*p = cd1;
	p->CDouble::~CLArrayTemplateV();
	free(p);
	//return;
	ArrB* a = (new ArrB);
	//Accept array assignment
	*a ={ 1, 1.1,222,222,222,222,222,222,222,222};
	(*a).clear();
	ArrB b = { 3 };
	*a = b;
	*a = { 4,44,444,555,666,777,888,999};
	*a = 1;
	*a = 1.1;
	delete a;
	//return;
	RAND_SEED();
	int ii,aa,jj,bb;
	//Infinite dimension test
	for (size_t kkk = 0; kkk < 10; kkk++)
	{
		ArrObj t1;
		t1[1] = 1;
		t1.clear();

		CLTick tk;
		for (int i = 0; i < 9; ++i)
		{
			int a = RAND_I_Ai_B(0, 100);
			aa = a;
			ii = i;
			auto v = &t1;
			for (int j = 0; j < a; ++j)
			{
				jj = j;
				int b = RAND_I_Ai_B(10, 200);
				bb = b;
				v = (ArrV*) & (v->at(b));
			}
			*v = (VT)RAND_F_A_B(-99, 0);
		}
		t1.clear();
		for (int i = 0; i < 9000; ++i)
		{
			int a = RAND_I_Ai_B(0, 100);
			aa = a;
			ii = i;
			auto v = &t1;
			for (int j = 0; j < a; ++j)
			{
				jj = j;
				int b = RAND_I_Ai_B(5, 105);
				bb = b;
				v = (ArrV*) & (v->at(b));
			}
			*v = RAND_F_A_B(1, 5);
		}
		printf("\n\n Time consuming after cleaning %.5f s , mem a= %lld b ,u= %lld b ,s= %lld b , \n\n", tk.getSpendTime(0), t1.getMemerySize(), t1.getUsedMemerySize(), t1.getSpareMemerySize());
		t1.clear();
		printf("\n\n Time consuming after cleaning %.5f s , mem a= %lld b ,u= %lld b ,s= %lld b , \n\n", tk.getSpendTime(1), t1.getMemerySize(), t1.getUsedMemerySize(), t1.getSpareMemerySize());
		t1.releaseMemery();
	}
	return;
}

Here is the code implementation
CLArrayTemplate.h

#pragma once
#ifndef __CL_ARRAYTEMPLATE_H__
#define __CL_ARRAYTEMPLATE_H__

#include "windows.h"
#include <vector>
#include <stack>

#ifndef __CL_VALUEPACK__
#define __CL_VALUEPACK__
//An object-oriented encapsulation class template for basic numeric types
template<class T>class CLValuePacking {
public:
	using obj = CLValuePacking<T>;
	using pObj = CLValuePacking<T>*;
	using pObjc = const CLValuePacking<T>*;
	using ref = CLValuePacking<T> &;
	using refc = const CLValuePacking<T> &;
	T v;
	//Do not initialize value object
	inline CLValuePacking() {
#ifdef _DEBUG
		v = 0;
#endif
	}
	inline CLValuePacking(T _v) {
		v = _v;
	}
	inline CLValuePacking(refc tag) {
		v = tag;
	}
	inline ~CLValuePacking() {
#ifdef _DEBUG
		memset(&v, 0xFF, sizeof(T));
#endif
	}
	inline size_t memSize() { return sizeof(T); }
	inline operator T() const { return v; }
	inline operator T& () { return v; }
	inline T& operator=(const T& _v) { return v = _v, v; }
	template<class otherT>inline T& operator=(const otherT& _v) { return v = _v, v; }
	//operation
	inline T& operator--() {
		return --v, v;
	}
	inline T& operator++() {
		return ++v, v;
	}
	inline obj operator--(int) {
		obj a = *this;
		--v;
		return a;
	}
	inline obj operator++(int) {
		obj a = *this;
		++v;
		return a;
	}
	template<class otherT>
	inline T& operator+=(const otherT& _v) {
		return v += _v, v;
	}
	template<class otherT>
	inline T& operator-=(const otherT& _v) {
		return v -= _v, v;
	}
	template<class otherT>
	inline T& operator*=(const otherT& _v) {
		return v *= _v, v;
	}
	template<class otherT>
	inline T& operator/=(const otherT& _v) {
		return v /= _v, v;
	}
	template<class otherT>
	inline T operator+(const otherT& _v) {
		return v + _v;
	}
	template<class otherT>
	inline T operator-(const otherT& _v) {
		return v - _v;
	}
	template<class otherT>
	inline T operator*(const otherT& _v) {
		return v * _v;
	}
	template<class otherT>
	inline T operator/(const otherT& _v) {
		return v / _v;
	}
	template<class otherT>
	inline bool operator==(const otherT& _v) {
		return v == _v;
	}
	inline int operator%(int _v) {
		return (((int)(v)) % _v);
	}
};

template<class T, class otherT, class Ret>
Ret operator+(const otherT& v, const CLValuePacking<T>& t) {
	return v + T(t);
}

template<class T, class otherT, class Ret>
Ret operator-(const otherT& v, const CLValuePacking<T>& t) {
	return v - T(t);
}

template<class T, class otherT, class Ret>
Ret operator*(const otherT& v, const CLValuePacking<T>& t) {
	return v * T(t);
}

template<class T, class otherT, class Ret>
Ret operator/(const otherT& v, const CLValuePacking<T>& t) {
	return v / T(t);
}

//Instantiate basic numerical packaging class template class
#define CLVPack(valueClass,definedClassName)\
template class CLValuePacking<valueClass>;\
typedef CLValuePacking<valueClass> definedClassName;\
typedef definedClassName& definedClassName##R;\
typedef const definedClassName& definedClassName##RC;\
typedef definedClassName* P##definedClassName;\
typedef const definedClassName* PC##definedClassName;

#endif

//Object type multidimensional safe array class template class (Note: the object class should properly handle the impact of object assignment or copy construction on internal dynamic pointer variables to avoid multiple releases)
template <class T>
class CLArrayTemplate {
public:
	using obj = CLArrayTemplate<T>;
	using pObj = CLArrayTemplate<T>*;
	using pObjc = const CLArrayTemplate<T>*;
	using ref = CLArrayTemplate<T> &;
	using refc = const CLArrayTemplate<T> &;
	using vlist = std::initializer_list<T>;
	using data = std::vector<CLArrayTemplate<T>*>;
	using pdata = std::vector<CLArrayTemplate<T>*>*;
protected:
	class VPackage {//Packaging class
	public:
		T* m_value;	//Node value object
		inline VPackage()
			:m_value(new T)
		{
		}
		inline ~VPackage() {
			if (m_value != 0) {
				delete m_value;
				m_value = 0;
			}
		}
	};
	VPackage m_vPack;
	pdata m_sublst;//Child object table of node
	bool m_createByLst;
	std::stack<pObj> objLibrary;//mem pool
	void _release() {
		//Free memory pool
		_releaseLib();
		//Release the table itself, and its children
		if (m_sublst != NULL) {
			for (size_t i = 0, si = m_sublst->size(); i < si; i++) {
				auto pc = m_sublst->at(i);
				if (pc != 0) {
					_deleteOne(pc);
				}
			}
			delete m_sublst;
			m_sublst = NULL;
		}
	};
	void _releaseLib() {
		while (!objLibrary.empty()) //Release Library
		{
			pObj pc = objLibrary.top();
			objLibrary.pop();
			_deleteOne(pc);
		}
	};
	virtual pObj _newObj() {
		pObj pnew;
		if (!objLibrary.empty()) {
			pnew = objLibrary.top();
			objLibrary.pop();
			pnew->m_vPack.VPackage::VPackage();
			pnew->m_createByLst = false;
			return pnew;
		}
		else {
			pnew = (pObj)malloc(sizeof(obj));
			pnew->CLArrayTemplate::CLArrayTemplate();
			return pnew;
		}
	}
	virtual void _storeOne(void* p) {
		((pObj)p)->clear();//Cleaning up Zi Lian
		((pObj)p)->m_vPack.VPackage::~VPackage();//Destructor object
		objLibrary.push((pObj)p);
	}
	virtual void _deleteOne(void* p) {
		((pObj)p)->CLArrayTemplate::~CLArrayTemplate();
		free(p);
	}
	inline size_t _getObjSizeof() const {
		return  _getClassSizeof() + (m_vPack.m_value ? sizeof(T) : 0);
	}
	inline virtual size_t _getClassSizeof() const {
		return sizeof(obj);
	}
	inline void* _newData() { return new data; }
	void _copyList(const pdata& tag_sublst) {
		size_t lsi = (tag_sublst != 0 ? tag_sublst->size() : 0);
		if (lsi > 0) {
			if (!m_sublst)
				m_sublst = (pdata)_newData();
			size_t si = m_sublst->size();
			if (si < lsi) {
				m_sublst->resize(lsi, (pObj)0);
			}
			for (size_t i = 0; i < lsi; i++)
			{
				auto& p = m_sublst->at(i);
				auto& pt = tag_sublst->at(i);
				if (pt != 0) {
					if (p == 0)
						p = _newObj();
					*p->m_vPack.m_value = *pt->m_vPack.m_value;
				}
			}
		}
	}
	void _clear() {
		if (m_sublst != NULL) {
			for (size_t i = 0, si = m_sublst->size(); i < si; i++) {
				auto& pc = m_sublst->at(i);
				if (pc != 0) {
					_storeOne(pc);
				}
			}
			m_sublst->clear();
		}
	};
public:
	//Gets the total memory usage of the object, including the used memory and the spare memory cached in the memory pool
	size_t getMemerySize() const {
		size_t sii = getUsedMemerySize();
		sii += getSpareMemerySize();
		return sii;
	}
	//Free all memory occupied by the structure, including the used memory and the spare memory cached in the memory pool
	void releaseMemery() {
		_release();
	}
	//Gets the amount of spare memory (excluding memory in use) that has been reserved in the memory pool
	size_t getSpareMemerySize() const {
		size_t sii = 0;
		std::stack<pObj> stk2 = objLibrary;
		while (!stk2.empty())
		{
			sii += (stk2.top()->getMemerySize());
			stk2.pop();
		}
		return sii;
	}
	//Free the amount of spare memory that has been reserved in the memory pool (excluding the memory in use)
	void releaseSpareMemery() {
		_releaseLib();
	}
	//Gets the amount of memory used by the object (not including the spare memory in the memory pool)
	size_t getUsedMemerySize()const {
		size_t sii = _getObjSizeof();
		if (m_sublst != NULL) {
			sii += (m_sublst->capacity() * sizeof(pObj));
			for (size_t i = 0, si = m_sublst->size(); i < si; ++i)
			{
				pObj p = (m_sublst->at(i));
				if (p)
					sii += p->getMemerySize();
			}
		}
		return sii;
	}
	inline CLArrayTemplate()
		:m_sublst(0), m_createByLst(false) {
	}
	template<class otherT>
	inline CLArrayTemplate(otherT v)
		: m_sublst(0), m_createByLst(false) {
		*m_vPack.m_value = v;
	}
	inline CLArrayTemplate(refc tag)
		: m_sublst(0), m_createByLst(false) {
		*this = tag;
	}
	inline CLArrayTemplate(const vlist& _Ilist)
		: m_sublst(0), m_createByLst(true) {
		*this = _Ilist;
	}
	//Destructors free memory for all objects and child nodes
	inline virtual ~CLArrayTemplate() {
		_release();
	}
	inline ref operator =(T v) {
		return (m_createByLst = false, *m_vPack.m_value = v), * this;
	}
	ref operator =(refc tag) {
		if (!tag.m_createByLst)
			m_createByLst = false, * m_vPack.m_value = (*tag.m_vPack.m_value);
		_copyList(tag.m_sublst);
		return *this;
	}
	ref operator =(const vlist& _Ilist) {
		size_t lsi = _Ilist.size();
		if (lsi > 0) {
			if (!m_sublst)
				m_sublst = (pdata)_newData();
			auto si = m_sublst->size();
			if (si < lsi) {
				m_sublst->resize(lsi, (pObj)0);
			}
			for (size_t i = 0; i < lsi; i++)
			{
				auto& p = m_sublst->at(i);
				if (p == 0)
					p = _newObj();
				*p->m_vPack.m_value = *(_Ilist.begin() + i);
			}
		}
		return *this;
	}
	//i instance objects are generated directly to the queue for use by subsequent at or [] operations. Before a specific cell is called,
	//The function will prepare the object (dynamically apply for memory), and the function will not change the existing object;
	void generate(int i) {
		size_t _i = (i < 0 ? 0 : i);
		if (!m_sublst)m_sublst = new data;
		if (m_sublst->size() >= _i) {
			for (size_t i = 0; i < _i; i++)
			{
				auto& pc = m_sublst->at(i);
				if (pc == 0)
					pc = _newObj();
			}
			return;
		}
		m_sublst->resize(_i, (pObj)0);
		for (size_t i = 0; i < _i; i++)
		{
			auto& pc = m_sublst->at(i);
			if (pc == 0)
				pc = _newObj();
		}
		return;
	}
	//The redundant linked list objects will be deleted, the specified number will be reserved, and the existing objects will not be initialized
	void resize(int i) {
		size_t _i = (i < 0 ? 0 : i);
		if (!m_sublst)
			m_sublst = new data;
		size_t si = m_sublst->size();
		if (si > _i) {
			for (size_t i = si; i > _i; --i)
			{
				auto& pc = m_sublst->at(i - 1);
				if (pc != 0) {
					_storeOne(pc);
					pc = 0;
				}
			}
			m_sublst->resize(_i);
			return;
		}
		else if (si < _i)
			m_sublst->resize(_i, 0);
		return;
	}

	//Returns a reference to an internal value 
	inline T& operator()() { return *m_vPack.m_value; }

	//Clear the child connection and keep the child connection object, which is different from reset();
	inline void clear() {
		_clear();
	}
	//It can make the object itself be used in mathematical operations like a calculation number, constant value type conversion
	inline operator T() const {
		return *m_vPack.m_value;
	}
	//It can make the object itself be used in mathematical operations like a calculation number, variable type conversion
	inline operator T& () {
		return *m_vPack.m_value;
	}
	//Get the ith object of the chain. If i < 0, it will automatically take 0. If i > the maximum number of chains, it will automatically expand the capacity. Therefore, i will never generate cross-border errors
	ref at(size_t _i) {
		if (!m_sublst)
			m_sublst = new data;
		if (m_sublst->size() < _i + 1) {
			m_sublst->resize(_i + 1, (pObj)0);
			auto& pc = m_sublst->at(_i);
			pc = _newObj();
			return *pc;
		}
		auto& pc = m_sublst->at(_i);
		if (pc == 0)
			pc = _newObj();
		return *pc;
	}
	template<class Ti>
	inline ref at(const Ti& i) {
		return at(i < 0 ? 0 : size_t(i));
	}
	//Get the ith object of the chain. If i < 0, it will automatically take 0. If i > the maximum number of chains, it will automatically expand the capacity. Therefore, i will never generate cross-border errors
	inline ref operator[](size_t i) { return at(i); }
	template<class Ti>
	inline ref operator[](const Ti& i) { return at(i); }
	//Get the number of elements in the chain
	inline size_t size() const {
		return m_sublst != NULL ? m_sublst->size() : 0;
	}
	//Add element to end of link
	inline ref push_back(T v) {
		return at(size()) = v, *this;
	}
};

//Instantiate multidimensional safe array template class of object type (Note: the object class should properly handle the impact of object assignment or copy construction on internal dynamic pointer variables to avoid multiple releases)
#define CLArrayObj(objClass,definedClassName)\
template class CLArrayTemplate<objClass>;\
typedef CLArrayTemplate<objClass> definedClassName;\
typedef definedClassName& definedClassName##R;\
typedef const definedClassName& definedClassName##RC;\
typedef definedClassName* P##definedClassName;\
typedef const definedClassName* PC##definedClassName;

//Basic numeric type multidimensional safe array class template class
template<class T>
class CLArrayTemplateV :public CLArrayTemplate<CLValuePacking<T>> {
public:
	using obj = CLArrayTemplateV<T>;
	using obj_base = CLArrayTemplate<CLValuePacking<T>>;
	using pObj = CLArrayTemplateV<T>*;
	using pObj_base = CLArrayTemplate<CLValuePacking<T>>*;
	using ref_base = CLArrayTemplate<CLValuePacking<T>> &;
	using refc_base = const CLArrayTemplate<CLValuePacking<T>> &;
	using ref = CLArrayTemplateV<T> &;
	using refc = const CLArrayTemplateV<T> &;
	using vlist = std::initializer_list<CLValuePacking<T>>;
protected:
	virtual pObj _newObj() {
		pObj pnew;
		if (!obj_base::objLibrary.empty()) {
			pnew = (pObj)obj_base::objLibrary.top();
			obj_base::objLibrary.pop();
			pnew->clear();//Cleaning up Zi Lian
			pnew->reset();//reset object
			return pnew;
		}
		else {
			pnew = (pObj)malloc(sizeof(obj));
			pnew->CLArrayTemplateV::CLArrayTemplateV();
			return pnew;
		}
	}
	virtual void _storeOne(void* p) {
		obj_base::objLibrary.push((pObj)p);
	}
	virtual void _deleteOne(void* p) {
		((pObj)p)->CLArrayTemplateV::~CLArrayTemplateV();
		free(p);
	}
	inline virtual size_t _getClassSizeof() const {
		return sizeof(obj);
	}
public:
	inline void reset() {
		obj_base::m_createByLst = false;
		(*obj_base::m_vPack.m_value) = 0;
	}
	//Constructor and initialize the value to
	inline CLArrayTemplateV()
	{
		(*obj_base::m_vPack.m_value).v = 0;
	}
	template<class otherT>
	inline CLArrayTemplateV(otherT v)
	{
		(*obj_base::m_vPack.m_value).v = v;
	}
	CLArrayTemplateV(refc tag)
	{
		if (tag.m_createByLst)
			obj_base::m_createByLst = true, (*obj_base::m_vPack.m_value).v = 0;
		else
			(*obj_base::m_vPack.m_value).v = (*tag.m_vPack.m_value).v;
		obj_base::_copyList(tag.m_sublst);
	}
	CLArrayTemplateV(const vlist& _Ilist)
	{
		obj_base::operator = (_Ilist);
		obj_base::m_createByLst = true;
		(*obj_base::m_vPack.m_value).v = 0;
	}
	inline virtual ~CLArrayTemplateV() {
		obj_base::_release();
	}
	template<class otherT>
	inline ref operator =(otherT value) {
		return (obj_base::m_createByLst = false, (*obj_base::m_vPack.m_value).v = T(value)), * this;
	}
	//inline ref operator =(T value) {return (obj_base::m_createByLst = false, (*obj_base::m_vPack.m_value).v = value), * this;}	
	ref operator =(refc tag) {
		if (tag.m_createByLst)
			obj_base::m_createByLst = true, (*obj_base::m_vPack.m_value).v = 0;
		else
			(*obj_base::m_vPack.m_value).v = (*tag.m_vPack.m_value).v;
		obj_base::_copyList(tag.m_sublst);
		return *this;
	}
	inline ref operator =(const vlist& _Ilist) {
		return obj_base::operator = (_Ilist), * this;
	}
	//It can make the object itself be used in mathematical operations like a calculation number, constant value type conversion
	inline operator T() const {
		return (*obj_base::m_vPack.m_value).v;
	}
	//It can make the object itself be used in mathematical operations like a calculation number, variable type conversion
	inline operator T& () {
		return (*obj_base::m_vPack.m_value).v;
	}
	inline ref at(size_t i) {
		return (ref) * &(obj_base::at(i));
	}
	template<class Ti>
	inline ref at(const Ti& i) {
		return (ref) * &(obj_base::at(i < 0 ? 0 : size_t(i)));
	}
	//Get the ith object of the chain. If i < 0, it will automatically take 0. If i > the maximum number of chains, it will automatically expand the capacity. Therefore, i will never generate cross-border errors
	inline ref operator[](size_t i) { return (ref) * &(obj_base::at(i)); }
	template<class Ti>
	inline ref operator[](const Ti& i) { return (ref) * &(obj_base::at(i < 0 ? 0 : size_t(i))); }

	//operation

	obj operator--(int) {
		obj a = *this;
		++((*obj_base::m_vPack.m_value).v);
		return a;
	}
	obj operator++(int) {
		obj a = *this;
		++((*obj_base::m_vPack.m_value).v);
		return a;
	}
	inline ref operator--() {
		return --(*obj_base::m_vPack.m_value).v, * this;
	}
	inline ref operator++() {
		return ++(*obj_base::m_vPack.m_value).v, * this;
	}
	inline int operator%(int v) {
		return (((int)((*obj_base::m_vPack.m_value).v)) % v);
	}
};

//Instantiate multidimensional security array template class of basic numeric type
#define CLArrayV(baseValueClass,definedClassName)\
template class CLArrayTemplateV<baseValueClass>;\
typedef CLArrayTemplateV<baseValueClass> definedClassName;\
typedef definedClassName& definedClassName##R;\
typedef const definedClassName& definedClassName##RC;\
typedef definedClassName* P##definedClassName;\
typedef const definedClassName* PC##definedClassName;


#endif
Published 7 original articles, won praise 1, visited 409
Private letter follow

Topics: network less Windows