Совокупная инициализация с закрытыми конструкторами копирования / перемещения - PullRequest
4 голосов
/ 08 июня 2011

Я сталкивался с этим при тестировании некоторых вещей для другого вопроса об инициализации агрегатов. Я использую GCC 4.6.

Когда я инициализирую агрегат со списком, все элементы создаются на месте, без копирования или перемещения. Для остроумия:

int main()
{
  std::array<std::array<Goo,2>,2>
    a { std::array<Goo,2>{Goo{ 1, 2}, Goo{ 3, 4}} ,
        std::array<Goo,2>{Goo{-1,-2}, Goo{-3,-4}} };
}

Давайте подтвердим, сделав несколько шумных конструкторов:

struct Goo
{
  Goo(int, int) { }
  Goo(Goo &&) { std::cout << "Goo Moved." << std::endl; }
  Goo(const Goo &) { std::cout << "Goo Copied." << std::endl; }
};

После запуска сообщения не печатаются. Однако, если я сделаю конструктор перемещения закрытым, компилятор пожалуется на ‘Goo::Goo(Goo&&)’ is private, хотя конструктор перемещения явно не нужен.

Кто-нибудь знает, существует ли стандартное требование, чтобы конструктор перемещения был доступен для агрегатной инициализации, подобной этой?

Ответы [ 2 ]

8 голосов
/ 08 июня 2011

Не вызывать конструктор копирования или перемещения - это оптимизация , специально разрешенная стандартом (но не обязательная).

Чтобы быть согласованными между компиляторами, реализация должна проверять, что конструктор мог быть вызван, если он не хотел оптимизировать его.

0 голосов
/ 10 июня 2011

Пожалуйста, позвольте мне продолжить ответ Бо с измененным регистром, снова в GCC 4.6:

struct Goo
{
  Goo(int x, unsigned int n) : x(x), s(new char[n]) { }
private:
  Goo(const Goo &);
  Goo(Goo &&);
  int x;
  char * s;
};

struct Foo
{
  int a;
  Goo g;
};

void f()
{
  Foo k { 3, {1,2} }; // works
  //Foo t { 1, Goo{5,6} }; // fails
  //Foo r { 0, Goo(7,8) }; // fails
}

Почему первая форма построения на месте в порядке, даже без доступных конструкторов копирования / перемещения (обратите внимание, что Goo явно не POD или агрегат), а две последние (функционально идентичные) формы нет? Какая часть стандарта говорит, что компилятор должен проверять доступный конструктор в последних двух случаях, но не в первом случае?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...