c++c++11copy-elision

How to enforce copy elision, why it won't work with deleted copy constructor?


I have an uncopiable class. Copying this would be problematic. I want to guarantee that it won't be ever copied, so I made its copy constructor deleted:

class A {
  public:
    A();
    A(const A&) = delete;
};

A fun() {
  return A();
};

int main() {
  A a = fun();
};

Unfortunately, g++ won't compile this on the reason:

t.cc: In function ‘A fun()’:
t.cc:8:12: error: use of deleted function ‘A::A(const A&)’
   return A();
            ^
t.cc:4:5: note: declared here
     A(const A&) = delete;
     ^
t.cc: In function ‘int main()’:
t.cc:12:13: error: use of deleted function ‘A::A(const A&)’
   A a = fun();
             ^
t.cc:4:5: note: declared here
     A(const A&) = delete;
     ^

But this is a very clear situation where copy elision should be used, so the copy constructor shouldn't be ever called. Why is it so?


Solution

  • Until C++17 copy elision is an optimization the compiler is not required to do, so classes must be copyable since the compiler might want to copy (even if it actually does not). In C++17 copy elision will be guaranteed in many cases and then classes won't need copy ctors.

    See also:

    http://en.cppreference.com/w/cpp/language/copy_elision

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

    https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/ (the bit about "Guaranteed copy elision")

    You could perhaps use the old trick of declaring the copy constructor in your class but not actually implement it? That should please the compiler as long as it does not actually invoke the copy ctor. I didn't test that, but I believe it should work for your case until C++17 arrives.