jeudi 29 juillet 2021

Move constructor needed, but not used, in array initialization with elements of class with deleted copy constructor

I apologize for the wordy title, but I'm having trouble concisely expressing this question.

I have a class with a deleted copy constructor and copy assignment operator. When I attempt to initialize an array with instances of the class I get a compiler error unless I provide a move constructor. However, the provided move constructor is not actually invoked.

Here's a MWE illustrating the issue.

#include <cstdio>
#include <string>

class A
{
public:
    explicit A(std::string s) : s_(s) { puts("constructor"); }
    A() = delete;
    ~A() = default;
    A(const A &other) = delete;
    A &operator=(const A &other) = delete;
    // A(A &&other) : s_(std::move(other.s_)) { puts("move constructor"); }

    void print_s() { printf("%s\n", s_.c_str()); }

private:
    std::string s_;
};

int main()
{
    A arr[]{A{"some"}, A{"string"}};
    for (auto &a : arr) {
        a.print_s();
    }
}

With the move constructor commented out as shown, I get the error:

> g++ file.cc -g -std=c++11 -o file && ./file
file.cc: In function ‘int main()’:
file.cc:22:32: error: use of deleted function ‘A::A(const A&)’
   22 |  A arr[]{A{"some"}, A{"string"}};
      |                                ^
file.cc:10:2: note: declared here
   10 |  A(const A &other) = delete;
      |  ^
file.cc:22:32: error: use of deleted function ‘A::A(const A&)’
   22 |  A arr[]{A{"some"}, A{"string"}};
      |                                ^
file.cc:10:2: note: declared here
   10 |  A(const A &other) = delete;
      |  ^

If I uncomment the move constructor I get the output

constructor
constructor
some
string

So, the move constructor does not actually appear to be invoked.

Why is the move constructor needed? Have I made a mistake somewhere (e.g., a poorly implemented move constructor)?

Aucun commentaire:

Enregistrer un commentaire