3
#define len(a) if (a == 8)   1       \
               else if (a == 3) 0    \
               else -1

this code is just an example how do we use nested if else. I don't want to use ternary operator as in that case i can't use else if statement.

13
  • 7
    Use a function. Commented Jun 7, 2020 at 15:28
  • 1
    Why do you want to use the preprocessor for this? Commented Jun 7, 2020 at 15:29
  • 5
    I'd highly appreciate it if you'd do it in my competitor's code base. Commented Jun 7, 2020 at 15:30
  • 2
    I just want to learn how to do this using pre-processors #define len(a) [](int x) -> int { if (x == 8) return 1; if (x == 3) return 0; return -1; }(a) Now that you have learned how to do it, I also hope that you have learned not to do it. Commented Jun 7, 2020 at 15:59
  • 2
    Pick one tag, C or C++. Commented Jun 7, 2020 at 16:08

5 Answers 5

6

Don't abuse the preprocessor. Use a real function:

constexpr auto len(int const a) {
    if (a == 8) return 1;
    if (a == 3) return 0;
    return -1;
}
Sign up to request clarification or add additional context in comments.

9 Comments

@Ray if the provided argument is a constant expression, the result will be calculated at compile time as well. If it's not, the result isn't either.
@_Static_assert, It can be, but to force it to be done at compile time, you need to use the result in a context that requires a constant expression.
@chr yes, you're right. I imagine most compilers will do that optimization anyway. And even if the argument is not constexpr, it's likely to be inlined. So this exactly like preprocessing, but much more convenient to write/use/maintain.
it is only C++. will not compile as C
@P__J__ you could have a macro defined #ifndef __cplusplus #define constexpr #endif. So you can't tell if it's valid C or not.
|
1
inline __attribute__((always_inline)) int len(const int a)
{
    switch(a)
    {
        case 8: return 1;
        case 3: return 0;
    }
    return -1;
}

3 Comments

I haven't programmed in C++ forever, I think I had constexpr mixed up with inline.
as I understand it has to be both valid C & C++
Note that __attribute__((always_inline)) is non-standard and does not work in all compilers.
1

If you can use GNU extensions and insist on a macro with if-else branching, you can use compound statement expression:

#define len(a) ({                 \
    int _res = -1;                \
    if ((a) == 8) _res = 1;       \
    else if ((a) == 3) _res = 0;  \
    (_res); })

This works both in C and C++. Unfortunately, such compound statements cannot be used in constant expressions.

2 Comments

So this is like using a lambda, but non-portable?
@_Static_assert, not fully equivalent. In that lambda, a is evaluated just once, here it can be evaluated twice. This can easily be fixed. And there are no lamdas in C.
0

Re: "I don't want to use ternary operator as in that case i can't use else if statement" -- well, yes, you can't use else if in a ternary operator. But you can use another ternary operator:

int x = a == 8 ? 1
    : a == 3 ? 0
    : -1;

Comments

-2

There is no issue in writing nested or not if statements in a macro, or at least no more issues than usual when you try to wrap statements in macros. But note that I used statement, there is no such thing as an if expression in either C or C++ excepted the ternary operator you don't want to use.

So if you want nested ifs statements in a macro, you can do something like

#define stmt(c1, c2) \
   if (c1) \
      do_1(); \
   else if (c2) \
      do_2(); \
   else \
      do_3()

(note that the way to escape end of lines is with \ and not with /). If you want an expression, you'll have either to use the ternary operator or a function as showed in other answers. Well, even if you need statements, I'd suggest to use a function instead of a macro.

4 Comments

I cant find any reason of doing it except to make code hard to debug and hard to read
@AProgrammer All the other answers covered this. This is not practical.
@P__J__ you commented while I was adding the fact that even for statements I'd recommend a function.
@AProgrammer always suggest waiting to finish your complete answer, before submitting it. That way this issue will be avoided in the future.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.