I have code that looks like:
vector<unique_ptr<Foo>> foos = ... // Init vector.
// Do some stuff.
func(std::move(foos)); // func should now own foos, I'm done with them.
// Takes ownership of foos.
void func(vector<unique_ptr<Foo>>&& foos);
Now inside func
I want to refactor out a bit of code into a separate function that needs to use foos
. I am wondering how to do this. The options I considered are:
void util_func1(const vector<Foo*>& foos); // Does not take ownership of foos
void util_func2(const vector<unique_ptr<Foo>>& foos); // Does not take ownership of foos
The first option seems in line with the recommendation for (non-vectors of) unique_ptr, if a function takes ownership, pass unique_ptr by value, if a function doesn't take ownership pass by raw ptr/ref. If I understand correctly, the recommendation is to never pass unique_ptr by const-ref. Which is essentially what util_func2
is doing.
My problems is that now func
has gotten pretty ugly:
void func(vector<unique_ptr<Foo>>&& foos) {
vector<Foo*> raw_ptr_foos;
raw_ptr_foos.reserve(foos.size());
for (auto foo : foos) raw_ptr_foos.push_back(foo.get());
util_func1(raw_ptr_foos);
}
So is util_func2
the correct way to do this or should I bite the bullet and write the ugly conversion to raw_ptr_foos
or is there a 3rd way?
CodePudding user response:
If you have C 20, you express it as concepts, and have a constrained template as your helper.
template <typename P, typename T>
concept points_to = requires(P p) {
{ *p } -> std::common_reference_with<T &>
} && std::equality_comparable_with<std::nullptr_t>
template <std::ranges::borrowed_range R, typename T>
concept indirect_range_of = points_to<std::ranges::range_value_t<R>, T>;
template <indirect_range_of<Foo> Foos>
void util_func1(Foos foos);
void func(std::vector<std::unique_ptr<Foo>> foos) {
util_func1(std::ranges::views::all(foos));
}
Prior to that you write a template, and optionally add sfinae or static_asserts
template <typename Foos
void util_func1(const Foos & foos);
void func(std::vector<std::unique_ptr<Foo>> foos) {
util_func1(foos);
}
CodePudding user response:
If you want to access and change these vector elements in multiple functions, I would consider using shared_ptrs instead of unique_ptrs. This way you still don't have to worry about memory leaks at the end of function execution and you don't have to mess around with raw pointers.