But we can do even better! We can eliminate vector functions in the loop... by writing code in an ugly, verbose, error-prone C-like fashion. :)
for (auto* ptr = my_vector.data(), *const end = my_vector.data() + my_vector.size(); ptr != end; ++ptr) { do_something(*ptr); }
Conversation
In an optimized build, there's good odds that that final C-like loop and the original modern C++ loop will result in the same output.
In a debug build, or when a compiler falls on its face (it happens), the difference can mean the modern C++ loop has 3x the iteration overhead!
2
23
Again, that doesn't mean we all _want_ the C-like version. The modern C++ version is clear, simple, expresses intent.
The problem isn't about _abstractions_. Abstractions are good.
The problem is that the _specific mechanism_ that C++ uses for these abstractions is trouble!
1
32
Most C++ abstractions rely on functions. Every user-defined operator? Function.
Language utilities like std::move? Function.
Accessing data in any "fundamental" type like unique_ptr/span/vector/etc? Functions.
3
1
19
Functions in and of themselves are fine. We like functions. Even the most curmudgeonly of C programmers uses functions. :)
The problem for these little abstractions is that the overhead of invoking a function can be many times the operation in question.
1
21
Incrementing the iterator type of a vector, under the hood, is "just" a pointer increment (assuming we turned off iterator debugging features). That's one instruction on most hardware. Invoking a non-inlined function (Debug build, remember?) is much more complex.
1
1
16
Let's not forget std::move. It doesn't even _do_ anything from a runtime perspective. Absolutely zero cost, conceptually. But it's a function!
Unless a compiler does magic, that shows up as runtime overhead. Even many C++ committee luminaries use macros to avoid that tax.
1
1
19
Let's look back at C. Plenty of code writes abstractions in C. It just often relies on macros. Just invoking a macro has guaranteed zero runtime overhead. A macro might expand to code with overhead, sure, but the macro itself is truly zero runtime cost.
2
1
21
But macros don't integrate in C++ well. They don't respect name lookup rules and all that jazz.
C++ just never offered a proper alternative, something that has the "guaranteed inline splat" of preprocessor macros but with the full name lookup rules applied.
2
2
24
The problem isn't abstraction. The problem is specifically _how_ C++ chose to implement its abstractions.
Something like P1221 Parametric Expressions (open-std.org/JTC1/SC22/WG21) would be one solve here.
2
27
Replying to
It might be interesting to compare this with Scala 3's inline keyword which can be used on functions, values, and parameters: docs.scala-lang.org/scala3/guides/ โ it might tricky to know what to mark inlined ahead of time, but it could be useful in some places.

