7

The first time I tried to write a range based for loop to iterate over unique_ptrs I wrote:

std::vector<std::unique_ptr<Foo>> vec;
// Initialize vec

for (auto v : vec) // error
{}

I then realized this is trying to create a copy of each element which doesn't make sense with a unique_ptr. So then I wrote it as a reference:

for (auto& v : vec)
{}

Adding a const in front of it keeps me from changing the pointer.

for (const auto& v : vec)
{
   v = nullptr; // error (good!)
}

How can I write it, so that the data pointed to cannot be changed? For example, the following code should not compile.

for (??? v : vec)
{
   v->func();
}

class Foo
{
public:
   void func();

private:
   bool mBar;
}

Foo::func()
{
   mbar = true; // Should cause error
}
3
  • Do you always need the pointee to be const (and thus can alter the definition of vec) or do you only need it to be const for this loop ? Commented Apr 7, 2014 at 13:30
  • Another application of this could be writing an inspector function, so preferably for only the loop. However, from the answers this doesn't sound possible. Commented Apr 7, 2014 at 13:40
  • look here: stackoverflow.com/questions/15518894/… Commented Apr 7, 2014 at 13:51

2 Answers 2

5

To prevent the data from being modified, include const in the template parameter for your pointer:

std::vector<std::unique_ptr<const Foo>> vec;

I think you'll have problems making the pointer itself const though. The reason is that the vector has to be able to copy the pointer object around internally (e.g. when the container is resized). With a unique_ptr, that means ownership has to be transferred between instances, meaning it has to be mutable (not const).

To make the pointer itself const, I think you've got two main choices: use a vector of const shared_ptr<>, or an array (i.e. fixed size) of const unique_ptr<>.

Sign up to request clarification or add additional context in comments.

Comments

3

For that, your unique_pointer must be instantiated for a const-qualified type, like this:

std::vector<std::unique_ptr<const Foo>> vec;

But maybe it is enough to use the iterator to initialise a constant reference at the start of the loop, the compiler should optimise it away:

for (const auto& v_iter : vec) {
    const auto& x = *v_iter;
    do_things(...);
}

Everything else is hackery.

What probably would work is reinterpreting your vector<unique_pointer<Foo>> as a vector<unique_pointer<const Foo>>, but it might result in hilarious undefined behavior if either vector or unique_pointer has a specialisation. Do not try, it is not worth that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.