Copy initialization of the form '= {}'

Viewed 438

Given the following:

#include <stdio.h>

class X;

class Y
{
public:
  Y() { printf("  1\n"); }             // 1
  // operator X(); // 2
};

class X
{
public:
  X(int) {}
  X(const Y& rhs) { printf("  3\n"); } // 3
  X(Y&& rhs) { printf("  4\n"); }      // 4
};

// Y::operator X() { printf("   operator X() - 2\n"); return X{2}; }

int main()
{
  Y y{};     // Calls (1)

  printf("j\n");
  X j{y};    // Calls (3)
  printf("k\n");
  X k = {y}; // Calls (3)
  printf("m\n");
  X m = y;   // Calls (3)
  printf("n\n");
  X n(y);    // Calls (3)

  return 0;
}

So far, so good. Now, if I enable the conversion operator Y::operator X(), I get this;-

  X m = y; // Calls (2)

My understanding is that this happens because (2) is 'less const' than (3) and therefore preferred. The call to the X constructor is elided

My question is, why doesn't the definition X k = {y} change its behavior in the same way? I know that = {} is technically 'list copy initialization', but in the absence of a constructor taking an initializer_list type, doesn't this revert to 'copy initialization' behavior? ie - the same as for X m = y

Where is the hole in my understanding?

2 Answers
Related