C++ For C# Developers: Part 51 – Missing Library Features
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
- Part 1: Introduction
- Part 2: Primitive Types and Literals
- Part 3: Variables and Initialization
- Part 4: Functions
- Part 5: Build Model
- Part 6: Control Flow
- Part 7: Pointers, Arrays, and Strings
- Part 8: References
- Part 9: Enumerations
- Part 10: Struct Basics
- Part 11: Struct Functions
- Part 12: Constructors and Destructors
- Part 13: Initialization
- Part 14: Inheritance
- Part 15: Struct and Class Permissions
- Part 16: Struct and Class Wrap-up
- Part 17: Namespaces
- Part 18: Exceptions
- Part 19: Dynamic Allocation
- Part 20: Implicit Type Conversion
- Part 21: Casting and RTTI
- Part 22: Lambdas
- Part 23: Compile-Time Programming
- Part 24: Preprocessor
- Part 25: Intro to Templates
- Part 26: Template Parameters
- Part 27: Template Deduction and Specialization
- Part 28: Variadic Templates
- Part 29: Template Constraints
- Part 30: Type Aliases
- Part 31: Destructuring and Attributes
- Part 32: Thread-Local Storage and Volatile
- Part 33: Alignment, Assembly, and Language Linkage
- Part 34: Fold Expressions and Elaborated Type Specifiers
- Part 35: Modules, The New Build Model
- Part 36: Coroutines
- Part 37: Missing Language Features
- Part 38: C Standard Library
- Part 39: Language Support Library
- Part 40: Utilities Library
- Part 41: System Integration Library
- Part 42: Numbers Library
- Part 43: Threading Library
- Part 44: Strings Library
- Part 45: Array Containers Library
- Part 46: Other Containers Library
- Part 47: Containers Library Wrapup
- Part 48: Algorithms Library
- Part 49: Ranges and Parallel Algorithms
- Part 50: I/O Library
- Part 51: Missing Library Features
- Part 52: Idioms and Best Practices
- Part 53: Conclusion
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:
- Microsoft Visual Studio
- Intel Intrinsics Guide
- GCC Builtins including intrinsics
- ARM NEON Intrinsics
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.