Remix.run Logo
jeffbee 10 months ago

In this degenerate example, the completely straightforward way is tied for fastest as well. It's clear this has nothing to do with ranges.

    Response response;
    response.data.reserve(widget.data.size());
    std::ranges::transform(widget.data, std::back_inserter(response.data),
        [](const auto& element) {
          return ToData{.title = element.title, .amount = element.amount*42};});
    return response;
vitus 10 months ago | parent [-]

> the completely straightforward way is tied for fastest as well.

Is it, though? back_inserter should replicate push_back(), which incurs a move at the very minimum. The approach with emplace_back() does not.

https://quick-bench.com/q/1zwemArsS0gtKwveR9FZsuRwT34

This also isn't the way C++20 wants us to work with ranges and views, either -- this is basically just std::transform as you'd write it 20 years ago, except with a container as the argument instead of your begin / end iterators (so, basically absl::c_transform).

jeffbee 10 months ago | parent | next [-]

The difference is in your file you still have the `Widget widget` parameter, whereas your faster version has the `const Widget& widget` parameter. That's what matters.

ETA: there is a slight advantage for your function body using GNU libstdc++, but there is no advantage when using LLVM libc++. Under libc++ all three are exactly as fast, and faster across the board than any of the GNU results.

https://quick-bench.com/q/Ot1AK-q7D0CNVDeHrKCRtJ-dmA0

10 months ago | parent | prev [-]
[deleted]