Блог пользователя Tornad0

Автор Tornad0, история, 8 лет назад, По-английски

Hi codeforces, I have a great idea:D

when I read others code in codeforces, I always meet some #define term:

#define pb push_back
#define ppb pop_back
#define FOR(i,a,b) for (int _n(b), i(a); i <= _n; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b);i>=_b;i--)
#define all(c) (c).begin(), (c).end()

Can anyone please make a automatic translator to translate the original simplified code into it's full form? So that people who are not familiar with that can read the code more easily :D

  • Проголосовать: нравится
  • -19
  • Проголосовать: не нравится

»
8 лет назад, # |
  Проголосовать: нравится +11 Проголосовать: не нравится

type g++ main.cpp -E -dD in the terminal. that's good enough :)

»
8 лет назад, # |
  Проголосовать: нравится +25 Проголосовать: не нравится

There are not so many different defines (several dozens, maybe), and it would be easier just to memorize them all.

  • »
    »
    8 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    But different coder will have different styles of defines. So that make things harder.

    • »
      »
      »
      8 лет назад, # ^ |
        Проголосовать: нравится +23 Проголосовать: не нравится

      No, I mean, several dozens TOTALLY. Among all coders. Yes, sometimes you can see FOR(i, 0, n), sometimes it is forn(i, n), sometimes something else... But it isn't really too much.

      • »
        »
        »
        »
        8 лет назад, # ^ |
          Проголосовать: нравится +12 Проголосовать: не нравится

        I don't get the downvotes, he's right. Almost everybody who uses macros in C++ just more-or-less copied that part of their template from someone else's code. The number of distinct macros in use is small. They all do the same five or six things. Also, they are always defined in roughly the same section of the code (just below the includes), so it's usually quick and easy to check what a particular macro does if you need to.

»
8 лет назад, # |
  Проголосовать: нравится +155 Проголосовать: не нравится

Flame mode on.

Vote me up if you think that using FORN, FOR, FORD, forn etc defines sucks.

Vote me down if you don't think so.

  • »
    »
    8 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +35 Проголосовать: не нравится

    I won't vote either way, because the answer is neither black nor white. There is a time and place for everything.

    Using defines to save a few seconds of time spent implementing your solution is pointless. I'm looking at you, "#define push_back pb"!

    However, for many of those defines that wasn't the primary purpose. The people who started using them had a different goal.

    A related saying: "Many design patterns are just workarounds for missing features of your programming language." This is in fact what many of the defines are supposed to do.

    Duplication of code is bad. Did you ever write "for (i=0; i<n; ++i) for (int j=0; j<n; ++i)" or something similar? Note the "++i" at the end. Sure you did. All you wanted to say was "iterate over all n valid indices", but C++ required you to type the iteration variable not once, not twice, but already three times just when declaring the cycle. And during a copy-paste-rewrite session, some of these tend to get lost. Bugs like this are not exactly the easiest ones to debug. In Python, you can write "for i in range(n)". The REP(i,n) define brings this syntax to C++.

    For the very same reason I still mourn the deprecated-and-later-removed operators <?= and >?=. If you never saw these, "x <?= y" is shorthand for "x = min(x,y)". Again, you only had to write (and evaluate!) x once. (And no, having a define that "MIN(x,y)" means "if (y < x) x = y;" is not the same thing, but let's not go there now.)

    Back in the day, one of the popular defines was

    #define FOREACH(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();++it)

    This was super useful: often you want to iterate over an STL container, and C++ lacked concise syntax. Now, in modern versions of C++, this macro has been deprecated by the range-based for-cycle (finally!) and we are seeing its use diminish. This is precisely the type of a "missing feature" macro.

    Next: container.size() returning unsigned may be a reasonable decision from a design point of view, but it's super annoying and it is a frequent source of bugs: e.g., (3u — 5u) is a huge positive number. Having and using a macro SIZE(container) that typecasts the size() to a signed int prevents these bugs.