3

I've got an Action class that looks like this (in its stripped down form):

struct Action {

explicit Action(...some parameters...); // I only use this to construct Action objects

Action(const Action&) = delete; // Don't want copy constructor
Action(Action&&) = delete; // Same for move constructor

}

In some other translation unit, I have tried to do this:

Action action = someMethodForGettingActions(); // The method returns Action objects by rvalue

Visual Studio's Intellisense wants to hang me for this, justifiably. It says it can't access the move constructor. Yet this compiles and runs as expected. What's going on here? Is this some compiler optimization playing mind tricks on me?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Mark
  • 621
  • 1
  • 9
  • 17
  • Which intellisense parser specifically? Not all the IDE's use the same. – πάντα ῥεῖ Jul 03 '15 at 19:56
  • I'm using Visual Studio 2013. – Mark Jul 03 '15 at 19:57
  • 3
    This takes advantage of return value optimisation, but the compiler should forbid compilation because you have deleted the `const Action&` constructor, even though it doesn't actually need to use it. – Dave Jul 03 '15 at 19:59
  • @Dave It does though. And it's driving me nuts. Try it yourself. – Mark Jul 03 '15 at 20:14
  • 1
    It doesn't in GCC. This is almost certainly a Visual Studio compiler bug: https://ideone.com/wePDoN – Dave Jul 03 '15 at 20:26
  • https://ideone.com/rDEcyK I have modified it a bit to fit my case, but it doesn't compile either. Definitely a VS quirk. – Mark Jul 03 '15 at 20:31
  • 2
    [MSVC bug](https://connect.microsoft.com/VisualStudio/feedback/details/1010149/c-unrvo-optimization-causes-delete-function-qualifier-to-be-ignored-allowing-invalid-c-code-to-compile-and-run). Your example in the comment above fails to compile on VS2015. Test it [here](http://webcompiler.cloudapp.net/). – Praetorian Jul 03 '15 at 20:49
  • @Praetorian I would mark this as the accepted question if I could. This settles it then. – Mark Jul 03 '15 at 20:52

1 Answers1

2

It is a Return Value Optimization at work. It is actually permitted by C++11 standard. Check the accepted answer of:

c++11 Return value optimization or move?

The question there was a bit different, but the answer fits your problem.

Community
  • 1
  • 1
CygnusX1
  • 20,968
  • 5
  • 65
  • 109
  • So the compiler just blatantly lets you compile wrong code because it knows it will be optimized out? Is RVO really this taken for granted nowadays? – Mark Jul 03 '15 at 20:25
  • The compiler is still supposed to reject compilation of such code if the copy & move constructor is explicitly forbidden. The fact that they are not actually used is irrelevant. Try the compiling the same code with GCC. – Dave Jul 03 '15 at 20:27
  • @Dave It appears (based on the specification quoted in that link) that an implementation is both allowed to accept the code, and allowed to reject it if it does not want to perform copy elision for whatever reason (note "is allowed to omit"). – John Colanduoni Jul 03 '15 at 20:29
  • 3
    @JohnColanduoni elision rules apply only *after* the validity of the program is established. See for example http://en.cppreference.com/w/cpp/language/copy_elision "Even when copy elision takes place and the copy-/move-constructor is not called, it must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed." – Dave Jul 03 '15 at 20:42