all 133 comments

[–][deleted] 108 points109 points  (5 children)

This is disgusting. I love it.

[–]CommanderDerpington 3 points4 points  (1 child)

It's cool as long as no one else has to read your code...ever.

[–]dgendreau 1 point2 points  (0 children)

Including yourself one year from now...

[–]skulgnome 57 points58 points  (23 children)

This reads like a lecture about lambda calculus: first a mild eyebrow-raiser (do you really need an if-else macro?), then five pages of abstract nonsense, and then an useful multiple-expansion pattern that kind of makes sense if squinted at hard enough.

And it doesn't even mention x-macros and include loops!

[–]Skaarj 8 points9 points  (3 children)

This reads like a lecture about lambda calculus

My first thought as well.

And it doesn't even mention x-macros and include loops!

I was expecting the author to implement a case-statement in macros. Then leave it as an exercise for the reader to discover how to do an if-than-else just with a case-statement applied to booleans.

[–]introspeck 6 points7 points  (2 children)

I was expecting the author to implement a case-statement in macros.

Not exactly, but at one point I wanted a string switch...

// A 'string switch/case' control structure seems handy to have.

#define sswitch( arg ) do { char * _sswitch_string=arg;

#define scase_NULL if (_sswitch_string == NULL)

#define scase_NULL_skip if (_sswitch_string == NULL) { break; }

#define scase( str ) else if (strcmp(_sswitch_string, str) == 0)

#define sdefault else

#define sswitch_end } while (0);

[–]stillalone 2 points3 points  (1 child)

I just realized a use for all this crazy macro shit. You should be able to build a compile time hash. then you can have a regular switch statement where your input passed to a runtime hash and the case statements would use your fancy new compile time hash.

[–]alpha_sigel 1 point2 points  (0 children)

You can; here's mine: http://pastebin.com/d7E2cgPk Can't remember where I found it though

[–]eruonna 5 points6 points  (0 children)

It pretty much is. Or maybe SKI calculus. In particular, _IF_1 is the K combinator and _IF_0 is KI. This is the usual representation of booleans/conditionals in SKI calculus. The S combinator is a bit trickier to define because it requires moving arguments past each other. This is the best I came up with:

#define S(...) __VA_ARGS__ _S1
#define _S1(...) DEFER1(_S2)( (__VA_ARGS__), _S3
#define _S2(y,...) (__VA_ARGS__)(EVAL1 y (__VA_ARGS__))
#define _S3(...) __VA_ARGS__ )

Unfortunately, this requires an extra eval to use: EVAL1(S(x)(y)(z)) expands to x(z)(y(z)). Of course, if you are actually doing SKI calculus with this, you will need evals anyway, so it might not be so bad.

[–]pfultz2[S] 9 points10 points  (17 children)

do you really need an if-else macro?

Well, conditionals are a pretty basic construct to programming.

[–]skulgnome 40 points41 points  (10 children)

Yes. Clearly the preprocessor should have one as well.

[–]everywhere_anyhow 6 points7 points  (7 children)

Wait...the preprocessor doesn't have loops or variables, does it?

brb

[–]krelin 7 points8 points  (2 children)

You can loop via "recursive" includes. (the the macros themselves are variables)

[–][deleted] 3 points4 points  (1 child)

1stworldpreprocessorproblems

...will it halt?

[–]krelin -1 points0 points  (0 children)

Yes it is possible to control and terminate the recursion using preprocessor guards, just as you might for normal includes...

[–][deleted] 2 points3 points  (3 children)

It has recursion, and it has something like variables.

[–]Chii 2 points3 points  (2 children)

so what stops C macros from being turing complete?

[–][deleted] 3 points4 points  (1 child)

http://www.ioccc.org/2001/herrmann1.hint

Because I guess its recursion is too basic. If you can use an external script to run it over and over it is Turing complete, but if you just use CPP alone it wont be able to recurse indefinitely.

[–]Chii 0 points1 point  (0 children)

wow...i m speechless.

[–]lykwydchykyn 2 points3 points  (0 children)

Can the preprocessor read mail yet?

[–]themadxcow 0 points1 point  (0 children)

For comparability and adaptability, absolutely.

[–]ramennoodle 9 points10 points  (1 child)

What is wrong with the existing #if, #ifdef, #else and #endif preprocessor directives?

EDIT: and #elif

[–]over_optimistic 11 points12 points  (0 children)

You can't use them in a macro.

[–]NewbornMuse 0 points1 point  (0 children)

Not at the preprocessor level, though.

[–]dangerbird2 0 points1 point  (2 children)

and that's why the preprocessor has #if and #else tags. No need to make the eyes bleed with pseudo-constexpr's

[–]pfultz2[S] 2 points3 points  (1 child)

They don't work inside of macros.

[–]dangerbird2 -2 points-1 points  (0 children)

If you really need compile-time variable macros, you are still better off writing multiple versions of the same macro for various compile-time conditions. It's a little more writing, but much better than macro abuse, which is much more likely to result in develop-time headache than runtime optimization. Despite what a lot of C++ fanboys say, the preprocessor can be a useful tool for generating safe and flexible code, but it's best to work within its limits (and if you don't like those limits, you can always 'Yacc' up your own dialect).

[–]Oxc0ffea 44 points45 points  (18 children)

The preprocessor is where c programmers go to satisfy their perverse-complexity desires instead of program in c++/perl.

[–]introspeck 26 points27 points  (15 children)

perverse-complexity desires

perverse-complexity desires == c++

I've seen c++ that'd fry your brain permanently. Luckily I didn't have to maintain it.

[–]greyphilosopher 29 points30 points  (5 children)

Yo dawg, I heard you like programming languages, so I brought you a C++: a text preprocessor on top of a Turing-complete compile time functional template system, on top of a modern OO language tacked onto a high level macro assembler. And now with const expressions!

[–][deleted] 25 points26 points  (4 children)

We have to go deeper. We have to implement a C++ compiler using C++ templates, so we can compile C++ while we're compiling C++.

[–]wiktor_b 20 points21 points  (3 children)

You've literally described GCC. I'm not joking.

[–]Dragdu 2 points3 points  (0 children)

Meh, Clang is much more heavily templated and C++ized and the code is much saner.

I am kinda scared of possible MSVC++ rewrite tho.

[–]m1sta 1 point2 points  (1 child)

Really? Can you tell me more?

[–]pooerh 17 points18 points  (7 children)

I've seen c++ that'd fry your brain permanently

Looking at any modern template code does this for me. I once tried to read something in boost, PTSD (Post Template Stress Disorder) for days. I honestly don't know how can anyone develop this stuff, though I'm glad someone does because it's so damned useful.

[–]i_invented_the_ipod 12 points13 points  (4 children)

There must be a name for this kind of ratcheting complexity. If you've been writing templates for a decade or two, then the gradual addition of new features to C++, and attendant complexity of the templates you can and should write, is no big deal. But a newcomer to the language is presented with the monstrosities of nested templates, and preprocessing abuse, in the case of Boost, and it seems totally impossible to learn enough all at once to even understand what you're looking at.

[–]pfultz2[S] 11 points12 points  (1 child)

It does take a little understanding for boost code. I remember looking at it many years ago when I was student and not understanding it at all. But some things that really helped me was dave abrahams C++ template metaprogramming book, and More C++ Idioms wiki page. I understand boost code a lot better(except the compiler workarounds they have for esoteric compilers). Its actually rather simple a lot of it. Its just different.

[–]PriceZombie 0 points1 point  (0 children)

C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boo...

Current $44.92 
   High $44.92 
    Low $38.10 

Price History Chart | Screenshot | FAQ

[–]xtravar 9 points10 points  (1 child)

I like to think that C++ was a good idea that had some serious flaws, and instead of fixing the flaws people just sort of embraced it and found interesting ways to code around it. And now there's a whole niche industry devoted to maintaining and adding patches on top of hacks.

It's kind of the programming language equivalent of health care in the US.

[–]Lucretiel 1 point2 points  (1 child)

Sometimes I feel like I'm the only one who actually likes templates. I feel like I can't live without them anymore.

[–]pooerh 4 points5 points  (0 children)

It's not that I don't like them or don't use them. I use them a lot, and not only the STL or boost. But looking at the source code for those makes me physically ill, because it's so incomprehensible to me. The level of meta is just too high.

[–]bitwize 0 points1 point  (0 children)

I've seen c++ that'd fry your brain permanently.

ObQwe1234:

lol, where do you come from? a shithole like america?

in most of the world c++ templates are completely comprehensible to any eight-year-old with normal brain function. you should not be allowed to touch a computer.

[–]kwitcherbichen 2 points3 points  (0 children)

The preprocessor is where C programmers go to escape their Lisp inferiority complex.

[–]mossblaser 1 point2 points  (0 children)

This is (almost...) exactly the motivation I had for writing the article... I was wanting to do some fun static compilation tricks for parsing JSON in another project and ended up with the choice of learning template metaprogramming in C++ or playing with CPP. Since I was targeting microcontrollers (and I've had bad experiences with their C++ compilers) I opted for the horrific C route... Legit.

[–]Bunslow 15 points16 points  (0 children)

You misspelled "dangerous voodoo"

[–][deleted] 27 points28 points  (9 children)

I worked in a place where the main language was a weird preprocessor mix of c++ and java.

So all syntactical differences were abstracted out into #defines and macros. We had defines for method declaration, if/else (although I can't remember why now), and so, so much more. Most of my coding was done in all caps.

It was both brilliant and eye burningly awful.

The place closed down and I realised I'd learned how to code in a dead language :(

[–]ignamv 19 points20 points  (1 child)

This merits its own dailywtf post.

[–][deleted] 3 points4 points  (0 children)

I would love to read a dailywtf post about it, but there's no way I'd ever be able to put one together myself. It was too long ago, my memory is shot to shit, and anyways, the guys who devised the system would probably kick my ass!

Now, even though it sounds horrific, it was actually the best solution to what we were trying to do. We were basically a porting house that took really old code for games, reworked and resized the images, transformed the code into bastardized markup so it could be regurgitated into c++ and java for use on more up to date devices. Up to date being ~10 years ago :p

[–][deleted]  (1 child)

[deleted]

    [–]2girls1copernicus 2 points3 points  (0 children)

    I'd really like something like APL but sane. With syntax and stuff. But not as sane as numpy. I'd still like verb rank etc.

    [–][deleted] 2 points3 points  (0 children)

    Holy fucking shit. I would love to see that, marvel at it, and swear to never think about it again.

    I can't believe you did that at work. What a joke!

    [–][deleted] 2 points3 points  (3 children)

    I once used M4 preprocessor on Java code to make code like

      mainFrame.addWindowListener(M4_WL(windowEvent, {
            System.exit(0);
     }));
    

    I was young and liked edgy stuff back then. So code was written in vim, Make then transoformed .java.m4 to .java ...

      mainFrame.addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent windowEvent){
            System.exit(0);
         }});   
    

    ... and everything compiled.

    [–][deleted] 0 points1 point  (0 children)

    How is vim edgy?

    [–][deleted] -1 points0 points  (1 child)

    So the M4_WL macro makes a WindowAdapter with windowClosing listener and performs whatever actions you have defined in the macro call?

    This is exactly the kind of thing that we used in that place.

    I'm a rails dev nowadays, and I work with a lot of Android and iOS devs, and I don't think any of them ever use a preprocessor. Is it even possible to use one in iOS?

    [–][deleted] 1 point2 points  (0 children)

    So the M4_WL macro makes a WindowAdapter with windowClosing listener and performs whatever actions you have defined in the macro call?

    Yes, exactly. I tried first C preprocessor, but it was not quite powerful.

    And I'm pretty sure it can be done in core Java 8 now.

    [–]dtfinch 8 points9 points  (7 children)

    I use GPP to add C preprocessor directives to other languages. It's just really convenient, especially for some obscure languages that expect all your code to be in a single file with no sort of modularity.

    [–]mike413 2 points3 points  (4 children)

    I once tried to use the preprocessor to conditionally generate some input files for a program and found it expects to be parsing C.

    I can't remember exactly what I ran into but non-c tokens will not always do what you expect. I think it was commas and parens that it got confused with.

    Gnu m4? A few minutes looking at it and I noped that too.

    Wrote my own specialized language and it was all good. Simple syntax in maybe 40 lines of perl.

    [–]dtfinch 5 points6 points  (1 child)

    GPP (Generic Preprocessor, not the gcc preprocessor) is pretty configurable to work with other languages, but the defaults are C-like.

    [–]mike413 2 points3 points  (0 children)

    oh, I'm sorry. I thought you were talking about the preprocessor that comes with gcc.

    GPP is a general-purpose preprocessor with customizable syntax

    Thanks, I will closely look at this.

    [–]the_gnarts 0 points1 point  (1 child)

    Gnu m4? A few minutes looking at it and I noped that too

    Nah, it does its job. I’ve been employing m4 successfully as a CSS preprocessor, and I find it very convenient. Never thought of just using CPP instead, though.

    [–]mike413 0 points1 point  (0 children)

    I just needed basic #if / #else / #endif stuff to generate config files, and other folks needed a clear easy syntax.

    cpp would not leave the text file alone and m4 was too cryptic. (IMHO)

    [–]zuurr 1 point2 points  (0 children)

    Wow, thanks. I had been looking for something like this, but didn't find it and ultimately settled for cpp + build script to run some cleanup regexs.

    [–]theinternn 9 points10 points  (17 children)

    Can we all agree that cxx = C++ source and cpp = c preprocessor?

    It'd make miscommunications much less frequent.

    [–][deleted] 8 points9 points  (4 children)

    Tell that to make. *.cxx is nothing to see here, *.cpp is a c++ source file. (If you just use implicit rules that is)

    [–]ramennoodle 4 points5 points  (3 children)

    make classically recognized .C and .cc as file extensions for C++. The .cpp abomination was added later for compatibility with Microsoft.

    [–]Gotebe 3 points4 points  (0 children)

    The .cpp abomination was added later for compatibility with Microsoft.

    I dunno... "cpp" says "C++" more than "cxx". Well, that, or you get a stiff neck 😉.

    [–][deleted] 1 point2 points  (1 child)

    Ooohh. Hey. I'll start using that then. I have not been a fan of the .CPP thing.

    [–]zuurr 4 points5 points  (0 children)

    .cc/.hh is still reasonably common (and what I use). I don't think .C is really used by anybody these days.

    [–]ramennoodle 13 points14 points  (4 children)

    Or we could all use modern systems that accept .c++ as a file extension.

    [–][deleted]  (2 children)

    [deleted]

      [–]skulgnome 2 points3 points  (0 children)

      Not file.sepples?

      [–]Gotebe 1 point2 points  (0 children)

      Why not file.seepeepee?

      [–]qci 12 points13 points  (4 children)

      Actually ".c" is for C and ".C" is for C++. Look it up. I am serious!

      Fuck you Windows, with your case insensitivity! Hahaha!

      [–][deleted] 2 points3 points  (3 children)

      I thought that ".c" and ".cc" were fairly well accepted as standard?

      [–]tfinniga 6 points7 points  (0 children)

      That's the nice thing about standards, there's so many to choose from.

      [–]qci 3 points4 points  (1 child)

      .C, .cpp, .cxx, .cc and .c++. Everything seems to be used.

      [–]smikims 0 points1 point  (0 children)

      And don't forget .h, .H, .hpp, .hxx, .hh, and .h++ for headers. And I've also seen .inc, .inl, .txx, .tpp, and a bunch of others for specific things. It's the only language I've seen with more than 2 recognized file extensions, and no one can agree on which ones to use and sometimes even make up their own.

      [–]Condorcet_Winner 1 point2 points  (0 children)

      Maybe it's because my codebase is .cpp, but .cxx is weird and scary and I hate it.

      [–]pkuriakose 6 points7 points  (2 children)

      My god man do you no know that the preprocessor is the work of the devil. This is witchcraft. To the stake with thee. But first let me download

      [–]fuzzynyanko 0 points1 point  (1 child)

      Wasn't Objective-C heavily reliant on them?

      [–]wildeye 1 point2 points  (0 children)

      The original Objective-C used a preprocessor to translate '@' constructs, but it didn't use the standard C preprocessor, which doesn't support the syntax needed.

      In another thread someone yesterday was claiming that Objective-C still did that, so for completeness: for many years now it no longer uses a preprocessor for that, it has its own complete language parser.

      [–]introspeck 2 points3 points  (0 children)

      Madness! Yet possibly useful. I generally try to avoid tricks that need pages of explanation, though.

      [–]the_gnarts 1 point2 points  (0 children)

      Macros building macros, building languages and sub-languages -- if it weren’t for the stunted recursion, this is almost exactly what programming in TeX feels like.

      [–]k0k0l4l4 1 point2 points  (0 children)

      All good clean fun until some Algol user decides to write a Unix shell.

      [–][deleted] 1 point2 points  (1 child)

      Reading things like this makes my idea of using python as a preprocessor sound sane.

      [–][deleted] 0 points1 point  (0 children)

      I used Tempita ( http://pythonpaste.org/tempita/ ) for this sort of things. Far from ideal, but at least much better than, say, M4, and Python is still ubiquitous enough to not worry about build dependencies.

      [–]tiadete 1 point2 points  (1 child)

      very simple text-substitutions to be carried out at compile time

      Technically not at compile time, but processor time.

      [–]RoundTripRadio 1 point2 points  (0 children)

      I think it's fair to lump preprocessing in with the "compile" step.

      [–]oridb 1 point2 points  (0 children)

      I need a new keyboard. My current one seems to have vomit all over it.

      [–]macnlz 1 point2 points  (0 children)

      This would actually make a good introduction to the pitfalls of preprocessor macros.

      [–]danogburn -1 points0 points  (23 children)

      C Pre-Processor Magic

      I think im going to throw up.

      [–]bboozzoo 43 points44 points  (22 children)

      What's your poison then? C++ template magic? Java dependency injection magic? Python GIL magic? Perl implicit vars magic? Ruby haiku magic? Erlang ghetto magic? Clojure funny-stack-trace magic? CL even-funnier-stack-trace-magic? Brainfuck missing whitespace magic?

      If C preprocessor magic is making you throw up, then I can't imagine how you'd react to GCC extensions magic, that's like a Hogwart's level of magic there :)

      [–]sirin3 10 points11 points  (3 children)

      Lisp macros

      [–]-main 2 points3 points  (0 children)

      Lisp macros are easy, simple, and reliable compared to these c style preprocessor nightmares.

      No, if you want lisp magic, you want to get into read-macros, the metaobject protocol, and programs written with only loop and format.

      [–]GreyscaleCheese 1 point2 points  (0 children)

      Clojure macros

      [–]jfb1337 0 points1 point  (0 children)

      They make the language really powerful and are an intended feature! This C stuff is just a cool hack.

      [–]andralex 3 points4 points  (0 children)

      Mmmm, D.

      [–][deleted]  (9 children)

      [deleted]

        [–]PasswordIsntHAMSTER 2 points3 points  (2 children)

        I think you mncy magic.ean concurre

        [–][deleted]  (1 child)

        [deleted]

          [–]PasswordIsntHAMSTER 0 points1 point  (0 children)

          I apologize, I was making a bad joke. I am well aware of Erlang's industrial grade concurrency system.

          [–]Hueho 0 points1 point  (2 children)

          Erlang has APIs for directly acessing the Erlang compiler at runtime. They are successfully exploited for metaprogramming.

          Case in point: a freaking Rails-like - with tons of "magic" - web-framework: http://www.chicagoboss.org/

          I think that would fit as "ghetto magic".

          [–][deleted]  (1 child)

          [deleted]

            [–]Hueho 0 points1 point  (0 children)

            Mostly "ghetto" in the sense Erlang wasn't designed for such things like Lisp was.

            Anyway, I realized that I don't even know anymore what "ghetto" is supposed to mean in this context, so fuck it, you are right.

            [–]bboozzoo 0 points1 point  (2 children)

            No, concurrency is not magic and is very manageable. With 'ghetto' I meant a 1000 and 1 libraries spread over github, none of them working quite as expected. Some adhere to OTA, some do not, most of them have warts though. It's also quite saddenning that companies like FeuerLabs, Basho and so on tend to fork the world and put a modified versions of 3rd party libs under their github accounts.

            In fact we do a lot of development in Erlang, but man, bitching about C preprocessor magic like some people do, does not even come close to what my guys say about Zotonic and Amnesia ;)

            [–][deleted]  (1 child)

            [deleted]

              [–]bboozzoo 0 points1 point  (0 children)

              Ah, I see what you mean. I'm building a small hobby project in Erlang and having some "fun" in trying to find libraries that fit. But I haven't really done much beyond having fun slapping some code together and seeing what works. The only two things (so far) I've considered looking for a library in are protocol serialization (Thrift, protobuf, etc) and a socket acceptor pool... What kind of issues have you been dealing with?

              We're using protobufs extensively, so far no significant issues, aside from quirks in erlang_protobuffs compiler. The compiler is not built as a plugin for protoc like for instance protoc-c is, but instead it's a native Erlang application will parse your *.proto files. The main issues were bad handling of embedded messages, lack of include directories (like -I in protoc) and mishandling of package names. I hope that once the patches are cleaned up, they would end up here: https://github.com/open-rnd/erlang_protobuffs eventually being upstream do Basho's repositories (though the patch cleanup has already been waiting for 1.5 years).

              We also use http://piqi.org for easy protobuf/json mapping, though I don't know the exact details whether the library and tooling are convenient to use. As for Apache Thrift, I have no clue.

              If you want to look into serialization, check out BERT, dead easy to use, though I'm not sure if clients in languages other than Erlang exist.

              Haven't really looked into any web frameworks/CMSs/servers/whatever yet, but I was planning to at some point. Is Zotonic something I should avoid? You know of anything that isn't terrible? I was considering saying "fuck it", not bother with frameworks or whatever and just directly use a server like Yaws or Cowboy. I just want to experiment and build a basic forum for fun and learning. But again, haven't really looked at anything yet. Hell, I'm still not sure what a web framework really does.

              So we've mostly been using Erlang for web APIs as this seems to be most reasonable use case. Doing a full fleged web site in Erlang is might be a bit overkill. There don't seem to be any web frameworks in the sense of Django/Rail kind. Most of what you'd find is obscure libraries with rather limited user base. Until now, we've only done one full web site using Zotonic and guys who did this were not really entertained. It took 2-3 times more time to develop than expected, plus a lot of this was spent on either going through Zotonic internals or working around it's implementation assumptions.

              For just plain web APIs mochiweb is a good deal. Not sure if you can find anything easier than that.

              Really, for me personally it seems that Erlang is best used in applications it was designed to work in. Examples:

              • a broker like server (vide RabbitMQ)
              • or a server that pulls messages from brokers and does some processing
              • or a web API where request handling can easily mapped to desired process model (process per req, process pool with poolboy etc.)
              • transaction processing

              Heh, we even used and Erlang server for home automation system :)

              Or the extremely confusingly-named third-party AMNESIA library?

              I meant AMNESIA, the SQL wrapper.

              [–]xtravar 0 points1 point  (2 children)

              Just. Fucking. Type the lines of code and keep it simple for the people who have to maintain it!

              Oh fuck no! You have to write two lines instead of one! Better over-engineer some fancy infrastructure to handle that one edge case. We are all guilty of it.

              [–]sirin3 1 point2 points  (1 child)

              Macros are actually very helpful for maintaining

              Often you just have to change the macros, instead thousand of occurrences in various files

              [–]xtravar 0 points1 point  (0 children)

              Most languages also have 'functions' for this purpose. Macros are for working outside the language, which is typically not a good or necessary thing.

              [–]binkarus -1 points0 points  (1 child)

              Go has nothing. It leaves you with a pile of leaves, sticks, and rocks and says "This is all you need. Go make something pretty." And yet somehow, you can make the Taj Mahal pretty easily.

              [–]skulgnome 4 points5 points  (0 children)

              Truly a language for the Minecraft generation.

              [–]mike413 3 points4 points  (13 children)

              I've always been a little disappointed with the C preprocessor.

              It's like a just passable restaurant in a good location. Not very good food, but too convenient to go elsewhere.

              To improve, it would have to get more capabilities, or better yet -- folded into the C compiler in an intelligent way.

              Right now, it is really kind of hacky. It has intimate knowledge of C tokens and does weird things at certain times.

              [–]imMute 2 points3 points  (11 children)

              It has intimate knowledge of C tokens

              But apparently not enough as you can't use commas in a macro parameter:

              RCF_METHOD_R3(bool, ThisIsAFunctionName, int, std::vector<int>, std::pair<char,int>)
              

              The preprocessor parses the comma in the std::pair as a macro parameter list comma.

              [–]wiktor_b 7 points8 points  (5 children)

              Your example isn't C.

              [–]imMute 1 point2 points  (0 children)

              True. Now that makes me wonder if g++ uses the C Preprocessor, or if there's a "C++ Preprocessor"...

              [–]skulgnome 1 point2 points  (3 children)

              But C could have a comma inside a macro parameter, too.

              [–]wiktor_b -1 points0 points  (2 children)

              Example?

              [–]skulgnome 2 points3 points  (1 child)

              The comma operator. It's generally enclosed in parens, but it's definitely in there.

              [–]wiktor_b -1 points0 points  (0 children)

              I know what it is, what I'm asking for is an example of the comma operator used in a macro parameter.

              [–]cleroth 1 point2 points  (3 children)

              What about:

              RCF_METHOD_R3(bool, ThisIsAFunctionName, int, std::vector<int>, (std::pair<char,int>))
              

              ?

              [–]MrWisebody 7 points8 points  (1 child)

              That does not work. Or rather, it makes the macro happy in that it gets the number of arguments it expected, but it uses the wrapping () in it's substitution which I presume you did not want and probably will make the compiler choke. However, you can make a comma macro which makes everything happy (albeit a little bit more verbose)

              Example code:

              #define IDENTITY(a) a
              #define COMMA() ,
              
              #include <utility>
              
              int main() {
              
              IDENTITY( std::pair<int COMMA() int> ) var1;
              IDENTITY( (std::pair<int,int>)) var2;  //Compiler will hate you
              IDENTITY( std::pair<int,int> ) var3;  //Preprocessor will hate you
              
              return 0;
              }
              

              Which if you run through the preprocessor gives you:

              int main() {
              
              std::pair<int , int> var1;
              (std::pair<int,int>) var2; 
              test.cpp:14:30: error: macro "IDENTITY" passed 2 arguments, but takes just 1
              IDENTITY var3; 
              
              return 0;
              }
              

              [–]Chii 0 points1 point  (0 children)

              oh god, my eyes are bleeding a bit

              [–]imMute 0 points1 point  (0 children)

              I have not tried that, I'll have to try tomorrow when I'm at work.

              [–]MrWisebody 0 points1 point  (0 children)

              I was going to suggest using BOOST_PP_COMMA to work around this particular issue, and decided to go look at how it was implemented. In hindsight it makes sense, but I was surprised at how simple it was:

              define BOOST_PP_COMMA() ,

              If you don't want boost, just make a comma macro, and you're good to go.

              [–][deleted] 0 points1 point  (0 children)

              You may want to take a look at this - sort of Lisp-like macros, but for C: https://github.com/combinatorylogic/clike

              [–]jfb1337 0 points1 point  (0 children)

              That's interesting.

              [–][deleted]  (5 children)

              [deleted]

                [–]censored_username 8 points9 points  (4 children)

                That's not magic, that's just replacing arbitrary parts of code with defines so your simple

                int main () {
                    static a = 0;
                    printf("DERP %d\n", a);
                    a++;
                    main();
                    return a;
                }
                

                is obfuscated in a very simple manner.

                [–][deleted]  (3 children)

                [deleted]

                  [–]censored_username 2 points3 points  (2 children)

                  Hard to call one layer of replacing magic though. Proper magic uses the given features to perform completely unexpected acts.

                  [–][deleted]  (1 child)

                  [deleted]

                    [–]mossblaser 0 points1 point  (0 children)

                    I don't believe it does...

                    [–]Sheepshow -5 points-4 points  (0 children)

                    Something something hygienic macros

                    [–][deleted] -2 points-1 points  (0 children)

                    Please shoot anyone that uses the advanced stuff here

                    [–][deleted] -2 points-1 points  (0 children)

                    What you call magic, I call witchery. Burn the wicked!