c++ without the standard library & should you do it?

I love C. What's there not to love about this language, it's fast — mostly can be 1-1 translated into native code, portable and it's minimalist — you don't need to learn all these newfangled language constructs like those in Java, with C you can learn the syntax in a day or less. However, C has major limitations as a modern language, there's no native support for classes (you'd have to do long function declarations in order to get methods, and forget about property access protection lest you hack it in), there's no native support for automatic memory management like smart pointers or garbage collection (though BoehmGC can do that) and don't get me started on the ancient macro system — which is basically a wrapper of the Find-Replace function in text editors.

This is probably why C++ was created. All of which I mentioned earlier had been solved, with actual runtime classes, smart pointers through <memory> header and templates allowing for easier code generation. Of course, this all comes with a cost, compiling takes a lot longer, in fact, here are the hard numbers when for a simple Hello World program:

Language Code Time
C
#include <stdio.h>
int main() {
printf("Hello World\n");
return 0;
}
> time /bin/cc -o a a.c
real 0m0.053s
user 0m0.053s
sys 0m0.000s
C++
#include <iostream>
int main() {
std::cout << "Hello World\n";
return 0;
}
> time /bin/c++ -o a a.c
real 0m0.523s
user 0m0.471s
sys 0m0.052s

Most of this is due to the standard library's (in my case GNU's) headers — which heavily use templates and are highly dependent on each other. In addition, stdlib classes have deep inheritance trees, when they don't really need to be. If you just count the number of lines of the source files post-processed, you end up with 28257 lines for C++, as opposed to 719 lines for C. No wonder it's 10x faster to compile in C than in C++.

Enter Orthodox C++

"Orthodox C++ is a minimal subset of C++ that improves C, but avoids all unnecessary things from so called Modern C++." Simply put, it's C++, but you can't use RTTI (runtime type information), exceptions or anything in the C++ stdlib, only the C standard library with modern C++ language features sprinkled in. Is it perfect for my use? Let's find out by writing a simple HTTP request application.

There is no good way of compiling C++ without the standard library in GCC, unless you disable all the linker flags and add your own. I ended up compiling the program by using g++ to generate object files and gcc to link it all together.

To allocate/deallocate memory on the heap, you'd have to call malloc and free in C. There's none of that in C++ of course, you have to use the new and delete operators. To fix this, you can simply shim the functions by aliasing operator new and operator delete to malloc and free respectively. (thanks pts.blog)

One thing to note that there's no standardized data structure library for C, so you can't just create a class wrapper around some functions and call it a day. Sure, there are BSD macros, however it doesn't seem too integrated with C++, you might as well write C at that point. So I decided to rewrite the standard library, well the part of the standard library that I would be using that is. I've implemented classes for std::vector, std::string and std::unique_ptr. I decided not to write classes for std::cout since the printf family does all I want to. This is also an incorrect implementation of the standard, for instance, std::string is just an std::vector<char>, however, it will work for most common uses.

And lo and behold, here's my code! Nothing to fancy, it can just pull any file from an HTTP(s) server.

To run it, simply do, for instance:

./main https://www.google.com

Some numbers

Here are some raw numbers for you to gauge at. First, compile time.

Orthodox C++

This uses a custom (possbily incorrect) standard library implementation, and uses stdio.h

> time m -B main CC=/bin/cc CXX=/bin/c++
/bin/c++ -g -c -o main.o main.cpp -fno-rtti -fno-exceptions -nostdinc++ -Wall -O3
/bin/cc -s -g -o main main.o -lssl -lcrypto
real 0m0.670s
user 0m0.633s
sys 0m0.037s

C++

This version uses the pure standard C++ library, and uses iostream instead of stdio.h

> time /bin/g++ -s -o main1 main1.cpp -Wall -O3 \
-lssl -lcrypto -static-libstdc++ -fno-rtti -fno-exceptions
real 0m1.280s
user 0m1.094s
sys 0m0.186s

The orthodox version is 1.91x faster than the pure version. What about file size then?

Orthodox C++

> stat main
File: main
Size: 18808 Blocks: 56 IO Block: 4096 regular file

C++

> stat main1
File: main1
Size: 944960 Blocks: 1864 IO Block: 4096 regular file

18808 bytes compared to 944960 bytes. 50x smaller.

Conclusion

So should I do orthodox C++ instead of C++? The answer is, it depends. If you want to write embedded or really small software for C++, then by all means, disable those unnecessary language features and write a custom stdlib. However, if you just want to get things done, then use pure C++. For me, Orthodox C++ is kind of like a middle ground between low and high level C++, just enough to write fast software in, and just enough for it to be safe.