Aggregate initialization using private copy / move instances

I came across this while testing some things for another question about aggregate initialization. I am using GCC 4.6.

When I initialize an aggregate with a list, all members are created in place, without copying or moving. To wit:

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}} }; } 

We confirm by creating several noisy designers:

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

No messages are printed at startup. However, if I make the move constructor private, the compiler complains about 'Goo::Goo(Goo&&)' is private , although the move constructor is clearly not needed.

Does anyone know if there is a standard requirement for a move constructor for accessibility for aggregate initialization like this?

+4
source share
2 answers

Do not call the copy or move constructor - this is Optimization , specifically allowed by the standard (but not required).

To be consistent between compilers, an implementation must verify that the constructor could be called if it did not want to optimize it.

+8
source

Please let me follow Bo's answer with a modified case, again in 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 } 

Why is the first form of building in place of OK even without the available copy / move constructors (note that Goo clearly not a POD or an aggregate), but the last two (functionally identical) forms are not? What part of the standard says that the compiler should check the available constructor in the last two cases, but not in the first case?

0
source

All Articles