Consider the following code:
#include <iostream>
struct Thing
{
Thing(void) {std::cout << __PRETTY_FUNCTION__ << std::endl;}
Thing(Thing const &) = delete;
Thing(Thing &&) = delete;
Thing & operator =(Thing const &) = delete;
Thing & operator =(Thing &&) = delete;
};
int main()
{
Thing thing{Thing{}};
}
I expect Thing thing{Thing{}};
statement to mean construction of temporary object of Thing
class using default constructor and construction of thing
object of Thing
class using move constructor with just created temporary object as an argument. And I expect that this program to be considered ill-formed because it contains an invocation of deleted move constructor, even though it can be potentially elided. The class.copy.elision section of standard seems to demand this as well:
the selected constructor must be accessible even if the call is elided
The Wording for guaranteed copy elision through simplified value categories does not seem to allow it either.
However gcc 7.2 (and clang 4 as well, but not VS2017 which still does not support guaranteed copy elision) will compile this code just fine eliding move constructor call.
Which behavior would be correct in this case?
It doesn't make an ill-formed program build. It gets rid of the reference to the deleted function entirely. The appropriate wording in the proposal is here:
[dcl.init] bullet 17.6
The example further strengthens this. Since it indicates the whole expression must collapse into a single default construction.
The thing to note is that the deleted function is never odr-used when the copies are elided due to value categories, so the program is not referring to it.
This is an important distinction, since the other form of copy elision still odr-uses the copy c'tor, as described here:
[basic.def.odr]/3
[class.copy] describes the other form of permissible (but not mandatory) copy-elision. Which, if we demonstrate with your class:
Should make the program ill-formed. And GCC complains about it as expected.
And by the way. If you think the previous example in the online compiler is a magicians trick, and GCC complains because it needs to call the move c'tor. Have a look at what happens when we supply a definition.