1

Given this minimal example:

#include <iostream>
#include  <stdexcept>

using std::cout;
using std::endl;
using std::runtime_error;

struct MyObj
{
    MyObj() { cout << "constructed\n";}
    MyObj(const MyObj& r) { cout << "copied\n"; }
    MyObj(MyObj&& r) noexcept { throw runtime_error("I should terminate the program if uncaught"); }// = delete;
};

void Test(MyObj value)
{
    cout << "called\n"; 
}

int main()
{
    Test(MyObj());

    return 0;
}

Here I (perceive to) implement all constructors that would be compiler implemented if left absent. I also confirmed I can get each one to execute given traditional invocations. The basis of my confusion lies in what main does however.

Test requires that whatever expression is passed to it, once evaluated, can be used to construct a discrete and independent value of MyObj. My passing a previously non-existent default construction should yield an r-value reference &&.

Trying to construct a value from an && is a perfect signature match to the implemented move constructor. In fact, if I declare that constructor as deleted (= delete;), the compiler fails, saying a referenced function has been deleted, indicating my reasoning is at least marginally correct.

However, when I declare the function as written in the code example, an implementation destined to terminate the program if executed...nothing happens. I initially tried a cout to mirror the other constructors, and nothing happened, so I added the runtime_error to up the ante, or anti in this case. Nevertheless, the compiler warns a function declared noexcept assuredly throws one, but compiles anyway and runs , printing:

constructed
called

I'm left with two questions.

  1. Why does the compiler fail, claiming I am referencing a deleted function, if the executable will demonstrably never call it (in the =delete; case)?

  2. How is the parameter value in Test initialized from the r-value reference if neither by copy nor move?

NB: This is MSVC 14.11.25503 hosted by VS2017.

Edit: I just want to clarify, given the noexcept specification, that throw should terminate the program regardless.

melpomene
  • 84,125
  • 8
  • 85
  • 148
schulmaster
  • 413
  • 5
  • 16
  • I have heard of copy elision, but never has it manifested itself so overtly. Let me ask this then: Can the compiler fail due to errors it itself will mitigate completely? – schulmaster Sep 13 '18 at 04:23
  • @schulmaster Yes. Read the post. "If a call to a copy or move constructor is elided, that constructor must still exist and must be accessible. This ensures that copy elision does not allow copying objects which are not normally copyable, e.g. because they have a private or deleted copy/move constructor." – schulmaster Sep 13 '18 at 04:28

0 Answers0