Orthodox C++ (sometimes referred as C+) is minimal subset of C++ that improves C, but avoids all unnecessary things from so called Modern C++. It's exactly opposite of what Modern C++ suppose to be.
Back in late 1990 we were also modern-at-the-time C++ hipsters, and we used latest features. We told everyone also they should use those features too. Over time we learned it's unnecesary to use some language features just because they are there, or features we used proved to be bad (like RTTI, exceptions, and streams), or it backfired by unnecessary code complexity. If you think this is nonsense, just wait few more years and you'll hate Modern C++ too ("Why I don't spend time with Modern C++ anymore" archived LinkedIn article).
Code base written with Orthodox C++ limitations will be easer to understand, simpler, and it will build with older compilers. Projects written in Orthodox C++ subset will be more acceptable by other C++ projects because subset used by Orthodox C++ is unlikely to violate adopter's C++ subset preferences.
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
- C-like C++ is good start, if code doesn't require more complexity don't add unnecessary C++ complexities. In general case code should be readable to anyone who is familiar with C language.
- Don't do this, the end of "design rationale" in Orthodox C++ should be immedately after "Quite simple, and it is usable. EOF".
- Don't use exceptions.
Exception handling is the only C++ language feature which requires significant support from a complex runtime system, and it's the only C++ feature that has a runtime cost even if you don't use it – sometimes as additional hidden code at every object construction, destruction, and try block entry/exit, and always by limiting what the compiler's optimizer can do, often quite significantly. Yet C++ exception specifications are not enforced at compile time anyway, so you don't even get to know that you didn't forget to handle some error case! And on a stylistic note, the exception style of error handling doesn't mesh very well with the C style of error return codes, which causes a real schism in programming styles because a great deal of C++ code must invariably call down into underlying C libraries.
- Don't use RTTI.
- Don't use C++ runtime wrapper for C runtime includes (
<cstdio>
,<cmath>
, etc.), use C runtime instead (<stdio.h>
,<math.h>
, etc.) - Don't use stream (
<iostream>
,<stringstream>
, etc.), use printf style functions instead. - Don't use anything from STL that allocates memory, unless you don't care about memory management. See CppCon 2015: Andrei Alexandrescu "std::allocator Is to Allocation what std::vector Is to Vexation" talk, and Why many AAA gamedev studios opt out of the STL thread for more info.
- Don't use metaprogramming excessively for academic masturbation. Use it in moderation, only where necessary, and where it reduces code complexity.
- Wary of any features introduced in current standard C++, ideally wait for improvements of those feature in next iteration of standard. Example
constexpr
from C++11 became usable in C++14 (per Jason Turner cppbestpractices.com curator)
Due to lag of adoption of C++ standard by compilers, OS distributions, etc. it's usually not possible to start using new useful language features immediately. General guideline is: if current year is C++year+5 then it's safe to start selectively using C++year's features. For example, if standard is C++11, and current year >= 2016 then it's probably safe. If standard required to compile your code is C++17 and year is 2016 then obviously you're practicing "Resume Driven Development" methodology. If you're doing this for open source project, then you're not creating something others can use.
UPDATE As of January 14th 2022, Orthodox C++ committee approved use of C++17.
- Embedded C++
- Nominal C++
- Sane C++
- Why Your C++ Should Be Simple
- C++, it’s not you. It’s me.
- "Keep It C-mple" Alexander Radchenko Sydney C++ Meetup
- A dialect of C++
- Any C source that compiles with C++ compiler.
- DOOM 3 BFG
- Qt (when built with no-rtti, no-exceptions)
- dear imgui
- bgfx
- TheForge
- Oryol
- Network Next SDK
That is just very wrong. Why do you return
std::unique_ptr<T>
instead of just returningT
? OOP Abuse?Yes, they DO have issues with things like this. Google just benchmarked the abi issue with std::unique_ptr being not moved. They observed 1.6% performance lost in MACRO (not micro) benchmarks. (Without even considering things like this.) Yes, using unique_ptr is a huge performance bug.
Freestanding isn't any special case. In fact, over 95% of devices are embedded devices. C++ the language is totally misdesigned for environments in basically any environment, particularly embedded and kernel. Linus Torvalds is totally correct. C++ is terrible for the kernel because C++ was never designed for the environment it should be used.
That paper already proves WG21 is a joke and why you need orthodox C++, not modern C++. WG21 cares about adding security bugs like std::filesystem, std::format but ignoring the reality modern C++ is terrible for basically everything. They have a very bad priority on doing things.
https://www.youtube.com/watch?v=zozo8b7-nsw
When will be a working compiler for herbceptions??
When will be their fix to iostream? They really need to remove that and replace it with something else like fast_io instead. It is funny entire WG21 committee cannot find a solution for fixing iostream compared to one single person.
https://youtu.be/CefgZlXeMUg?t=1055
In fact, C++ is so problematic even for environments like wasm due to the lack of support of EH. I recently compile C++ to Lua, I would argue C++ EH would forever be an implementation issue that is totally unusable.
'''
Only if you pull in std::make_unique. Even std::default_delete doesn't necessarily do pull it in either since it can work with a specialization of delete that does not use an actual heap.
'''
Those are already very bad. Ben Craig has said those things like heap won't be freestanding. You do not understand how things work at all tbh.
In embedded systems, you usually do not have a heap. You might argue you can add a heap to that. (I am sure embedded folks won't due to non-deterministic the heap introduces)
However, In the kernel, they usually have multiple heaps.
Windows kernel, for example, they have two heaps. One is interrupt-safe, another is none interrupt-safe. Assuming default to any of them is just totally wrong. Forcing a global default new is just impossible.
Not mentioning other issues like how to report allocation failures. If they said those facilities should just fail fast and make global operator new being noexcept, it would probably be better. However, there will be big company morons who whine about "our programs are too important, it cannot crash for some other shit"
Similar things like floating point, although CPU does provide floating-point facilities, using floating-point will force the OS kernel to save XMM registers for syscalls. That slows down syscall performance, making using floating-point not possible either.
I would argue only std::array (without at method) and std::span could be in the freestanding. (Yes, i see them as disasters too)
std::optional and std::string_view are designed in the way using EH for reporting logic_error too much, which makes them totally useless.