0

I have the following block:

int i = 0;
std::apply([&](auto &&... args) mutable {
    ((ef = (i++ == id) ?
           args.modifyEffectVec(ef, arr) : ef), ...);
}, EffectsTuple);

When i++==id, this is executed: args.modifyEffectVec(ef, arr). I want to log when this happens, so I know for which i it happened. I tried

int i = 0;
std::apply([&](auto &&... args) mutable {
    ((ef = (i++ == id) ?
           {
            ALOGV(TAG, "modifying effect for id %d", id);
            args.modifyEffectVec(ef, arr);
           } : ef), ...);
}, EffectsTuple);

but I discovered Why ternary operator does not support blocks?

I'm not sure how can I substitute this ternary for an if because it happens inside this thing called a fold expression

Zeus
  • 3,703
  • 3
  • 7
  • 20
Gatonito
  • 1,662
  • 5
  • 26
  • 55
  • Instead of making it a block, why not just put the thing into its own lambda and call that? It can do the logging call and execute the piece of code. – paddy Jan 13 '21 at 06:05
  • Extremely hairy, but I think that the comma operator would work here: `/* cond */ ? (ALOGV(TAG, "modifying effect for id %d", id), args.modifyEffectVec(ef, arr)) : ...`. That said, the code is already hairy, and I think it would be much easier to read if the `std::apply(...)` was extracted out into a new function. – Justin Jan 13 '21 at 06:05

3 Answers3

1

Why don't you just replace ; with ,?

int i = 0;
std::apply([&](auto &&... args) mutable {
    ((ef = (i++ == id) ?
            ALOGV(TAG, "modifying effect for id %d", id),
            args.modifyEffectVec(ef, arr);
            : ef), ...);
}, EffectsTuple);

EDIT:

The "," is a comma operator which adds a sequence point between the statements, that way you avoid putting a block there and both statements will still run.

More can be read here Comma_operator

AndersK
  • 35,813
  • 6
  • 60
  • 86
1

There is one family of expressions in C++ that allow for embedding an arbitrary number of statements within them. It's lambda expression. So if you want to execute a couple of statements in your fold, you can always wrap them in a lambda, and immediately invoke it over the fold.

int i = 0;
std::apply([&](auto &&... args) {
    ([&](auto &&) { 
         if (ef = (i++ == id)) {
            ALOGV(TAG, "modifying effect for id %d", id);
            args.modifyEffectVec(ef, arr);
         }
     } (std::forward<decltype(args)>(args)), ...);
}, EffectsTuple);

You don't seem to be using args in your fold, but in case you are, the extra lambda is written to forward it on correctly.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
0

As alternative, as you only call the function for idth tuple argument, you might do

std::apply([&](auto &&... args) mutable {
    auto funcs[] = {std::function{[&](){ args.modifyEffectVec(ef, arr);}...};
    ALOGV(TAG, "modifying effect for id %d", id),

    funcs[id]();
}, EffectsTuple);
Jarod42
  • 203,559
  • 14
  • 181
  • 302