Home > other >  Initializing a member of uncopyable and unmovable type
Initializing a member of uncopyable and unmovable type

Time:01-13

Given an uncopy/movable struct U, membes of that struct can not be assigned in the constructor (see C). They can only be initialized via a member initializer list (see S).

struct U {
    U(int x);
    U(U &other) = delete;
    U(U &&other) = delete;
};

struct S {
    S(int x) : u(x) {}
    U u;
};

struct C {
    C(int x) { u = U(x); }  // compiler complains: cannot assign
    U u;
};

Error:

<source>:13:5: error: constructor for 'C' must explicitly initialize the member 'u' which does not have a default constructor
    C(int x) { u = U(x); }
    ^
<source>:14:7: note: member is declared here
    U u;
      ^
<source>:1:8: note: 'U' declared here
struct U {
       ^
<source>:13:18: error: object of type 'U' cannot be assigned because its copy assignment operator is implicitly deleted
    C(int x) { u = U(x); }
                 ^
<source>:4:5: note: copy assignment operator is implicitly deleted because 'U' has a user-declared move constructor
    U(U &&other) = delete;
    ^

Code is here: https://godbolt.org/z/11nvh1ze4

The compiler of course rightfully complains. If x would be calculated in the constructor body, the initializer list could not be used. Is there any syntax that would allow to do so?

CodePudding user response:

You cannot initialize it in the constructors body. Members are initialized before the body of the constructor is executed. If x is computed when the constructor is called then you can still use the member initializer list. For example when you have a void f(int&) that needs to be called to retrive the parameter for u:

struct C {
    C(int x) : u(compute_x(x)) { } 
    U u;
private:
    static int compute_x(int x) { f(x); return x; }
};

There was another now deleted answers that raised a good point about the mental model of a constructor. The point to take away here is that the constructor body is not for initialization of members. This happens before the body runs. Once you got the hang of it you will find yourself writing many constructors whose body is nothing more than {}, because its actually not that common that a constructor does more than setting up the class members.

  •  Tags:  
  • Related