Reputation: 6331
I recently read about the various smart pointer types and i think that especially unique_ptr will be extremely useful, and shared_ptr with weak_ptr as well to some extent. However i'm not sure how to create "generic" functions which can deal with either pointer type and if that would even be a good idea.
So imagine having a vector of objects encapsulated by a smart pointer an you would like to apply some action to all elements using a function, something like this:
void doSomething(vector<shared_ptr<SomeType>>& array) {
// iterate over all array elements and do something
}
Obviously you will need to replicate this function three times for shared/unique/weak_ptr, which is somewhat cumbersome. It would be easier to have a "generic"/"polymorphic" smart pointer type which fits all of them for function parameter usage:
void doSomething(vector<generic_ptr<SomeType>>& array) {
// iterate over all array elements and do something
// no matter if array is a vector<shared_ptr> or vector<unique_ptr>
}
So, does there exist such a smart pointer? If yes - which problems may arise from its usage? If no - why not?
Upvotes: 3
Views: 2134
Reputation: 76721
Some misconceptions lead to an awkward code style:
Smart pointers are as generic as raw pointers: you can treat them much the same when calling functions of the pointed-to objects. If you really need to pass them to functions taking a raw pointer (and those functions will not take ownership), you can use their get()
function to give you that pointer. See 3.
Functions acting on collections should not take the collection as a parameter, but instead be a template taking a pair of iterators, which can then be used by dereferencing the pointers pointed to by the iterators, giving you a reference to the real object.
Don't write functions taking raw pointers. Use references instead and dereference at the call site. I'm aware this isn't always possible, but most often it is.
An alternative to looping in a function, is making the function act on a single object (reference), and putting the loop at the call-site. C++11 makes this very clean:
void some_function(item_type& item); // const if necessary
for(auto&& item_ptr : collection_of_item_smart_ptrs)
some_function(*item_ptr);
Clearly formulating intent, purpose, and type without any syntactical or stylistic hassle.
Upvotes: 4
Reputation: 4463
Differt pointer types allow different ownership handling with different runtime overhead required. In your case you can use template:
template<typename TVector>
void doSomething(TVector& array) {
// iterate over all array elements and do something
}
And use common for all of smart(and not so smart) pointers operator*
and operator->
Upvotes: 4
Reputation: 837
Each of these smart pointer types has its onw usage model.
unique_ptr can not be put in a container, it is neither copyable nor copy-assignable
weak_ptr must be converted shared_ptr in order to access the referenced object. Usable for a cache for example, cumbersome to use all over the place.
shared_ptr is the way to go in you situation
Upvotes: 0
Reputation: 70989
All of these pointer types actaully wrap a bare pointer. So we have two cases:
Your method modifies the pointer in some way. In this case you will not be able to generalize it as it should different cases depending on the type.
You never modify the pointer. Simply pass const bare pointer to the function.
Upvotes: 0