Вопрос

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
}
Это было полезно?

Решение

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

Другие советы

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top