Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aggregate initialization with private copy/move constructors

I came across this while testing some stuff for another question on initializing aggregates. I'm using GCC 4.6.

When I initialize an aggregate with a list, all the members are constructed 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}} };
}

Let us confirm by making some noisy constructors:

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

Upon running, no messages are printed. However, if I make the move constructor private, the compiler complains with ‘Goo::Goo(Goo&&)’ is private, although the move constructor is patently not needed.

Does anyone know if there's a standard requirement for the move constructor to be accessible for aggregate initialization like this?

like image 770
Kerrek SB Avatar asked Feb 24 '23 22:02

Kerrek SB


1 Answers

Not calling the copy or move constructor is an optimization specifically allowed by the standard (but not required).

To be consistent across compilers, an implementation must check that the constructor could have been called, if it didn't care to optimize it out.

like image 94
Bo Persson Avatar answered Mar 05 '23 16:03

Bo Persson