Search code examples
c++compiler-errorscopy-assignment

Why Assignment Operator implicitly deleted for const-members in c++?


This is not a duplicate of the question attached to the close request.

I have a class with a const-qualified field. I'm trying to assign it to a data structure that already has a value in the place I'm assigning. But because my class has a const-qualified field, my compiler is not allowing me to do so.


Errors:

Depending on the compiler, I either get:

note: copy assignment operator of 'A' is implicitly deleted because field 'size' is of const-qualified type 'const unsigned short'

or:

error: non-static const member ‘const short unsigned int A::size’, cannot use default assignment operator

Which are basically the same thing.


Minimal Viable Example:

#include <iostream>
#include <vector>
class A {
    private:
        const unsigned short size;
     
    public:
    
        A(unsigned short sz) : size(sz) {}
        
        void print_sz() {
            std::cout<<this->size<<"\n";
        }
};

int main()
{
    A a = A(2);
    
    std::vector<A> a_vec = std::vector<A>();
    a_vec.push_back(A(0));
    a_vec[0] = A(1); // This line breaks my code
    
    a_vec[0].print_sz(); // I want to see 1 printed here
    return 0;
}

This doesn't make sense to me... why can't it implicitly copy over a const value?

Who cares if it's const, just make a copy of the damn short!

I've tried std::move and so many other things

I don't want to implement a copy assignment operator and copy each member by hand because there's so many fields and a dynamic array in my actual code that I know I'll mess something up if I try to implement it.

I just want to put an A into my vector...


Questions:

1 - How do I fix this? I want any quick hack that works and doesn't require implementing a copy assignment operator. I don't care about the element already in the container. I just want to move the data from the temporary stack into the vector (to use elsewhere)

2 - If you have the time, I'd love an explanation as to why this makes sense...


Thanks.


Solution

  • You can't do assignment here. You've specified that size is const, which means you can initialize it, but you can't assign to it.

    One (kind of ugly) workaround would be to destroy the existing object, then use placement new to create a new object with the new value in the same location.

    #include <iostream>
    #include <vector>
    class A {
        private:
            const unsigned short size;
         
        public:
        
            A(unsigned short sz) : size(sz) {}
            
            void print_sz() {
                std::cout<<this->size<<"\n";
            }
    };
    
    int main()
    {
        A a = A(2);
        
        std::vector<A> a_vec = std::vector<A>();
        a_vec.push_back(A(0));
        a_vec[0].~A();        // out with the old
        new (&a_vec[0]) A(1); // and in with the new
        
        a_vec[0].print_sz(); // Prints `1`
        return 0;
    }