Zero To Hero! ...
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.
  • 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
Discord   YouTube    Github 


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.

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)
Hero::Map<>
Peak: 171 (mb)
Time: 0.291 (s)
Wins by 72 (ms)
std::unordered_map<>
Peak: 203 (mb)
Time: 0.579 (s)
Hero::Hash<>
Peak: 202 (mb)
Time: 0.345 (s)
Wins by 231 (ms)


Clean readable, reusable,
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...



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


  • template 
    pair<_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};
    }