c++ - Brace-init-list and assignments -


#include <iostream>  struct int_wrapper {     int i;      int_wrapper(int = 0) : i(i) {} };  struct {     int_wrapper i;     int_wrapper j;      a(int_wrapper = 0, int_wrapper j = 0) : i(i), j(j) {} };  int main() {     a;      = {3};      // error: no match ‘operator=’ (operand types ‘a’ , ‘int’)     // = 3;      std::cout << a.i.i << std::endl;      return 0; } 

i know isn't allowed more 1 user-conversion when doing implicit conversion, but, why brace-init-list double user-conversion works?

remember: using braced-init-list means "initialize object". getting implicit conversion followed object initialization. you're getting "double user-conversion" because that's asked for.

when a = <something>;, effective equivalent of a.operator=(<something>).

when braced-init-list, means a.operator=({3}). pick operator= overload, based on initializing first parameter braced-init-list. overload called 1 takes type can initialized values in braced-init-list.

there 2 overloads of operator. namely, copy-assignment , move-assignment. since braced-init-list initializes prvalue, preferred function call move-assignment operator (not matters, since leads same thing). parameter of move-assignment a&&, braced-init-list attempt initialize a. , via rules of copy-list-initialization.

having selected operator= function call, initialize a. since constructor of a not explicit, copy-list-initialization free call it. since constructor has 2 default parameters, can called single parameter. , type of first parameter in a's constructor, int_wrapper, implicitly convertible type of first value in braced-init-list, int.

so, implicit conversion int_wrapper, used copy-list-initialization initialize prvalue temporary object, used assign existing object of type a via move-assignment.

by contrast, a.operator=(3) attempts implicitly convert 3 a directly. of course requires 2 conversion steps , therefore not allowed.

just remember braced-init-lists mean "initialize object".


Comments