Yes, something like that. Of course you need to make sure that counter is visible when you actually run the graph computation (in your example you’d get a dangling reference since counter is local to the C++ function).
My general idea was (pseudo-code):
int counter = 0;
# `df` is the already-filtered dataframe
df.Define("my_index", [&counter] { return counter++; })
so that the lambda is only run for entries that survived the filtering. Ideally you would define "my_index" immediately before using it, so that there is no further filtering involved that would invalidate it.
Clearly this doesn’t work as neatly in a more complicated scenario (as yours might be), like if you need multiple counters and so on. Sorry if my example is simplifying too much.