3

I'm wondering why this code compiles correctly. Since the copy-constructor and assignement-operator are deleted, I thought these mechanics would not be available.

I'm thinking that the constructions in main() are substituted by the compiler with some kind of emplace construction effectively made by Object itself... but I couldn't figure why or how that would happen.

struct Object
{
private:
    friend struct ObjectFactory;
    Object() {}
    Object(const Object& other) = delete;
    Object& operator=(const Object&) const = delete;
};

struct ObjectFactory
{
    static Object CreateObject() { return Object(); }
};

int main()
{
    Object object1 = ObjectFactory::CreateObject();
    Object object2 ( ObjectFactory::CreateObject() );
    Object object3 { ObjectFactory::CreateObject() };
}
VincentDM
  • 469
  • 6
  • 17

1 Answers1

1

I'm wondering why this code compiles correctly. Since the copy-constructor and assignment-operator are deleted, I thought these mechanics would not be available.

Your code wouldn't compile with C++11 or C++14. However, since C++17 – thanks to guaranteed copy elision – a function can return a prvalue even if the type isn't copyable or movable.


Note that this only applies when returning prvalues. For example, if you define your CreateObject() so that the expression in the return statement isn't a prvalue but an lvalue:

static Object CreateObject() {
   Object object;
   return object; // <-- lvalue, not a prvalue
}

This function will not even compile with C++17:

error: call to deleted constructor of 'Object'

JFMR
  • 23,265
  • 4
  • 52
  • 76