Askaga
Askaga

Reputation: 6331

Are there generic smart pointers?

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

Answers (4)

rubenvb
rubenvb

Reputation: 76721

Some misconceptions lead to an awkward code style:

  1. 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.

  2. 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.

  3. 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

alexrider
alexrider

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

Marius
Marius

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

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 70989

All of these pointer types actaully wrap a bare pointer. So we have two cases:

  1. 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.

  2. You never modify the pointer. Simply pass const bare pointer to the function.

Upvotes: 0

Related Questions