Orthodox C++
What is Orthodox C++?
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.
Why not Modern C++?
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).
Why use Orthodox C++?
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.
Hello World in Orthodox C++
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
What should I use?
- 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)
Is it safe to use any of Modern C++ features yet?
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.
Any other similar ideas?
- 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++
Code examples
- 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
Why ? It doesn't make it any easier than
T *
...Welp, you do have a point here. I actually already knew about this, and it is true that
std::unique_ptr
has found itself disadvantaged by the Itanium ABI, although this is more of an implementation-specific issue than anything else, and the link you gave is about the solution to that, so... (note: I was objecting to your old statement because considering the way you formulated it, you appeared to be specifically arguing that the performance problems were caused by one-line methods in headers)I mean, your point about format strings is interesting, but it seems odd to specifically bash C++ for adding format strings that are nicely usable in C++ code when this is something that has been done by most languages out there...
Also, the log4j format string vulnerability isn't exactly something inherent to format strings... the way I see it, the vulnerability is basically like if
%s
in printf would execute its operand as a shell command if it starts with${system:
or something stupid like that. It's not something inherent to format strings and I could very easily see it happening outside of there.. certainly Log4j could have had the same vulnerability without using a format string (i.e. iflog.info("something '{}'.\n", userControlled)
is vulnerable, I see no reason why an identical API except made without format strings wouldn't find itself just as much vulnerable when people dolog.info("something '", userControlled, "'.\n")
...).Well I apologize for the misunderstanding then, the way you formulated it seemed to imply otherwise. I actually do share most of your grievances with iostream btw, I certainly do consider it to generally be pretty shit (although I have some major doubts about
fast_io
being the magic solution to it all...)??? Under what environment would you see that happen ? If you accidentally link in the entire libc to your kernel or something like that you're gonna have much bigger problems than this...
Giving examples of obviously stupid usages of
unique_ptr
isn't gonna break it... in the same way I could say something like "usingswitch
is always just wrong" on the basis of the massive amount of "oops forgot a break" fuckups.You could also just, yunno, have the standard say that the toolchain
#ifdef
s out the exception-throwing methods when in freestanding mode... If the standard added such a thing (which is what P0829 is proposing) you'd be able to easily check if you've accidentally used the forbidden functions by compiling in freestanding mode (should be easy enough if you're writing a library intended for that kind of usage), which would directly give you an explicit "unknown method" error while compiling the offending TU.