thewolfsound.com
Why C++ Sometimes Sucks: 17 Reasons Why C++ Development Is Difficult | WolfSound
Excerpt
## Biggest pains of C++ development - Compiler support is lagging behind the standard on certain platforms. - Example: as of July the 3rd, 2024, Apple Clang still doesn’t support std::expected, `std::jthread`(joinable thread), or `std::stop_token`. … - It’s hard/impossible to write C++ modules cross-platform. - Slow compilation of templates. - Poor compiler messages, especially when using templates. C++ concepts help but there they still require a lot of effort to be understood on compilation error. Rust is better at this. - No standard dependency management. - Using Conan or vcpkg is difficult. - CPM package manager is the most promising and least difficult to set up. Check out my tutorial on JUCE with CPM setup. - No standard “recipes” to build 3rd-party libraries; each has custom build. - It’s hard to predict if a third-party library will run on all platforms: Windows, macOS, Linux, Android, and iOS. It’s simply too difficult for most library developers to test. - Third-party libraries warnings are not easy to suppress on all platforms. - Unchecked memory access is very easy to do. - Out-of-range access. - Memory leaks. - Double delete. - Use after delete/move. - Macros are confusing. It’s easy to hurt yourself. - Poor linting. C++ linters often get lost because of transitive inclusion of header files. … - Fortunately, there are libraries that provide the missing pieces like the Boost library or the JUCE C++ framework. - Strings and UTF-8 string handling surprisingly difficult. The library support for UTF-8 emerges just now. - There isn’t a standard way of structuring multithreaded-code. - C++ coroutines are complex to understand and use.
Related Pain Points
Unchecked memory access leads to silent bugs
8Out-of-range access on containers like vectors is not checked at runtime by default, unlike Java. Without explicit `.at()` calls, array access bugs silently corrupt memory.
C++ modules cross-platform support is broken
7C++20 modules were introduced but cross-platform support remains extremely limited and too complicated for average developers. Existing implementations lack practical usability.
No standard package management system
7C++ lacks a standard dependency manager like Rust's Cargo or Python's pip. Solutions like Conan and vcpkg are difficult to use; CPM is more promising but not standard.
Template compilation is slow
7Templates in C++ are compiled slowly, adding significant overhead to build times, especially problematic when templates must be defined in headers.
Poor compiler error messages for templates
6C++ compiler messages are unhelpful when template code is incorrect, making debugging difficult. C++20 concepts help but require significant effort to understand.
Difficult to suppress third-party library warnings
6When using strict compiler warning settings, third-party libraries often generate warnings that are hard to suppress across all platforms. Transitive header inclusions make it nearly impossible to silence warnings in external code.
Compiler support lags behind C++ standard
6Popular compiler implementations like Apple Clang lag years behind standard releases. As of July 2024, Apple Clang lacks std::expected, std::jthread, and std::stop_token, forcing developers to work around missing features.
Third-party library platform support is unpredictable
6It's difficult to determine if a third-party library will work across all target platforms (Windows, macOS, Linux, Android, iOS). Libraries rarely provide guarantees due to ecosystem volatility.
C++ coroutines are too complex to use
6Coroutines in C++ are complex to understand and use in practice, with poor documentation and limited adoption despite being standardized.
Macros are confusing and error-prone
5Macros are powerful but extremely tempting to misuse, especially for newcomers. They remain widely used throughout codebases despite their difficulty and propensity to introduce hard-to-find bugs.
No standard multithreading patterns
5There is no standardized way to structure multithreaded code in C++, leaving developers to create bespoke solutions.
Difficult string and UTF-8 handling
5String manipulation in C++ is cumbersome and lacks convenience functions. UTF-8 support is only now emerging in the standard library after years of using workarounds.