Despite the C++ Standard Library having 13 articles worth of content, there’s still quite a bit that it doesn’t contain compared to what’s available in C#’s .NET libraries. Today we’ll look at some of those gaps and see how to fill them.

Table of Contents

Overview

The .NET library for C# is truly gigantic. It covers an extremely wide-ranging set of functionality for a programming language’s standard library. Even other “batteries included” languages like Python and Java have nowhere near as much functionality as .NET does. It absolutely dwarfs the C++ Standard Library, which has historically limited itself to truly core functionality that can be applied to virtually any computing device, is extremely mature, and can be achieve consensus in a large, diverse standards committee. .NET, being controlled by Microsoft, includes a great many features that are specific to Microsoft Windows, the platforms it happens to run on, and the technologies it encourages using.

As a result of this, C# developers have a ton of general-purpose tools such as for JSON serialization but also a ton of tools such as access to GDI+ that will most likely not apply to any code we write. We can ignore them, but it makes providing an implementation of .NET on non-Windows platforms more difficult and therefore less likely to be accomplished and available. .NET itself has fractured into a collection of overlapping libraries which may or may not be available on any given platform: .NET Framework, .NET Core, .NET Compact Framework, .NET Micro Framework, Microsoft Silverlight, Mono, and Unity. Some of these are deprecated and others have been renamed but there are still broad gulfs between libraries like .NET Core and Unity.

Like the C++ language itself, the C++ Standard Library is a standard. There are various implementations of the standard, but they all have approximately the same features. Variance between them is mostly in the form of unspecified behavior such as exception message strings and deviances from the standard such as adding or removing some (usually relatively-minor) features. This is especially true in newly-released standards such as C++20 at the time of writing.

In a way the comparison between the two languages’ standard libraries is a bit apples-to-oranges, but today we’ll look at some of the high-level sorts of functionality a C# developer using one of the .NET libraries won’t find in the C++ Standard Library.

Cryptography

The System.Security.Cryptography namespace provides C# programmers with access to many common cryptographic algorithms including AES, RSA, and the SHA family. The System.Net.Security namespace provides TLS and SSL.

The C++ Standard Library doesn’t have any cryptography functionality built in, so we seek other libraries to provide the needed functionality. Thankfully, we can make easy use of C libraries as well as C++ libraries so we have many options. Here are a few of them:

Library Language License Crypto Algorithms TLS and SSL
Botan C++ BSD Yes Yes
OpenSSL C Apache Yes Yes
Crypto++ C++ Boost Yes No
libsodium C ISC Yes No
Compression

In C#, we use the System.IO.Compression to access compression algorithms such as GZip and Deflate as well as ZIP archives. Again, we turn to non-standard libraries when we need compression functionality with C++. Here are a few:

Library Language License Algorithms
zlib C zlib GZip, Deflate
Zipper C++ MIT ZIP
LZ4 C BSD LZ4
LZMA SDK C and C++ Public Domain LZMA, LZMA2
Networking

System.Net provides access to low-level sockets and WebSockets while sub-namespaces provide higher-level functionality. For example, System.Net.Http provides HTTP functionality such as a client: HttpClient.

Proposals have been made to add networking functionality to the C++ Standard Library, but so far haven’t been accepted. While we wait for standardization, we can make use of many existing libraries including these:

Library Language Licence Protocols
Boost.Asio C++ Boost TCP, UDP, ICMP, serial ports, UNIX sockets, Windows HANDLE, SSL (via OpenSSL)
Boost.Beast C++ Boost Via Boost.Asio and OpenSSL: HTTP (client and server), WebSocket (client and server)
cpp-httplib C++ MIT HTTP (client and server)
WebSocket++ C++ BSD WebSocket
Graphical User Interfaces

.NET has built-in support for three Windows GUIs: GDI+ in System.Drawing, Windows Forms in System.Windows.Forms, and Windows Presentation Foundation in System.Windows. While not part of .NET, Microsoft makes Xamarin available for cross-platform GUI development on Windows, macOS, Linux, Android, and iOS but not web browsers.

C++ has no built-in GUI support, but can access Windows Forms and Windows Presentation Foundation via C++/CLI. Quite a few libraries are also available for cross-platform GUI development:

Library Language Licence Windows macOS Linux Android iOS Web Browser
Qt C++ LGPL, GPL, Commercial Yes Yes Yes Yes Yes Yes
GTK+ C LGPL Yes Yes Yes
wxWidgets C++ wxWindows Yes Yes Yes
Dear ImGui C++ MIT Yes Yes Yes Yes Yes Yes
CPU Intrinsics

System.Runtime.Intrinsics and its sub-namespaces System.Runtime.Intrinsics.X86 and System.Runtime.Intrinsics.Arm contain “intrinsics” for x86 and ARM CPUs. These are functions whose calls are translated by the compiler directly into a named CPU instruction. They provide low-level control without needing to resort to assembly code.

C++ doesn’t have standardized intrinsics, but they’re widely available:

JSON

The JSON format is supported directly by .NET in the System.Text.Json namespace. The C++ Standard Library doesn’t directly support this format or any others, so we instead make use of libraries:

Library Language License
JSON for Modern C++ C++ MIT
RapidJSON C++ MIT
JsonCpp C++ MIT
Boost.JSON C++ Boost
Debugging

The System.Diagnostics namespace in .NET provides some useful debugging features. For example, we can use Debugger.Break to break an interactive debugger. There’s also the StackTrace class to get stack traces, especially when we run into problems.

C++ doesn’t provide either of these in its Standard Library, but we can still access them. To break an interactive debugger on Windows, we #include <debugapi.h> and call the DebugBreak function. On UNIX systems, we #include <signal.h> and call the raise function with SIGTRAP as the argument.

Support for stack traces has been proposed for the Standard Library, but we’ll have to wait until at least C++23 for it to be adopted. For now, the Boost-licensed Boost.Stacktrace library that the Standard Library proposal is based on is available to fill the gap.

Database Clients

The System.Data goes as far as to build in support for particular databases. System.Data.SqlClient is a client for Microsoft SQL Server and System.Data.OracleClient is a client for Oracle Database.

The C++ Standard Library never endorses particular software products like these, so it has zero support for databases. Instead, Database vendors typically provide a C++ client, connector, or driver:

Library Language License Database
ODBC Driver for Microsoft SQL Server C Commercial Microsof SQL Server
Oracle C++ Call Interface C+++ Commercial Oracle Database
MySQL Connector C++ GPL or Commercial MySQL
MongoDB Driver C++ Apache MongoDB
Conclusion

The .NET family of standard libraries for C# often take a different design approach to the C++ Standard Library. They’re much more comfortable building in support for particular software such as Oracle Database. They’ll add OS-specific functionality such as to build GDI+ user interfaces. They’ll also add CPU intrinsics that are specific to particular processor architectures such as x86 and ARM.

The C++ Standard Library is designed in a more abstract way. It doesn’t choose to support any particular database, OS, processor, algorithm, or data format. We’ll simply have to look outside of the standard if we want any functionality related to a concrete software or hardware product.

The area of overlap between .NET and the C++ Standard Library relates to general tools such as collections and file system access. Sometimes the C++ Standard Library has more available here, such as with its doubly-ended queue type. Other times .NET has more available, such as with its ability to break an interactive debugger or open a network socket. These tools could be added to the C++ Standard Library in the future, but for now we need to employ other libraries to get access to them.