Question

I have const objects in a deque:

class ConstClass {
  public:
    ConstClass(int variable): variable_(variable) {}
  private:
    const int variable_;
};

std::deque<ConstClass> objects;
objects.push_back(ConstClass(1));
objects.push_back(ConstClass(2));
objects.push_back(ConstClass(3));

How can I replace the second element with another one?

If I try to do it using [] = or std::replace, I get:

Compiler could not generate operator = for class 'ConstClass'

The only way I can think of is creating empty deque, push_back() all elements from 'objects' there (replacing the N-th element with the new one), then clear() the 'objects' deque and push_back() the copied elements from the temp deque back to 'objects'..

I am sure there is a more sane way to do it, but I don't know how?

Was it helpful?

Solution

You can't. Your container is invalid because its element type must be copy-assignable or move-assignable, and yours is neither. This isn't diagnosed at construction, but you've already seen the resulting compilation error that occurs when you try to perform operations that rely on this property.

You could make it legal and compilable by overloading the copy and move assignment operators of your element type to ignore the const member, but it's not clear that this would make any sense.

Either store std::unique_ptrs to dynamically-allocated objects, or rethink the model.

OTHER TIPS

Some more context to the problem would be useful, how have you ended up here? What's the purpose of ConstClass and why does it have to be const?

Assuming there's good reasons you can't fix this without hacking, you could do this:

int main() {

   std::deque<std::shared_ptr<ConstClass>> objects;
   objects.push_back(std::make_shared<ConstClass>(1));
   objects.push_back(std::make_shared<ConstClass>(2));
   objects.push_back(std::make_shared<ConstClass>(3));

   objects[2] = std::make_shared<ConstClass>(100);
}

But there's surely a better way...

(you may want to use unique_ptr rather than shared, I'm not sure what your requirements are. If you're using an older platform, the boost shared_ptr would also work)

By specifying const member you are disabling the default assignment operator and you should not do the tricks/hacks to go around that limitation.

You can instead use smart pointers (unique or shared if you need shared ownership), for example like that:

int main(){
    std::deque<std::unique_ptr<ConstClass> > objects;
    objects.push_back(std::unique_ptr<ConstClass>(new ConstClass(1)));
    objects.push_back(std::unique_ptr<ConstClass>(new ConstClass(2)));
    objects.push_back(std::unique_ptr<ConstClass>(new ConstClass(3)));

    objects[2]=std::unique_ptr<ConstClass>(new ConstClass(4));
    // or any other usage of assignment operator, depending on the needs
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top