Experimental modern C++23 metaprogramming implementation of a pure archetype-based Entity Component System (ECS).
A lightweight, header-only exploration of a theoretical archetype-based ECS (Entity Component System) with a focus on expressiveness, compile-time tricks, and performance. This project implements the theoretical model of mapping systems directly to archetypes and uses modern C++23 features to produce an elegant solution. It is for experimentation: specifically to demonstrate some of the newer C++ metaprogramming wizardry by implementing a theoretical archetype-based ECS; it is not intended for production use.
- Purpose: a concise showcase of modern C++ metaprogramming and zero-cost abstractions via a theoretical system-to-archetype ECS.
- Scope: intentionally omits query APIs to emphasize the theoretical system→archetype mapping.
- You want to study how an archetype-based ECS can be modeled “by the book”.
- You want to see modern C++ techniques applied to ECS internals (type-munging, concepts, ranges, explicit object parameters, etc.).
- You need a fast, minimal reference for experiments or benchmarks.
- You need a production ECS with queries, tooling, scheduling, and ecosystem support—use a mature library.
- C++23-compatible compiler (tested with GCC 15.2).
- Recommended minimum:
- GCC 13+ or Clang 16+ or MSVC 19.38+ (explicit object parameters and ranges).
- A standard library implementation providing
std::rangesandstd::views::zip. - No external dependencies beyond the C++ standard library for the library itself.
- Tests depend on GoogleTest (gtest).
This is a header-only library. Add metarchetype.h to your include paths and include it:
#include "metarchetype.h"Namespace: everything resides in namespace meta.
meta::archetype<Allocator, Components...>: SoA storage for a set of component types.meta::system_set<Systems...>: a tuple-like container of systems.meta::entity_manager<Systems...>: holds systems and anarchetype_setdeduced from each system’sprocesssignature.meta::entity: 64-bit handle encoding(archetype_index | row_index).meta::sparse_set<Allocator>for dense-packed indices.- Traits and utils under
meta::traits:var_types,unique_tuple,tuple_index_v,contains,invocable_args, etc.
#include "metarchetype.h"
struct Position { float x{}, y{}; };
struct Velocity { float x{}, y{}; };
using arch_t = meta::archetype<std::allocator, Position, Velocity>;
// Define a system that operates on an archetype of Position + Velocity
struct movement_system {
// By convention, Systems expose a process(archetype) member.
void process(arch_t& arch) {
// For multi-component archetypes, get_components() returns a zipped view.
for (auto [pos, vel] : arch.get_components()) {
pos.x += vel.x;
pos.y += vel.y;
}
}
};
int main() {
// entity_manager deduces the unique set of archetypes from the Systems...
meta::entity_manager<movement_system> em{};
// Create an entity in the MovementSystem's archetype
meta::entity e = em.create_entity<arch_t>();
// Initialize its components
auto& p = em.get_component<Position>(e);
auto& v = em.get_component<Velocity>(e);
p = {0.0f, 0.0f};
v = {1.0f, 2.0f};
// Run update — forwards to movement_system::process(arch)
em.on_update();
// assert(near_equal(p.x, 1.0f) && near_equal(p.y, 2.0f));
}MIT License.