Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion of vector<shared_ptr<Foo> > to vector<shared_ptr<const Foo> >

According to this page you can implicitly convert shared_ptr<Foo> to shared_ptr<const Foo>. That makes good sense.

However, I run into an error when I try to convert a std::vector containing shared_ptr<Foo> to one containing shared_ptr<const Foo>.

Is there a good way to achieve this conversion?

like image 269
Alan Turing Avatar asked Dec 28 '22 20:12

Alan Turing


1 Answers

No: std::vector<shared_ptr<Foo> > and std::vector<shared_ptr<const Foo> > are different types, so you can't treat an object of one as an object of the other type.

If you really need a std::vector<shared_ptr<const Foo> >, you can easily create one with shared_ptrs to the same elements as the original:

std::vector<shared_ptr<Foo> > v;
std::vector<shared_ptr<const Foo> > cv(v.begin(), v.end());

However, if you write your code in terms of iterators, you shouldn't have any problem with this. That is, instead of using

void f(const std::vector<shared_ptr<const Foo> >&);

// used as:
std::vector<shared_ptr<const Foo> > v;
f(v);

you should be using

template <typename ForwardIterator>
void f(ForwardIterator first, ForwardIterator last);

// used as:
std::vector<shared_ptr<const Foo> > v;
f(v.begin(), v.end());

This way, the function f just requires that it gets a range of things that are usable as pointers to const Foo (or shared_ptr<const Foo>s, if the function assumes that the range contains shared_ptrs).

When a function takes a range instead of a container, you decouple the function from the underlying data: it no longer matters what the data actually is or how it is stored, so long as you can use it in the way that you need to use it.

like image 65
James McNellis Avatar answered Jan 11 '23 00:01

James McNellis