4 ms·
Deciphering C++ compiler errors: Nonsensical errors from a function declaration
- tbrownaw 2y agoWell, yes. This is why preprocessor macros should have obvious, inconvenient naming conventions. And should be avoided in favor of more modern (better-behaved) features when possible.
- WalterBright 2y agoI removed as much macro usage as practical from my ancient C code. Makes the code a lot easier to deal with.
- o11c 2y agoPro tip: `#pragma GCC poison` is very good for (incrementally) getting rid of specific C-isms (both individual macros and individual functions) and keeping them out. It looks like `#pragma deprecated` is similar for MSVC, but it has the major downside of only being a warning. That said, I am not at all afraid of using macros when appropriate. Just give them names that scream "I_AM_A_MACRO" unless you take care to make them sufficiently function-like, and if public give them a "namespace" prefix either way.
- aleden 2y agoBefore #define ing MY_MACRO, do #ifdef MY_MACRO #error #endif edit: and #undef MY_MACRO after done using it, ideally.
- AlotOfReading 2y agoNot a perfect defense either. If you ever have the misfortune of using mentor graphics code, they #define REGISTER. They also ship a standard library that uses the register keyword. If you build a project using their standard library and their toolchain together, it explodes. If you name something like set_register, it also explodes.
- jamesfinlayson 2y agoUgh... I had something similar recently but much more painful to figure out - apparently googletest defines and and or (lowercase) as macros). I started using googletest in a project with a moderate amount of inline assembly, and of course I got some thoroughly confusing error messages after the substitution replaced the and and or opcodes. Anyway, I didn't know that push_macro and pop_macro existed, so I'll have to revisit my previous hack around that issue.
- cordenr 2y agoIn C++ they're alternative tokens and should be keywords, so maybe googletest is providing them as macros as workaround for a compile that didn't support this? In other words, maybe a computer flag would allow you to disable them being defined? Although this could result in other issues...
- jamesfinlayson 2y agoYeah I kind of thought it was something like that, but searching for such broad terms got me nowhere, and the googletest documentation wasn't good enough for me to find it.
- o11c 2y agoThat's standard if `<iso646.h>` is included in C, but said header is a nop for C++. In the GCC world, inline asm uses strings so macros don't cause problems.
- jamesfinlayson 2y agoYeah okay - this was an MSVC project with inline assembly.
- oflebbe 2y agoWait what? This is an blogpost from Chen? I did remember reading better quality content before. This is the usual nightmare dealing with larger C++ codebase.
- pjmlp 2y ago> Doesn’t the non-macro version have a use-after-free? > > > Indeed it does. Rats. Not even the great Raymond Chen writes CVE free code.
- signa11 2y agoas the song goes “… sometimes you are the windshield, and sometimes you are the bug…”
- pionaryon 2y agoYou can suppress function like macros by using parenthesis because function like macro expansion is literally defined as "name directly followed by open paren". #define foo(x) something void foo(int a) {} // doesn't work void (foo)(int a) {} // does work because 'foo)' can never be a function macro
- badmintonbaseba 2y agoThe error is coming from a WinRT header, not something they can easily control. It's similar to having something like `#define string(x) something` and then including <string>.
- DrBazza 2y agoI knew this would be a preprocessor macro from the second I saw 'nonsensical errors'. The joys of having a multi-decade career in C++ and C.
- Night_Thastus 2y agoThis is the sort of reason why macros are evil and I hate them. Harder to inspect while running, can't be scoped properly, often have poor names, not as much static/compiler safety measures, etc. Evil evil evil. I get that sometimes they're unavoidable, but IMO you need to do everything you can to avoid them in C or C++. So many better options. Functions. Lambdas. Templated functions. ANYTHING but macros.
- winocm 2y agoOne heinous example is many implementations of '_FORTIFY_SOURCE', unless you want to resort to using lots of clang '__attribute__((__enable_if__(...)))' statements in your inline functions.
- bitbasher 2y agoOne thing I really enjoyed about Rust that I didn't imagine I would-- good compiler error messages. I actually find the compiler to be helpful, which shouldn't be surprising but it is.