I desire to insert a conversion function (probably a std::function) to modify an object that is being pushed onto a std::vector. I would like the object to construct in-place, and pass through the function without additional copies being constructed.
Let's say I'm doing this:
std::vector<foo> foo_array;
foo_array.push_back(foo(foo_construct_arguments...));
Now I want to do this:
foo_array.push_back(convert(foo(foo_construct_arguments...)));
Where 'convert' is something like this:
std::function<foo &(foo&)> convert{ [&](foo &f)->foo& { return f; } }
Obviously, the function must modify f to be useful, but in the simplest case let's say it just returns the object.
I want to end up with syntax that looks something like this:
foo_array.emplace_back(convert(foo(foo_construct_arguments...)));
And have an instance of foo constructed, modified by the convert function, then emplaced in the vector with only a single construction. It seems like there should be some way of specifying r-value references in the proper places to get this to happen, but I'm not familiar enough with move-semantics etc. to make it happen. I can find ways to get there with 1 copy along the way.
The syntax needed here is:
std::function<foo&&(foo&&)> convert{[](foo&& f) -> foo&& { return std::move(f); } };
Or, fully generic lambda fn
:
auto fn = [](auto&& f) -> decltype(auto) { return std::forward<decltype(f)>(f); };
std::function<foo&&(foo&&)> convert{fn};
If this code is on a hot path, you may like to avoid wrapping a lambda into std::function
, if possible.
Alternatively, emplace_back
returns a reference to the new element, which you can then use to modify the element in-place:
std::vector<foo> foo_array;
std::function<void(foo&)> convert{...};
convert(foo_array.emplace_back(foo_construct_arguments...));