Criticism on improved Room class.

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
User avatar
cyboryxmen
Posts: 190
Joined: November 14th, 2014, 2:03 am

Criticism on improved Room class.

Post by cyboryxmen » August 9th, 2016, 8:22 pm

I have learned a lot these past few months. I have discovered new semantics and techniques that will allow somewhat more optimised code but importantly makes it safer, easier to read and convenient to use. Looking back, I realise how monstrous the Room class is in terms of safety, readability and convenience and while I can blame it on the use of advanced template meta-programming techniques(when you're using variadic templates with template specialization to provide template recursion termination, you're going to alienate a lot of casual programmers), it mostly comes down to me still experimenting with template meta-programming coding styles and doing it in the worst ways possible.

Now, I have combined all the techniques I learned in object-oriented programming and template meta-programming to write code that looks so much better than before. I have even added comments to help explain certain aspects of the code and make it look less daunting to read by adding actual sentences written for humans. The code now uses placement new() which makes it completely conformed to the standard preventing it from causing undefined behaviour(especially with polymorphic types) and also takes into consideration with memory alignment(though not really necessary even with the use of placement new()). There are also a bunch of other changes that just makes it more accommodating to code with.

Try out the code for yourselves. I have set up examples and test cases for you to run the code on so try to compile those and see if they work for you. Tell me if the code is still alienating and there are still certain aspects that you don't really understand so I could remedy that. If you know certain ways to make the syntax more readable and/or convenient or certain things I could change to optimise it, give me your suggestions. Maybe you like to write code in a certain way and the way the Room class is set up makes it intimidating for you to use. I'll try to find a way to customize it to fit your needs.

Room.h

Code: Select all

#pragma once
#ifndef SHARED_ROOM_H_
#define SHARED_ROOM_H_
#include <cstdint>
#include <memory>
#include <type_traits>

namespace shared
{
	/******************************************************************************/
	/*!
	\brief
	Contains types and functions only avaliable to the Room class.

	*/
	/******************************************************************************/
	struct RoomAssets
	{
		RoomAssets() = delete;

	private:
		template<class Interface, std::uintmax_t size>
		friend class Room;

		template<class Interface>
		/******************************************************************************/
		/*!
		\brief
		Interface used by the Room class to provide cloning, moving and virtual
		destruction semantics for the occupant removing the need for them to implement
		it themselves.

		*/
		/******************************************************************************/
		class Agent
		{
		protected:
			//THERE CAN ONLY BE ONE!
			Agent() = default;
			~Agent() = default;
			Agent(const Agent&) = delete;
			Agent& operator=(const Agent&) = delete;

		public:
			/******************************************************************************/
			/*!
			\brief
			Call a generic agent to monitor the room when there is no one there.

			\return
			An agent.

			*/
			/******************************************************************************/
			static Agent* Call()
			{
				static Agent agent;
				return &agent;
			}

			/******************************************************************************/
			/*!
			\brief
			Run the destructor of the occupant.

			\param some_dude
			The poor sucker that actually agreed to stay here.

			*/
			/******************************************************************************/
			virtual void Murder(std::uint8_t*const some_dude) const
			{
				//Do nothing by default(Used when the room is occupied by nothing).
			}

			/******************************************************************************/
			/*!
			\brief
			Move the occupant to a new memory location.

			\param occupant
			The memory containing the occupant to escort.

			\param new_location
			The new memory location to escort the occupant to.

			*/
			/******************************************************************************/
			virtual void Escort(std::uint8_t*const occupant, std::uint8_t*const new_location) const
			{
				//Do nothing by default(Used when the room is occupied by nothing).
			}

			/******************************************************************************/
			/*!
			\brief
			Clone the occupant to a new memory location.

			\param occupant
			The memory containing the occupant to clone.

			\param new_location
			The new memory location to clone the occupant to.

			*/
			/******************************************************************************/
			virtual void Clone(const std::uint8_t* occupant, std::uint8_t*const new_location) const
			{
				//Do nothing by default(Used when the room is occupied by nothing).
			}

			/******************************************************************************/
			/*!
			\brief
			Visit the occupant and interact with them with an interface(Actually meeting
			face to face is soooooo pre-1983!).

			\param occupant
			The memory containing the occupant to visit.

			\return
			The interface.

			*/
			/******************************************************************************/
			virtual Interface* Visit(std::uint8_t*const occupant) const
			{
				//There is no one there lol.
				return nullptr;
			}

			/******************************************************************************/
			/*!
			\brief
			Visit the occupant and interact with them with an interface with const
			correctness(Actually meeting face to face is soooooo pre-1983!).

			\param occupant
			The memory containing the occupant to visit.

			\return
			The interface.

			*/
			/******************************************************************************/
			virtual const Interface* Visit(const std::uint8_t* occupant) const
			{
				//There is no one there lol.
				return nullptr;
			}
		};

		template<class Interface, class Type>
		/******************************************************************************/
		/*!
		\brief
		An efficient killer bred to assassinate with swiftness and discretion.

		*/
		/******************************************************************************/
		class Agent47 : public Agent<Interface>
		{
		private:
			//THERE CAN ONLY BE ONE!
			Agent47() = default;
			~Agent47() = default;
			Agent47(const Agent47&) = delete;
			Agent47& operator=(const Agent47&) = delete;

		public:
			/******************************************************************************/
			/*!
			\brief
			Always there when you need him.

			\return
			agent 47.

			*/
			/******************************************************************************/
			static Agent47* Call()
			{
				static Agent47 agent_47;
				return &agent_47;
			}

			/******************************************************************************/
			/*!
			\brief
			Run the destructor of the occupant.

			\param some_dude
			The poor sucker that actually agreed to stay here.

			*/
			/******************************************************************************/
			void Murder(std::uint8_t*const some_dude) const override
			{
				reinterpret_cast<Type*>(some_dude)->~Type();
			}

			/******************************************************************************/
			/*!
			\brief
			Move the occupant to a new memory location.

			\param occupant
			The memory containing the occupant to escort.

			\param new_location
			The new memory location to escort the occupant to.

			*/
			/******************************************************************************/
			void Escort(std::uint8_t*const occupant, std::uint8_t*const new_location) const override
			{
				Type& escort = *reinterpret_cast<Type*>(occupant);

				//Move our escort to the new location.
				new (new_location) Type(static_cast<Type&&>(escort));
			}

			/******************************************************************************/
			/*!
			\brief
			Clone the occupant to a new memory location.

			\param occupant
			The memory containing the occupant to clone.

			\param new_location
			The new memory location to clone the occupant to.

			*/
			/******************************************************************************/
			void Clone(const std::uint8_t* occupant, std::uint8_t*const new_location) const override
			{
				//Clone our occupant to the new location. Currently disabled until Visual Studio implements sfinae.
				//new (new_location) Type(*reinterpret_cast<const Type*>(occupant));
			}

			/******************************************************************************/
			/*!
			\brief
			Visit the occupant and interact with them with an interface(Actually meeting
			face to face is soooooo pre-1983!).

			\param occupant
			The memory containing the occupant to visit.

			\return
			The interface.

			*/
			/******************************************************************************/
			Interface* Visit(std::uint8_t*const occupant) const override
			{
				return reinterpret_cast<Type*>(occupant);
			}

			/******************************************************************************/
			/*!
			\brief
			Visit the occupant and interact with them with an interface with const
			correctness(Actually meeting face to face is soooooo pre-1983!).

			\param occupant
			The memory containing the occupant visit.

			\return
			The interface.

			*/
			/******************************************************************************/
			const Interface* Visit(const std::uint8_t* occupant) const
			{
				return reinterpret_cast<const Type*>(occupant);
			}
		};
	};

	template<class FirstType, class SecondType, bool FirstTypeIsBigger = (sizeof(FirstType) > sizeof(SecondType))>
	/******************************************************************************/
	/*!
	\brief
	Used to find the biggest type amoung two types.

	*/
	/******************************************************************************/
	struct GetBiggestType
	{
		GetBiggestType() = delete;
		using Type = FirstType;
	};

	template<class FirstType, class SecondType>
	/******************************************************************************/
	/*!
	\brief
	Recursion termination.

	*/
	/******************************************************************************/
	struct GetBiggestType<FirstType, SecondType, false>
	{
		GetBiggestType() = delete;
		using Type = SecondType;
	};

	template<class FirstType, class SecondType, class...OtherTypes>
	/******************************************************************************/
	/*!
	\brief
	Used to find the biggest type amoung a list of types.

	*/
	/******************************************************************************/
	struct FindBiggestTypeInList
	{
		FindBiggestTypeInList() = delete;
		using Type = typename FindBiggestTypeInList<typename GetBiggestType<FirstType, SecondType>::Type, OtherTypes...>::Type;
	};

	template<class SecondLastType, class LastType>
	/******************************************************************************/
	/*!
	\brief
	Recursion termination.

	*/
	/******************************************************************************/
	struct FindBiggestTypeInList<SecondLastType, LastType>
	{
		FindBiggestTypeInList() = delete;
		using Type = typename GetBiggestType<SecondLastType, LastType>::Type;
	};

	template<std::uintmax_t size, std::uintmax_t index = 0, bool BiggerOrEqualToSize = (sizeof(void*) * index >= size)>
	/******************************************************************************/
	/*!
	\brief
	Get a size that is a multiple of the size of a memory address to make sure
	that the memory of that size will be properly aligned(Not nessesary for using
	placement new() but it helps).

	*/
	/******************************************************************************/
	struct SetSizeToProperAlignment
	{
		SetSizeToProperAlignment() = delete;

		enum
		{
			value = SetSizeToProperAlignment<size, index + std::uintmax_t(1)>::value
		};
	};

	template<std::uintmax_t size, std::uintmax_t index>
	/******************************************************************************/
	/*!
	\brief
	Recursion termination.

	*/
	/******************************************************************************/
	struct SetSizeToProperAlignment<size, index, true>
	{
		SetSizeToProperAlignment() = delete;

		enum
		{
			value = sizeof(void*) * index
		};
	};

	template<class FirstType, class SecondType, class...OtherTypes>
	using RoomSizeForTypes = SetSizeToProperAlignment<sizeof(typename FindBiggestTypeInList<FirstType, SecondType, OtherTypes...>::Type)>;

	template<class Interface, std::uintmax_t size>
	/******************************************************************************/
	/*!
	\brief
	A class that contains a block of memory that can be used to represent any type
	that can be converted into a specific interface. This enables the ability to
	make memory polymorphic and turn it into any type we need at any given time.
	The Room remembers what is occupying it and will provide cloning and move
	symantics and do automatic virtual destruction on demand without the types nor
	the interface needing to implement them. It also helps with alignment since it
	allows all these different types to occupy the same array by storing themselves
	inside the same room class. The room will accept any type as long as it can be
	converted into it's specific interface and is smaller or equal to the size of
	the block of memory inside it. The room is set to be occupied by nothing by
	default and can be set to this state with the MurderOccupant() function.

	*/
	/******************************************************************************/
	class Room
	{
	public:
		/******************************************************************************/
		/*!
		\brief
		Default Constructor(Will set the room to be occupied by nothing).

		*/
		/******************************************************************************/
		Room()
		:
		agent_(RoomAssets::Agent<Interface>::Call())
		{
		}

		/******************************************************************************/
		/*!
		\brief
		Destructor.

		*/
		/******************************************************************************/
		~Room()
		{
			MurderOccupant();
		}

		/******************************************************************************/
		/*!
		\brief
		Copy constructor. Disabled until Visual Studio implements sfinae.

		*/
		/******************************************************************************/
		Room(const Room& room) = delete;
		//:
		//agent_(room.agent)
		//{
		//	room.agent_->Clone(room.memory_, memory_);
		//}

		/******************************************************************************/
		/*!
		\brief
		Copy operator(will destroy the current occupant if occupied). Disabled until
		Visual Studio implements sfinae.

		\return
		this.

		*/
		/******************************************************************************/
		Room& operator=(const Room& room) = delete;
		//{
		//	MurderOccupant();
		//	agent_ = room.agent_;
		//	room.agent_->Clone(room.memory_, memory_);

		//	return *this;
		//}

		/******************************************************************************/
		/*!
		\brief
		Move constructor.

		*/
		/******************************************************************************/
		Room(Room&& room)
		:
		agent_(room.agent_)
		{
			agent_->Escort(room.memory_, memory_);
		}

		/******************************************************************************/
		/*!
		\brief
		Move operator(will destroy the current occupant if occupied).

		\return
		this.

		*/
		/******************************************************************************/
		Room& operator=(Room&& room)
		{
			//To prevent stealing of own resources(Possible because object has been created already.)
			if (this == &room)
			{
				return *this;
			}

			MurderOccupant();
			agent_ = room.agent_;

			agent_->Escort(room.memory_, memory_);

			return *this;
		}

		template<class Type>
		/******************************************************************************/
		/*!
		\brief
		Copy constructor for types convertable to the interface.

		*/
		/******************************************************************************/
		Room(const Type& type)
		{
			static_assert(sizeof(type) <= size, "That type is bigger than the size of the room's memory block!");
			static_assert(std::is_convertible<Type, Interface>::value, "That type cannot be converted to the interface!");

			//Use placement new to define our block of memory.
			new (memory_) Type(type);

			//Get our top agent on watch right now!
			agent_ = RoomAssets::Agent47<Interface, Type>::Call();
		}

		template<class Type>
		/******************************************************************************/
		/*!
		\brief
		Copy operator for types convertable to the interface(will destroy the current
		occupant if occupied).

		\return
		this.

		*/
		/******************************************************************************/
		Room& operator=(const Type& type)
		{
			static_assert(sizeof(type) <= size, "That type is bigger than the size of the room's memory block!");
			static_assert(std::is_convertible<Type, Interface>::value, "That type cannot be converted to the interface!");

			//murder the previous occupant to make room for the new one.
			MurderOccupant();

			//Use placement new to define our block of memory.
			new (memory_) Type(type);

			//Get our top agent on watch right now!
			agent_ = RoomAssets::Agent47<Interface, Type>::Call();

			return *this;
		}

		template<class Type>
		/******************************************************************************/
		/*!
		\brief
		Move constructor for types convertable to the interface.

		*/
		/******************************************************************************/
		Room(Type&& type)
		{
			static_assert(sizeof(type) <= size, "That type is bigger than the size of the room's memory block!");
			static_assert(std::is_convertible<Type, Interface>::value, "That type cannot be converted to the interface!");

			//Use placement new to define our block of memory.
			new (memory_) Type(std::move(type));

			//Get our top agent on watch right now!
			agent_ = RoomAssets::Agent47<Interface, Type>::Call();
		}

		template<class Type>
		/******************************************************************************/
		/*!
		\brief
		Move operator for types convertable to the interface(will destroy the current
		occupant if occupied).

		\return
		this.

		*/
		/******************************************************************************/
		Room& operator=(Type&& type)
		{
			static_assert(sizeof(type) <= size, "That type is bigger than the size of the room's memory block!");
			static_assert(std::is_convertible<Type, Interface>::value, "That type cannot be converted to the interface!");

			//murder the previous occupant to make room for the new one.
			MurderOccupant();

			//Use placement new to define our block of memory.
			new (memory_) Type(std::move(type));

			//Get our top agent on watch right now!
			agent_ = RoomAssets::Agent47<Interface, Type>::Call();

			return *this;
		}

		/******************************************************************************/
		/*!
		\brief
		Member access operator overload to interact with the occupant with the
		interface(If the room is not occupied by anything, it will return a nullptr
		causing an error).

		\return
		The interface.

		*/
		/******************************************************************************/
		Interface* operator->()
		{
			return agent_->Visit(memory_);
		}

		/******************************************************************************/
		/*!
		\brief
		Member access operator overload to interact with the occupant with the
		interface with const correcness.(If the room is not occupied by anything, it
		will return a nullptr causing an error).

		\return
		The interface.

		*/
		/******************************************************************************/
		const Interface* operator->() const
		{
			return agent_->Visit(memory_);
		}

		/******************************************************************************/
		/*!
		\brief
		Return an Interface pointer to the occupying type(will return null if not
		occupied by anything).

		\return
		The interface.

		*/
		/******************************************************************************/
		Interface* Visit()
		{
			return agent_->Visit(memory_);
		}

		/******************************************************************************/
		/*!
		\brief
		Member access operator overload to interact with the occupant with the
		interface with const correcness.

		\return
		The interface.

		*/
		/******************************************************************************/
		const Interface* Visit() const
		{
			return agent_->Visit(memory_);
		}

		/******************************************************************************/
		/*!
		\brief
		Murder the occupant to make room for other occupants or just for funsies(will
		set the room to be occupied by nothing).

		*/
		/******************************************************************************/
		void MurderOccupant()
		{
			agent_->Murder(memory_);
			agent_ = RoomAssets::Agent<Interface>::Call();
		}

	private:
		std::uint8_t memory_[size];
		RoomAssets::Agent<Interface>* agent_;
	};
}
#endif
main.cpp

Code: Select all

#include <iostream>
#include <vector>
#include "TypeList.h"
#include "Room.h"

namespace shape_library
{
	class Square{};
	class Triangle{};
	class Circle{};
}

namespace mesh_library
{
	class Mesh{};
}

class Collidable
{
public:
	using Square = shape_library::Square;
	using Triangle = shape_library::Triangle;
	using Circle = shape_library::Circle;
	using Mesh = mesh_library::Mesh;

	virtual void CollideWith(Collidable* collidable) = 0;
	virtual void CollideWith(Square& collidable) = 0;
	virtual void CollideWith(Triangle& collidable) = 0;
	virtual void CollideWith(Circle& collidable) = 0;
	virtual void CollideWith(Mesh& collidable) = 0;
};

template<class Type>
class CollidableTemplate : public Collidable
{
public:
	//unsupported type
	CollidableTemplate() = delete;
};

template<>
class CollidableTemplate<Collidable::Square> : public Collidable
{
public:
	CollidableTemplate(Square& collidable)
	:
	collidable_(collidable)
	{
	}

	~CollidableTemplate()
	{
		std::cout << "Square collider has terminated" << std::endl;
	}

	void CollideWith(Collidable* collidable) override
	{
		collidable->CollideWith(collidable_);
	}

	void CollideWith(Square& collidable) override
	{
		std::cout << "Square has collided with square!" << std::endl;
	}

	void CollideWith(Triangle& collidable) override
	{
		std::cout << "Square has collided with triangle!" << std::endl;
	}

	void CollideWith(Circle& collidable) override
	{
		std::cout << "Square has collided with circle!" << std::endl;
	}

	void CollideWith(Mesh& collidable) override
	{
		std::cout << "Square has collided with mesh!" << std::endl;
	}

private:
	Square& collidable_;
};

template<>
class CollidableTemplate<Collidable::Triangle> : public Collidable
{
public:
	CollidableTemplate(Triangle& collidable)
		:
		collidable_(collidable)
	{
	}

	~CollidableTemplate()
	{
		std::cout << "Triangle collider has terminated" << std::endl;
	}

	void CollideWith(Collidable* collidable) override
	{
		collidable->CollideWith(collidable_);
	}

	void CollideWith(Square& collidable) override
	{
		std::cout << "Triangle has collided with square!" << std::endl;
	}

	void CollideWith(Triangle& collidable) override
	{
		std::cout << "Triangle has collided with triangle!" << std::endl;
	}

	void CollideWith(Circle& collidable) override
	{
		std::cout << "Triangle has collided with circle!" << std::endl;
	}

	void CollideWith(Mesh& collidable) override
	{
		std::cout << "Triangle has collided with mesh!" << std::endl;
	}

private:
	Triangle& collidable_;
};

template<>
class CollidableTemplate<Collidable::Circle> : public Collidable
{
public:
	CollidableTemplate(Circle& collidable)
		:
		collidable_(collidable)
	{
	}

	~CollidableTemplate()
	{
		std::cout << "Circle collider has terminated" << std::endl;
	}

	void CollideWith(Collidable* collidable) override
	{
		collidable->CollideWith(collidable_);
	}

	void CollideWith(Square& collidable) override
	{
		std::cout << "Circle has collided with square!" << std::endl;
	}

	void CollideWith(Triangle& collidable) override
	{
		std::cout << "Circle has collided with triangle!" << std::endl;
	}

	void CollideWith(Circle& collidable) override
	{
		std::cout << "Circle has collided with circle!" << std::endl;
	}

	void CollideWith(Mesh& collidable) override
	{
		std::cout << "Circle has collided with mesh!" << std::endl;
	}

private:
	Circle& collidable_;
};

template<>
class CollidableTemplate<Collidable::Mesh> : public Collidable
{
public:
	CollidableTemplate(Mesh& collidable)
		:
		collidable_(collidable)
	{
	}

	~CollidableTemplate()
	{
		std::cout << "Mesh collider has terminated" << std::endl;
	}

	void CollideWith(Collidable* collidable) override
	{
		collidable->CollideWith(collidable_);
	}

	void CollideWith(Square& collidable) override
	{
		std::cout << "Mesh has collided with square!" << std::endl;
	}

	void CollideWith(Triangle& collidable) override
	{
		std::cout << "Mesh has collided with triangle!" << std::endl;
	}

	void CollideWith(Circle& collidable) override
	{
		std::cout << "Mesh has collided with circle!" << std::endl;
	}

	void CollideWith(Mesh& collidable) override
	{
		std::cout << "Mesh has collided with mesh!" << std::endl;
	}

private:
	Mesh& collidable_;
};

template<class Type>
CollidableTemplate<Type> GetCollidable(Type& type)
{
	return CollidableTemplate<Type>(type);
}

void main()
{
	enum
	{
		room_size = shared::RoomSizeForTypes<CollidableTemplate<shape_library::Square>, CollidableTemplate<shape_library::Triangle>, CollidableTemplate<shape_library::Circle>, CollidableTemplate<mesh_library::Mesh>>::value
	};

	using RoomForCollidables = shared::Room<Collidable, room_size>;

	std::vector<RoomForCollidables> collidables(1);

	std::vector<Collidable::Square> squares(15);
	std::vector<Collidable::Circle> circles(15);
	std::vector<Collidable::Triangle> triangles(15);
	std::vector<Collidable::Mesh> meshes(15);

	//test for setting the room. The temp collidable we copied from should run it's destructor.
	collidables[0] = GetCollidable(circles[1]);

	//should override CollidableTemplate<Circle> and call it's destructor. The temp collidable we copied from should run it's destructor last.
	collidables[0] = GetCollidable(circles[1]);

	//same deal.
	collidables[0] = GetCollidable(circles[1]);

	collidables[0] = GetCollidable(squares[1]);

	//Override CollidableTemplate<Square> and set the room to nothing.
	collidables[0] = RoomForCollidables();

	std::cout << std::endl;

	//test for Room's compatibility with vector.
	for (std::size_t index = 0; index < 15; ++index)
	{
		collidables.push_back(RoomForCollidables());
	}

	//There are now 16 instances of a room of collidables(1 from the beginning and 15 from the for loop).
	collidables[0] = GetCollidable(circles[1]);
	collidables[1] = GetCollidable(squares[1]);
	collidables[2] = GetCollidable(meshes[1]);
	collidables[3] = GetCollidable(circles[1]);
	collidables[4] = GetCollidable(meshes[1]);
	collidables[5] = GetCollidable(meshes[1]);
	collidables[6] = GetCollidable(triangles[1]);
	collidables[7] = GetCollidable(meshes[1]);
	collidables[8] = GetCollidable(meshes[1]);
	collidables[9] = GetCollidable(triangles[1]);
	collidables[10] = GetCollidable(triangles[1]);
	collidables[11] = GetCollidable(meshes[1]);
	collidables[12] = GetCollidable(triangles[1]);
	collidables[13] = GetCollidable(triangles[1]);
	collidables[14] = GetCollidable(triangles[1]);
	collidables[15] = GetCollidable(squares[1]);
	
	std::cout << std::endl;

	//Should print collidables[second index] has collided with collidables[first index]
	collidables[0]->CollideWith(collidables[8].Visit());
	collidables[11]->CollideWith(collidables[3].Visit());
	collidables[3]->CollideWith(collidables[6].Visit());
	collidables[1]->CollideWith(collidables[11].Visit());
	collidables[2]->CollideWith(collidables[7].Visit());
	collidables[1]->CollideWith(collidables[6].Visit());
	collidables[2]->CollideWith(collidables[15].Visit());
	collidables[11]->CollideWith(collidables[10].Visit());
	collidables[0]->CollideWith(collidables[5].Visit());
	collidables[0]->CollideWith(collidables[3].Visit());
	collidables[0]->CollideWith(collidables[4].Visit());
	collidables[5]->CollideWith(collidables[3].Visit());
	collidables[5]->CollideWith(collidables[7].Visit());
	collidables[14]->CollideWith(collidables[7].Visit());
	collidables[7]->CollideWith(collidables[13].Visit());
	collidables[7]->CollideWith(collidables[2].Visit());

	std::cout << std::endl;

	//Test for compatibility with erase.
	collidables.erase(collidables.begin());

	std::cout << std::endl;

	//same but index + 1
	collidables[0]->CollideWith(collidables[12].Visit());
	collidables[0]->CollideWith(collidables[13].Visit());
	collidables[10]->CollideWith(collidables[7].Visit());
	collidables[0]->CollideWith(collidables[0].Visit());
	collidables[13]->CollideWith(collidables[1].Visit());
	collidables[14]->CollideWith(collidables[11].Visit());
	collidables[2]->CollideWith(collidables[13].Visit());
	collidables[14]->CollideWith(collidables[8].Visit());
	collidables[12]->CollideWith(collidables[11].Visit());
	collidables[3]->CollideWith(collidables[11].Visit());
	collidables[3]->CollideWith(collidables[11].Visit());
	collidables[6]->CollideWith(collidables[10].Visit());
	collidables[12]->CollideWith(collidables[4].Visit());
	collidables[14]->CollideWith(collidables[5].Visit());
	collidables[7]->CollideWith(collidables[8].Visit());
	collidables[12]->CollideWith(collidables[2].Visit());

	std::cout << std::endl;

	collidables.clear();

	std::cout << std::endl;

	system("pause");
}
Zekilk

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Criticism on improved Room class.

Post by chili » August 10th, 2016, 1:47 am

Interesting stuff you're doing here cyborg. The ability to have polymorphism while also maintaining contiguous data is pretty big, but I wonder if you lose that benefit from the pointer RoomAssets::Agent<Interface>* agent_;. I haven't looked too deeply into it so it's just a thought.
Chili

Post Reply