#pragma once
#include <concepts>
template<typename P>
	requires requires {typename P::UClass;}
class parray {
	using UClass = P::UClass;
protected:
	uint32_t t_size;
	uint32_t m_size;
	uint32_t m_head{ 0 };
	char* m_buf;
	UClass* u_class;
public:
	~parray() {
		if (m_buf) {
			free(m_buf);
		}
	}
	parray(uint32_t tsize, uint32_t size, UClass* uclass) 
		: t_size(tsize), m_buf((char*)malloc(tsize* size)), m_size(size),u_class(uclass) {}
	parray(parray& other) noexcept {
		m_size = other.m_size;
		m_head = other.m_head;
		m_buf = other.m_buf;
		other.m_buf = nullptr;
	}
	void* data() {
		return m_buf;
	}
	uint32_t size() {
		return m_head;
	}
	uint32_t data_size() {
		return t_size * m_head;
	};
	P* at(int i){
		if (i >= m_head) {
			return nullptr;
		}
		return (P*)(m_buf + i * t_size);
	};
};
template<typename P, typename T>
	requires std::is_base_of<P, T>::value && requires {typename P::UClass; }
class ptarray : public parray<P>{
	using parray<P>::m_head;
	using parray<P>::m_size;
	using parray<P>::m_buf;
	using parray<P>::t_size;
public:
	ptarray(uint32_t size = 1) : parray<P>(sizeof(T), size, new T::UClass()) {}
	void push_back(T& t) {
		if (m_head >= m_size) {
			return;
		}
		*(T*)(m_buf + m_head * t_size) = t;
		m_head++;
	};
};