Search code examples
c++for-loopstdvector

Can't use more modern for loop with vector of derived class object. Why?


I have a base class and some derived classes. I generate a few objects of the derived classes, cast to the base class, and push them into a vector. I can iterate over the vector using an int index, but not using an iterator. Any idea why?

Given...

class Product
{
protected:
    char product_id;
    char size_id;
public:
    void Print();
    virtual ~Product() = 0;
};

class ProductASmall : public Product { public: ProductASmall(); };
class ProductAMedium : public Product { public: ProductAMedium(); };
class ProductALarge : public Product { public: ProductALarge(); };

...and...

vector<unique_ptr<Product>> products;

unique_ptr<ProductFactory> product_factory = ProductFactory::GetProductFactory(ProductType::A);
products.push_back(product_factory->CreateSmall());
products.push_back(product_factory->CreateMedium());
products.push_back(product_factory->CreateLarge());

Why does this work...

for (unsigned int i = 0; i < products.size(); i++)
{
    products[i]->Print();
}

...and this fails...

for (auto p : products)
{
    p->Print();
}

...with error...

Error (active)  E1776   function "std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx> &) [with _Ty=Product, _Dx=std::default_delete<Product>]" (declared at line 3433 of "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\include\memory") cannot be referenced -- it is a deleted function   

Solution

  • The answer came from @Daniel Langr:

    You are trying to copy a vector element into p in each iteration, which is not possible (unique_ptr doesn't support copy semantics). Easy fix: auto & p or, better if sufficient, const auto & p.