{"id":15047320,"url":"https://github.com/jmz-mzr/containers","last_synced_at":"2026-04-09T05:32:29.639Z","repository":{"id":224377011,"uuid":"455997597","full_name":"jmz-mzr/containers","owner":"jmz-mzr","description":"A performant recreation of the C++ library containers","archived":false,"fork":false,"pushed_at":"2024-04-18T17:11:42.000Z","size":127,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-02T13:52:28.889Z","etag":null,"topics":["42","42born2code","42cursus","42network","42paris","42school","algorithm","containers","cpp","cpp-containers","cpp98","metaprogramming","redblacktree","sfinae","stl","stl-containers"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jmz-mzr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-05T22:10:38.000Z","updated_at":"2024-04-18T14:49:37.000Z","dependencies_parsed_at":"2024-02-25T16:35:42.897Z","dependency_job_id":"3bf1bdeb-c3fa-4495-8615-fa08a7d8cf34","html_url":"https://github.com/jmz-mzr/containers","commit_stats":null,"previous_names":["jmz-mzr/ft_containers","jmz-mzr/containers"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jmz-mzr/containers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmz-mzr%2Fcontainers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmz-mzr%2Fcontainers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmz-mzr%2Fcontainers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmz-mzr%2Fcontainers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jmz-mzr","download_url":"https://codeload.github.com/jmz-mzr/containers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmz-mzr%2Fcontainers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31587828,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"online","status_checked_at":"2026-04-09T02:00:06.848Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["42","42born2code","42cursus","42network","42paris","42school","algorithm","containers","cpp","cpp-containers","cpp98","metaprogramming","redblacktree","sfinae","stl","stl-containers"],"created_at":"2024-09-24T20:56:35.461Z","updated_at":"2026-04-09T05:32:29.600Z","avatar_url":"https://github.com/jmz-mzr.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Containers\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"A cargo ship carrying containers on the sea, its name written on its side is CPP\" src=\"https://github.com/jmz-mzr/containers/assets/60391881/da47fb52-3fc2-4de2-9a0c-d75bb9ff9976\"\u003e\n\u003c/p\u003e\n\n\u003cdetails align=\"center\"\u003e\n\u003csummary\u003e\u003cb\u003eTable of Contents\u003c/b\u003e\u003c/summary\u003e\n\u003cdiv align=\"left\"\u003e\n\u003cbr\u003e\n\n- [Overview](#overview)\n  - [A word about Coding Style](#a-word-about-coding-style)\n- [Key Features](#key-features)\n- [Testing](#testing)\n  - [Video](#tester-video)\n- [Core Concepts](#core-concepts)\n- [Vector](#vector)\n- [Stack](#stack)\n  - [An interesting finding](#an-interesting-finding)\n- [Map](#map)\n- [Set](#set)\n- [The Red / Black Tree](#the-red-black-tree)\n  - [Video](#tree-video)\n- [Documentation](#documentation)\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cbr\u003e\n\n## Overview\n\n“Containers“ is a C++ project aimed at recreating a handful of containers from the C++ standard library: [vector](#vector), [stack](#stack), [map](#map), and [set](#set).  \nThis project is not just about coding; it's about delving deep into the essence of C++, crafting performance-efficient, memory-safe containers with a clean coding style.\n\nTo make it fun \u0026 useful, two details matter:\n\n- The containers must follow the [C++98 standard](https://www.lirmm.fr/~ducour/Doc-objets/ISO+IEC+14882-1998.pdf), and re-implement every single feature they had back then, even deprecated ones. No C++11, no external libraries, just pure \u0026 beautiful basics.\n- They need to be memory safe, efficient, and closely mirror or outperform the performances of the STD library. For map \u0026 set, that means implementing a [Red / Black binary search tree](#the-red-black-tree).\n\nTo achieve our goal, what best start other than digging into the [LIBSTDC++](https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3/include/bits) and [LIBC++](https://github.com/llvm/llvm-project/tree/main/libcxx/include) codebases?  \nBeing able to read and make sense of complex code is an essential skill — and it sometimes leads to little gems (see my findings on [stack](#stack)).\n\n### A word about Coding Style\n\nC++ is more verbose than C. However, being a strong advocate for [Clean Code](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882) \u0026 [Clean Architecture](https://www.amazon.com/dp/0134494164) practices — and to pay homage to the [42 School’s Norminette](https://github.com/42School/norminette) coding style — I made a point on delivering an explicit, clean, readable and well organised code. Have a look at [`vector`](https://github.com/jmz-mzr/containers/blob/master/includes/vector.hpp) for a start.\n\n\u003cbr\u003e\n\n## Key Features\n\n- **Complete Implementation**: Faithfully recreated vector, stack, map, and set as per C++98 standards\n- **High Performance**: Performances even better than standard library containers\n- **Memory Safety**: Carefully crafted to prevent memory leaks and ensure safe memory operations\n- **Red / Black Tree**: Advanced Red / Black binary search tree implementation for map and set\n- **Coding Style**: Emphasis on clean, self-explanatory, readable and organized code\n\n\u003cbr\u003e\n\n## Testing\n\nNothing can be great until it’s well tested!\n\n```\nmake test\n```\n\nTwo testers are provided: the first is an [`introduction one`](https://github.com/jmz-mzr/containers/blob/master/tests/42_main.cpp), made by 42.  \nThe other is a [`comprehensive test suite`](https://github.com/jmz-mzr/containers/tree/master/tests/srcs), running small and then memory-heavy operations on both our containers (in the ‘ft’ namespace), and the containers in the STD library.  \nThe output and the time performances are compared: the output must be the same, and the time performances as well (Kudos, ours are even faster! 🎉)\n\nEverything is tested, even the subtle requirements, for volatile, const and non-const versions:\n\n- Containers created empty (even with types that cannot be default constructed)\n- Working with custom allocators\n- Constructors and destructors\n- Typedefs\n- Member operators\n- Iterators\n- Element access functions\n- Capacity functions\n- Modifiers functions\n- Lookup functions\n- Observers functions\n- Non-member functions \u0026 operators  \n  \u003cspan id=\"tester-video\"\u003e\u003c/span\u003e\n  \u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cvideo src=\"https://github.com/jmz-mzr/containers/assets/60391881/d44f8f37-a16a-4fe5-9116-69c911f4e5ad\" height=\"1080\" width=\"1920\" /\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n## Core Concepts\n\nCore C++ concepts and techniques — [SFINAE](https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error), [Template Metaprogramming](https://en.wikipedia.org/wiki/Template_metaprogramming), etc — are the heart of the containers. They are illustrated in the recreation of some handy tools: [`enable_if`](https://github.com/jmz-mzr/containers/blob/main/includes/enable_if.hpp), [`is_integral`](https://github.com/jmz-mzr/containers/blob/main/includes/is_integral.hpp), [`iterator_traits`](https://github.com/jmz-mzr/containers/blob/main/includes/iterator_traits.hpp), [`reverse_iterator`](https://github.com/jmz-mzr/containers/blob/main/includes/reverse_iterator.hpp), [`is_integral`](https://github.com/jmz-mzr/containers/blob/main/includes/is_integral.hpp), [`equal`](https://github.com/jmz-mzr/containers/blob/main/includes/equal.hpp), [`lexicographical_compare`](https://github.com/jmz-mzr/containers/blob/main/includes/lexicographical_compare.hpp), [`pair`](https://github.com/jmz-mzr/containers/blob/main/includes/pair.hpp), and [`make_pair`](https://github.com/jmz-mzr/containers/blob/main/includes/make_pair.hpp).\n\nSome are hard to grasp, and it’s easier with examples: take a look at the tests written for them [`here`](https://github.com/jmz-mzr/containers/tree/main/tests/srcs).\n\n#### Useful links:\n\n- A handy FAQ about [C++ Templates](https://isocpp.org/wiki/faq/templates)\n- More on [SFINAE](https://h--deb-clg-qc-ca.translate.goog/Sujets/Divers--cplusplus/SFINAE.html?_x_tr_sl=auto\u0026_x_tr_tl=en\u0026_x_tr_hl=fr\u0026_x_tr_pto=wapp) with examples\n- The complete [C++ Metaprogramming Library](https://en.cppreference.com/w/cpp/meta)\n\n\u003cbr\u003e\n\n## Vector\n\n```\ntemplate \u003c\n    typename T,\n    class Allocator = std::allocator\u003cT\u003e\n\u003e class vector;\n```\n\nVectors represent arrays that can change in size. They use contiguous storage locations, so their elements can be accessed with offsets on regular pointers as efficiently as in arrays. But their size can change dynamically, and their storage is handled automatically.\n\nCompared to arrays, vectors consume more space, with extra memory allocated for future growth. But they grow in an efficient way: they reallocate only when their memory is exhausted. Reallocations happen at logarithmically growing intervals of their size, so insertions at the end are provided with [amortized constant time complexity](https://en.wikipedia.org/wiki/Amortized_analysis#Dynamic_array).\n\nThe total amount of allocated memory can be queried using [capacity()](https://en.cppreference.com/w/cpp/container/vector/capacity).  \nThe [reserve()](https://en.cppreference.com/w/cpp/container/vector/reserve) function can be used to eliminate reallocations if the number of elements is known beforehand.\n\nLike arrays, vectors are very efficient at accessing elements, and adding / removing elements from their end.  \nFor inserting / removing elements other than at the end, containers like [deque](https://en.cppreference.com/w/cpp/container/deque) or [list](https://en.cppreference.com/w/cpp/container/list) perform better.\n\nInternally, the implementation leverages SFINAE (e.g. to recognize pointers in [`insert()`](https://github.com/jmz-mzr/containers/blob/main/includes/vector.hpp#L626-L633) or [`assign()`](https://github.com/jmz-mzr/containers/blob/main/includes/vector.hpp#L497-L504)), the allocator’s [allocate()](https://en.cppreference.com/w/cpp/memory/allocator/allocate) \u0026 [deallocate()](https://en.cppreference.com/w/cpp/memory/allocator/deallocate) functions, or the [std::uninitialized_fill()](https://en.cppreference.com/w/cpp/memory/uninitialized_fill), [std::uninitialized_copy()](https://en.cppreference.com/w/cpp/memory/uninitialized_copy), and [std::copy_backward()](https://en.cppreference.com/w/cpp/algorithm/copy_backward) functions.  \nAs with the other containers, a clever architecture allows for core private functions (like [`_construct_at_end()`](https://github.com/jmz-mzr/containers/blob/main/includes/vector.hpp#L372-L398), [`_reallocate()`](https://github.com/jmz-mzr/containers/blob/main/includes/vector.hpp#L231-L301)) to be reused in other private \u0026 public ones.\n\n#### Useful links:\n\n- More [documentation](https://en.cppreference.com/w/cpp/container/vector) from _CPP Reference_\n- The [`code`](https://github.com/jmz-mzr/containers/blob/main/includes/vector.hpp)\n\n\u003cbr\u003e\n\n## Stack\n\n```\ntemplate \u003c\n    typename T,\n    class Container = ft::vector\u003cT\u003e\n\u003e class stack;\n```\n\nStacks are container adaptors, a [LIFO (last-in-first-out)](\u003chttps://en.wikipedia.org/wiki/Stack_(abstract_data_type)\u003e) data structure where elements are inserted and extracted only from one end. Stacks wrap an underlying container (by default here a vector), and push and pop the elements from the back of the container, known as the top of the stack.\n\n### An interesting finding\n\nStacks leverage two comparison operators to achieve [all comparisons](https://en.cppreference.com/w/cpp/container/stack/operator_cmp): `operator==` and `operator\u003c`.  \nAs stacks are template containers, in order for the compiler \u0026 linker to find the instantiated operators definitions, we either:\n\n- Forward declare both the class and the operators templates, before declaring the operators as friend function template specializations (if not defining them directly inside the class template body)\n- Or we declare all the instantiations of the operator templates as friend\n\nThese two methods have different implications, well detailed [here](https://stackoverflow.com/questions/4660123/overloading-friend-operator-for-class-template/4661372#4661372).  \nOne of them allows the operator to access a stack of any type, not just the `T` type of the stack currently compared!\n\nLooking at their codebase, we observe that [LIBC++](https://github.com/llvm/llvm-project/blob/main/libcxx/include/stack#L278-L283) and [LIBSTDC++](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_stack.h#L111-L117) are not protected against this resulting potential vulnerability. Even more interesting, when we go back in LIBSTDC++ commit history, we see that the most secure way to grant this friendship [was there](https://github.com/gcc-mirror/gcc/blob/725dc051cada61aca8127f1062ec97a31acf79f1/libstdc%2B%2B-v3/bits/stl_stack.h#L38-L74), commented, before being [partially](https://github.com/gcc-mirror/gcc/blob/d53d7f6e612a61bfabc102466ec4203ac36a338e/libstdc%2B%2B-v3/include/bits/stl_stack.h), then [fully deleted later](https://github.com/gcc-mirror/gcc/blob/7ffb61d5030d7299320beb9b16978a66d6513d86/libstdc%2B%2B-v3/include/bits/stl_stack.h).\n\nIt might be hard to exploit, however people tend to get smart when trying to hack stuff ;)  \nLaunch the [tester](#testing) to see a live demo.\n\n#### Useful links:\n\n- More [documentation](https://en.cppreference.com/w/cpp/container/stack) from _CPP Reference_\n- The [`code`](https://github.com/jmz-mzr/containers/blob/main/includes/stack.hpp)\n\n\u003cbr\u003e\n\n## Map\n\n```\ntemplate \u003c\n    typename Key,\n    typename T,\n    class Compare = std::less\u003cKey\u003e,\n    class Allocator = std::allocator\u003cft::pair\u003cconst Key, T\u003e \u003e\n\u003e class map;\n```\n\nMaps are associative containers, storing elements as pairs of `key value` \u0026 `mapped value`, with unique keys.\n\nKey values are sorted using the `Compare` function. The mapped values store the content associated to a key.  \nThe content can be accessed directly with the corresponding key using the [bracket operator[]](https://en.cppreference.com/w/cpp/container/map/operator_at) (which creates a new element if the key doesn't already exist).\n\nSince the elements are sorted, search, removal, and insertion operations have logarithmic complexity.  \nMaps are typically implemented as binary search trees — here it is a [Red / Black tree](#the-red-black-tree).\n\n#### Useful links:\n\n- More [documentation](https://en.cppreference.com/w/cpp/container/map) from _CPP Reference_\n- The [`code`](https://github.com/jmz-mzr/containers/blob/main/includes/map.hpp)\n\n\u003cbr\u003e\n\n## Set\n\n```\ntemplate \u003c\n    typename Key,\n    class Compare = std::less\u003cKey\u003e,\n    class Allocator = std::allocator\u003cKey\u003e\n\u003e class set;\n```\n\nSets are containers that store unique elements of type `Key`.\n\nThe elements are sorted using the `Compare` function. They cannot be modified once in the container (the values are always `const`), but they can be inserted and removed from the container.\n\nSince the elements are sorted, search, removal, and insertion operations have logarithmic complexity.  \nSets are typically implemented as binary search trees — here it is a [Red / Black tree](#the-red-black-tree).\n\n#### Useful links:\n\n- More [documentation](https://en.cppreference.com/w/cpp/container/set) from _CPP Reference_\n- The [`code`](https://github.com/jmz-mzr/containers/blob/main/includes/set.hpp)\n\n\u003cbr\u003e\n\n\u003cspan id=\"the-red-black-tree\"\u003e\u003c/span\u003e\n\n## The Red / Black Tree\n\n[Map](#map) and [Set](#set) both rely on an underlying [Red / Black binary search tree](https://en.wikipedia.org/wiki/Red–black_tree).\n\nIt is a self-balancing binary tree, where each node has an extra information of color (red or black) used in the [`insertion`](https://github.com/jmz-mzr/containers/blob/main/includes/_tree.hpp#L110-L170) \u0026 [`removal`](https://github.com/jmz-mzr/containers/blob/main/includes/_tree.hpp#L172-L314) algorithms to satisfy the tree’s [core properties](https://medium.com/@ben.tom.vincent/why-use-a-red-black-tree-over-a-regular-binary-search-tree-a63857916907#:~:text=Properties%20%E2%80%94%20all%20must,of%20black%20nodes).  \nThese algorithms keep the tree balanced, and ensure that the time complexity for insertion, deletion, and searching is always O(log n).\n\nInternally, the tree’s `root` is the left child of its `end_node`. So if `root != NULL`, `end_node-\u003eleft` points to `root`, and `root-\u003eparent` points to `end_node`.  \nTo optimize memory usage and minimize complexity, the [`node_base`](https://github.com/jmz-mzr/containers/blob/main/includes/_tree.hpp#L371-L387) class manages the pointers and the color bit, while the deriving [`node`](https://github.com/jmz-mzr/containers/blob/main/includes/_tree.hpp#L389-L405) class contains the actual node’s value.\n\nThe nature of the tree allows the use of recursion, for example in [`_structural_copy()`](https://github.com/jmz-mzr/containers/blob/main/includes/_tree.hpp#L796-L820), in [`_destroy()`](https://github.com/jmz-mzr/containers/blob/main/includes/_tree.hpp#L850-L859) or in [`_print()`](https://github.com/jmz-mzr/containers/blob/main/includes/_tree.hpp#L921-L943). This print function is used to visualize the content of the tree, especially in the context of...\n\n#### The tree tester:\n\n```\nmake tree \u0026\u0026 ./_tree_tests\n```\n\nA custom tester, showing what the current tree looks like, along with the expected results.  \nAs with the [containers’ tester](#testing), everything is tested, from the ability to create an empty tree, with custom allocators, to all the member functions \u0026 operators.\n\u003cspan id=\"tree-video\"\u003e\u003c/span\u003e  \n\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cvideo src=\"https://github.com/jmz-mzr/containers/assets/60391881/aeebc974-49a9-4efd-ad34-2ecbc7b5bcc4\" height=\"1080\" width=\"1920\" /\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n## Documentation\n\n- [Bjarne Stroustrup's website](https://www.stroustrup.com/index.html)\n- [IsoCPP Tour](https://isocpp.org/tour)\n- [IsoCPP Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)\n- [CPP Rererence](https://en.cppreference.com/w/cpp)\n- [CPlusPlus Reference](https://cplusplus.com/reference/)\n- [CPlusPlus Tutorials](https://cplusplus.com/doc/tutorial/)\n- [LearnCPP Tutorials](https://www.learncpp.com/)\n- [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmz-mzr%2Fcontainers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjmz-mzr%2Fcontainers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmz-mzr%2Fcontainers/lists"}