Welcome
ZeroToHero is the YouTube channel where we discuss programming, data structures and algorithms, computer science, and software design.
In a world where things only ever seem to get more complicated, we bring it back down to earth.
Forget about modern C++, learn to write beautiful code with no dependencies... we take you from zero to hero.
Using a minimalist fictional dialect of C++ which we like to call C--, we will show you how to build high performance applications, libraries, and frameworks from scratch using cutting edge tools and techniques.
ZeroToHero is the YouTube channel where we discuss programming, data structures and algorithms, computer science, and software design.
In a world where things only ever seem to get more complicated, we bring it back down to earth.
Forget about modern C++, learn to write beautiful code with no dependencies... we take you from zero to hero.
Using a minimalist fictional dialect of C++ which we like to call C--, we will show you how to build high performance applications, libraries, and frameworks from scratch using cutting edge tools and techniques.
- Rediscover how to write code using Object Oriented principles, multiple inheritance, and polymorphism
- Practice computer science fundamentals, and take a deep dive into data structures and algorithms
- Understand data driven design, and minimalist approaches to error handling and control flow
- Do away with uneccessary syntax and complexity but gain power and performance
- Solve difficult problems using simple abstractions and low level techniques
- Kick bad habbits and stop following broken patterns and methodologies
- See how to write clean maintainable code that you will be proud off
- Find new approaches to benchmark, profile, debug and test your code
- Build confidence, and make an impact on the future of programming
- Write secure, bug free, reusable, robust software
- Target WASM and small portable binaries
Better performance.
Using very carefully designed, but also very simple interfaces we can build an Array<> data structure that supports binary search with lower and upper bound.
If care is taken with the binary search implementation we can write a method where an item not in the list can return its insertion index.
With fast callbacks we can then use an Array<> to provide external integer indexes for other arrays of more complex types.
Putting these ideas together we can build Map<> and Set<> types which support insertion order traversal, linear array based memory access and iteration, low memory usage, and very fast cache efficient lookup.
Up to 40% faster that standard C++ and 20%
less memory usage.
Using very carefully designed, but also very simple interfaces we can build an Array<> data structure that supports binary search with lower and upper bound.
If care is taken with the binary search implementation we can write a method where an item not in the list can return its insertion index.
With fast callbacks we can then use an Array<> to provide external integer indexes for other arrays of more complex types.
Putting these ideas together we can build Map<> and Set<> types which support insertion order traversal, linear array based memory access and iteration, low memory usage, and very fast cache efficient lookup.
Up to 40% faster that standard C++ and 20%
less memory usage.

Comparison of Hero::Map<> and Hero::Hash<>
against C++ standard library containers
over 1 million inserts.
Results recorded using
Microsoft Visual Studio 2019.
AMD Ryzen 9 5900HS.
std::map<>
Peak: 210 (mb)
Time: 0.363 (s)
Peak: 210 (mb)
Time: 0.363 (s)
Hero::Map<>
Peak: 171 (mb)
Time: 0.291 (s)
Wins by 72 (ms)
Peak: 171 (mb)
Time: 0.291 (s)
Wins by 72 (ms)
std::unordered_map<>
Peak: 203 (mb)
Time: 0.579 (s)
Peak: 203 (mb)
Time: 0.579 (s)
Hero::Hash<>
Peak: 202 (mb)
Time: 0.345 (s)
Wins by 231 (ms)
Peak: 202 (mb)
Time: 0.345 (s)
Wins by 231 (ms)


Clean readable, reusable,
maintainable code.
maintainable code.
Result Insert(_Kind_ && kind, int index) { Assert(index <= Size); // Normalise unbounded so we can insert at size if (!Indices::Normalise(index,Size,false)) return false; if (IsNull() || Size >= Allocated) Allocate(); if (index < Size) Array<_Kind_>::Move(Data+index+1,Data+index,Size-index); Data[index] = (_Kind_&&)kind; ++Size; return Result(true,index); }


template <class _Iter> _CONSTEXPR20_CONTAINER void _Assign_range( _Iter _First, _Iter _Last, forward_iterator_tag) { // assign forward range [_First, _Last) const auto _Newsize = _Convert_size<size_type>( static_cast<size_t>(_STD distance(_First, _Last))); auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; pointer& _Myend = _My_data._Myend; _My_data._Orphan_all(); if constexpr (conjunction_v<bool_constant< _Ptr_copy_cat<_Iter, _Ty*>::_Trivially_copyable>, _Uses_default_construct<_Alty, _Ty*, decltype(*_First)>, _Uses_default_destroy<_Alty, _Ty*>>) { #ifdef __cpp_lib_constexpr_dynamic_alloc if (!_STD is_constant_evaluated()) #endif // __cpp_lib_constexpr_dynamic_alloc { const auto _Oldcapacity = static_cast<size_type> (_Myend - _Myfirst); if (_Newsize > _Oldcapacity) { _Clear_and_reserve_geometric(_Newsize); } _Mylast = _Refancy<pointer>(_Copy_memmove(_First, _Last, _Unfancy(_Myfirst))); return; }

Dense unreadable,
unusable, mess...
unusable, mess...

Simple consistent discoverable generic interfaces.
using namespace Hero; Result<bool,int> res; Array array<int>; res = array.Insert(5); Map map<int,int> res = map.Insert(5); Set set<int>; res = set.Insert(5); // In each case above you can assert true as the result // type is always the same i.e. Assert(res); void ForEach(Iterable<int> & iter) { Iterand<int> it = iter.Forward(); while (it) { Print("%d",it()); ++it; } } // Forward/Reverse iteration is possible for any type, // defaults to value iterator for maps. ForEach(array); ForEach(map); ForEach(set); // Trivial to handle iteration from upper/lower bound // since map's are integer indexed int index = map.Index(5); while (index < map.Length()) { ++index; }

Unintuitive inconsistent viral template interfaces with buggy undefined behavior.
// Note the due to the lack of case differentiation we // can't use std namespace and must qualify everything // if we wish to use the keyword "vector" std::vector<int> vector; vector.push_back(5); // No consistent result type so there is no way to chain // calls or write generic algorithms. assert(vector.size()); // Auto can hide some of the ugly "syntax" but it doesnt // hide the bad "design" std::map<int,int> map; std::pair<std::map<int,int>,bool> res = map.insert(5); assert(res.second); std::set<int,int> set; std::pair<std::set<int,int>,bool> res = set.insert(5); assert(res.second); // There is no way to implement generic algorithms, // everything must be a template to use type traits, and // even then the iterable types are entirely different. template<typename T> void ForEach(T & t) { T::iterator it = t.begin(); while (it != t.end()) { // Does not work with std::map, it iterates a pair printf("%d",*it); } } ForEach(vector); ForEach(map); // Compiler error ForEach(set); // Compiler error std::map<int,int>::iterator it = map.lower_bound(5); while(it != map.end()) { // Undefined behavior/segfault, std::next/prev don't // invalidate out of range iterators. it = std::next(it); }
Visible public variables and implementation details debuggable with graphical UI
_Value_ & operator [] (_Key_ && key) { Keys.Append((_Key_&&)key); int index = Idx.Select(Keys.Size-1); if (index != -1) { // Cleanup any resources that may have been used Keys[Keys.Size-1] = _Key_(); --Keys.Size; return Values[index]; } Values.Append(_Value_()); index = Keys.Size-1; Idx.Insert(index); return Values[index]; }


Obfuscated implementation details, not debuggable without printf/stderr and text output
templatepair<_Nodeptr, bool> _Try_emplace(_Keyty&& _Keyval, _Mappedty&&... _Mapval) { const auto _Loc = _Mybase::_Find_lower_bound(_Keyval); if (_Mybase::_Lower_bound_duplicate(_Loc._Bound, _Keyval)) { return {_Loc._Bound, false}; } _Mybase::_Check_grow_by_1(); const auto _Scary = _Mybase::_Get_scary(); const auto _Inserted = _Tree_temp_node<_Alnode>(_Mybase::_Getal(), _Scary->_Myhead, piecewise_construct, _STD forward_as_tuple(_STD forward<_Keyty>(_Keyval)), _STD forward_as_tuple(_STD forward<_Mappedty>(_Mapval)...)) ._Release(); // nothrow hereafter return {_Scary->_Insert_node(_Loc._Location, _Inserted), true}; }
