Why does the following code work, although I explicitly deleted the move constructor?

 class X { public: X() = default; X(const X&) = delete; X(X&&) = delete; int val = 42; }; template<typename T> int foo(T x) { return x.val; } int main() { X x1; //X x2{x1}; // error //X x3{std::move(x1)}; // error //foo(x1); // error //foo(std::move(x1)); //error foo(X{}); // OK? } 

What restrictions are imposed on type T besides that it must have a member val that is cast to an int ? Is it possible to ban the last transfer?

  • When using C ++ 17 in foo(X{}); move the constructor is not called. The last pass can be disabled by disabling the default constructor. Well, or you can use the older standards of the language. - VTT

1 answer 1

Because in the line foo(X{}); There is no copying or moving. There is a materialization of the prvalue into an object named x . Materialization, as can be understood from the term itself, is the direct creation of an object from a prvalue, without any intermediate replicas / movements. It is impossible to prohibit it, it is “sewn” in the C ++ standard 17.

I wrote more about this here .

  • Understand, thanks, I will read now - credo