c++ criticism
some of these issues are inherent from c, some are unique to c++ and most have been solved in more recent languages like rust and go.
- no reference compiler
- no standard build system
- multiple -sometimes more than 10- ways to do the same thing (see the infamous struct initialization gif)
- no standard project structure, multiple ways to provide a library
- multiple ways to consume a library
- header only, separately compilable source
- even more tragic with c++20 modules
- in many cases consuming a thirdparty library will require an intermediate step between grabbing the source and using it from code (ex: openssl)
- absence of directory structure convention lead to the question: should I write
-Ithirdparty/mylib
,-Ithirdparty/mylib/include
or-Ithirdparty/mylib/src
?
- function overloading combined with implicit type casting is a recipe for disaster
- can be solved by things like
-Wconversion -Werror
but again non cross-platform solution that requires extra knowledge that is not explicitly documented as a solution for that specific problem
- can be solved by things like
- multiple methods for error reporting
- each function in std::filesystem has at least two declarations, one that throws exceptions and one that does not
- exceptions can be used at panic situations but can you guarantee that libraries that you use do the same thing ?
- no UTF-8 support provided by the language, for example: iterate code points of a string instead of iterating bytes
- painful to navigate through standard library source code in most implementations
- painful to get something useful from error messages for code that uses templates
- language provided way of printing text is massively outperformed by thirdparty libraries (see libfmt), happens at other tasks as well, in a language marketed with the term "zero cost abstraction"
- must type a function signature twice if you want to have a separate compilation unit for it (inherent from c)
- no reflection support (at least without doing nasty hacks), reflection makes it easy to implement:
- pretty printing
- serialization and deserialization
- for cross program communication
- for saving and loading configuration or primitive data
- ORM libraries
- relatively hard to cross compile
- relatively hard to produce a binary that is cross-linux-distribution portable
- libc compatibility
- statically vs dynamically linked libstdc++ issues
community approved way of building programs and providing libraries is in fact cmake
- it does not build your code but generates a build configuration that is specific to build tools and compilers, because it was too late to force compilers to support a set of flags/arguments and hence too difficult to interact with compilers directly
- generated configuration (just like any computer generated code) is unreadable
fails to unify the experience of having some options in a cross-environment way, ex:
- having debug symbols in a separate file other than actual program
- linking statically against standard library
- specifying build type in a cross platform way (release/debug)
cmake . -Bbuild && cmake --build build/ --config Release # vcxproj cmake . -DCMAKE_BUILD_TYPE=Release -Bbuild && cmake --build build/ # makefile
procedural language instead of an easy to play with declarative configuration
cmake does not check CMakeLists.txt for misplaced, duplicate or no-effect options
has IDE specific project generators, while this can be handy it puts an extra burden on cmake development
- build config should be simple enough that a basic parser can extract code analysis information from it
advantage:
- most good software is written in c and it is relatively easy to interact with c from c++ and start adding light weight abstractions