Remix.run Logo
jeffbee 3 days 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 2 days 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 2 days 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

2 days ago | parent | prev [-]
[deleted]