5 ms·
The C++ preprocessor doesn’t understand anything about C++, including templates
- adrianN 6y agoThe preprocessor is a really horrible hack of a macro system. I wish we could get rid of it and replace it with something sensible, but I doubt that will ever happen.
- pjmlp 6y agoIn C++ there is very little that we still need it for. Even for conditional compilation I have always been a fan of using module_os_arch.cpp than dealing with pre-processor spaghetti. The tools are there, the problem is getting people to use them instead of doing C like coding, assuming access to C++17/20 compilers. As for C, well I don't have high hopes that when WG14 doesn't care about improving security, they will ever do anything regarding the pre-processor, specially since it is such a crucial part of C development.
- Gibbon1 6y ago> Even for conditional compilation I have always been a fan of using module_os_arch.cpp than dealing with pre-processor spaghetti. That's what's come down to doing in the firmware I write in C. Has the advantage that you don't need to worry as much about other platforms when dicking with platform specific code. With preprocessor spaghetti it's really easy to break other platforms otherwise. That results in most of preprocessor usage is just switching include files.
- Gupie 6y agoWhat do you mean by "module_os_arch.cpp"? I cannot find any references to it or anything similar?
- michal_f 6y agoI suppose Op meant separating architecture dependant code to different cpp files and use build system to select right one.
- pjmlp 6y agoAs good practice from my Turbo Pascal days, I always consider a translation unit as being a module/unit/package/..., hence module. So lets say you have usb module to talk with USB devices. It would be composed of the following files: - usb.h and usb.cpp for the public interface and os agnostic code, including function declarations for the OS specific parts. - usb_windows.cpp, usb_linux.cpp, ... for OS specific code - usb_windows_x86.cpp, usb_windows_arm.cpp,... for inline Assembly, intrisics or hardware specific data structures. Then you get Make, CMake or whatever is your favourite build tool to combine those files depending on the build target. Pre-processor usage for OS specific code always starts easy on the beginning, but when you look at a bunch of files with 20 years of history and continuous change by consulting companies you need several days just to understand what is actually being generated when dropped into a random code base. This way is it much easier to navigate across the code. It is also the approach adopted by Go, and a couple of other languages without direct support for pre-processors.
- knorker 6y ago> I have always been a fan of using module_os_arch.cpp Oh no, I found that to work very very poorly. It's an antipatterns because architectures change, and that you can't cover all architectures. Not only for my own software (I've maintained portable open source for decades across many architectures), but also huge frustration when porting software to a new (for that software) architecture. Examples: The software should not care if it's "linux" or "freebsd", you care if getpwnam_r is the three or four argument version. When one OS changes (or admin tweaks it) to the POSIX compliant API by default, what do you do then? OpenBSD is API wise close to FreeBSD. So now I should find all files named ._freebsd_. and make a copy to _openbsd_, forking the code, if I port to OpenBSD? What about Debian kFreeBSD? You don't have all of these OSs, so just test features, not OS.
- jstimpfle 6y agoI think the general idea is simply that you don't use #ifdef but instead move the conditional compilation logic to the build script / build system. Of course you should group in files in a way that avoids redundancy. This is the way I'm going about it at least, even though I assume there might be complex situations where the boilerplate isn't warranted and it's better to put all the variants in a single file and use the preprocessor to determine which alternative to compile. Like you say in the end, test features (or maybe standards support), not too-specific things like OS or distribution.
- pjmlp 6y agoYep, this is something we can definitely agree on. :)
- knorker 6y ago> the general idea is simply that you don't use #ifdef but instead move the conditional compilation logic to the build script / build system. Yes, I entirely agree. But do NOT split it into what OS or architecture it is, like what I was replying to said.
- pjmlp 6y agoTry to debug a 10 level depth of nested #ifdef, across a 10000+ lines source code file, managed by unknown number of consulting companies paid by the tickets thought 20 years of company history without any kind of code review processes and you will get in love with such anti-patterns. Naturally one has to make the groupings in a way that makes sense, and the code organisation is not set in stone. Refactorings can and should be done when it makes sense to do so.
- cozzyd 6y agoI once saw someone suggest using PHP as a C preprocessor, which is hilarious in a way.
- burfog 6y agoThere are other choices: #script javascript // put your script here, have it change the parse tree, etc. #endscript Microsoft compilers could support VBscript. High-performance options include webassembly, the JVM, and the .net runtime.
- makapuf 6y agoWould be nice to allow it in gcc/clang in a standard way to access the parse tree. In C even maybe ?
- makapuf 6y agoYes, the main issue is not the language its the Revel at which it operates (text vs tokens or ast) What I wouldn't mind is more widespread adoption of other preprocessing steps, in whatever language, be it scheme or python.
- zbuf 6y agoI'm using the C preprocessor as a preprocessor to JSON, also hilarious. But whoever thought a language with no comments was a good idea -- means I can actually write comments in JSON files.
- flukus 6y ago> I wish we could get rid of it and replace it with something sensible Getting rid of it is hard, but replacing many uses of it with a more capable codgen/templating your definition of sensible is very simple, just a make rule or two.
- flohofwoe 6y agoThe preprocessor is fine if you use it as intended: simple text replacement and conditional compilation. Just don't use it for anything where code generation or generic programming is better suited.
- gumby 6y agoC++ templates were an attempt to put a real macro system into the C matrix. Over the last decade it’s finally become usable. But the baroque representational absurdities of C and it’s related languages make it always feel like standing on your head under water.
- mehrdadn 6y agoJust a PSA, but if the parenthesis solution doesn't work for you, you can define a COMMA macro and use it there (while everyone yells at you).
- Robadob 6y agoWe've come across this problem. The major testing frameworks seem to rely heavily on macros for tests. In particular, we were struggling to handle tests of thrown exceptions, as we couldn't trivially capture the result in a variable and place that inside the macro instead. The most versatile solution we found was to use a function pointer, so that the templating wasn't required when the function was called.
- PunksATawnyFill 6y agoMacros are inscrutable garbage and a sorry hack.
- Wowfunhappy 6y ago> The C and C++ preprocessors are like the Windows command prompt batch language: They implement a very simple language that people still use for some reason. I can tell you exactly why I use batch scripts—they're the only type of script that will run on double click in a stock Windows install. Powershell scripts won't by default for security reasons, but for some reason for batch it's okay. So I use batch.
- pjmlp 6y agoBecause tons of legacy applications rely on it and it would be a major outcry to change them to the way Powershell works. Locking down batch files, vbs and js scripts can be easily done at AD level and let people be pissed off with IT instead.
- Wowfunhappy 6y agoOkay, but then Microsoft needn't act surprised when people use batch. And security-wise, I have to question whether that's really a useful outcome versus letting Powershell scripts run by default.
- pjmlp 6y agoYeah, but it is hardly different than the "curl | sh" fashion I guess. Here how to disable it, https://www.computerhope.com/issues/ch001005.htm https://www.computerhope.com/issues/ch001005.htm