The alternative would be to rely on void* for all data types,
which was really nicely presented in Mastering Algorithms with C by Kyle Loudon, but after working through it the lack of type safety for even basic types was a huge pain.
At least with a bit of pre-processor magic, type safety and contiguous data is promised. Also, getting crafty with precompiled headers, one could dump all the expansions into a single templates.h, compile a .gch, and reap the benefits of hundreds of containered types with instantaneous compile times.