Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 "Non-movable" type [duplicate]

Possible Duplicate:
Why do C++11-deleted functions participate in overload resolution?

I have two questions about the following C++11 code:

#include <iostream>

using namespace std;

struct A {
  A()  { cout << "Default c-tor" << endl; }
  A(const A&)  { cout << "Copy c-tor" << endl; }
  A(A&&) = delete;
};

A f()
{
 A a;
 return a;
}

int main()
{
  A b = f();
  return 0;
}

I get the following compile errors with gcc and clang

gcc-4.7.2 (g++ --std=c++11 main.cpp):

main.cpp: In function ‘A f()’:
main.cpp:16:9: error: use of deleted function ‘A::A(A&&)’
main.cpp:8:2: error: declared here
main.cpp: In function ‘int main()’:
main.cpp:21:10: error: use of deleted function ‘A::A(A&&)’
main.cpp:8:2: error: declared here

clang-3.0 (clang++ --std=c++11 main.cpp):

main.cpp:19:4: error: call to deleted constructor of 'A'
        A b = f();
          ^   ~~~
main.cpp:8:2: note: function has been explicitly marked deleted here
        A(A&&) = delete;
        ^
1 error generated.
  • Shouldn't the compiler use the copy constructor if the move constructor is explicitly deleted?
  • Does anyone know any use for "non-movable" types?

Thanks in advance.

like image 525
lucasmrod Avatar asked Dec 29 '12 20:12

lucasmrod


Video Answer


4 Answers

A(A&&) = delete;

Declaring and defining it as delete does still declare it, and does not make it completely non-existent. Rather, it's similar (but not identical) to declaring it empty and private. Like so:

private: 
  A(A&&){}

In fact, that was the trick sometimes used for other operators before = delete was available. Again, it exists in the sense of lookup, but calling it is not ever allowed and in C++ calling permissions are (in almost or all cases) done after everything else, such as overload resolution, name lookup.

The standard actually say (8.4.3)

A deleted function is implicitly inline.

And there's noting (that I find) saying that deleted functions should not participate in name lookup.

Also, from 8.4.3

A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated.

like image 104
Johan Lundberg Avatar answered Oct 22 '22 00:10

Johan Lundberg


When you delete the move constructor, it doesn't remove it from the set of functions found by name lookup. Whenever your code would normally use the move constructor, you will get an error because, even though it was found, it has been deleted.

You have two moves in your code. The first is when you return a because when copy elision is possible and the object that would be copied is designated by an lvalue (a, here), it is treated as a move. The second is in the assignment A b = f(), because a f() is giving you a temporary that has not yet been bound to a reference.

If you want the copy constructor to be found rather than the deleted move constructor, you should just get rid of your deleted definition.

like image 25
Joseph Mansfield Avatar answered Oct 22 '22 00:10

Joseph Mansfield


This is a bit of a research task but I think declaring a move constructor states that the move constructor is to be considered. When it then gets deleted, it means that objects can be moved where they could be moved if there were a move constructor. If you want an object which isn't moved but copied, you'd just declare a copy constructor and you wouldn't mention the move constructor.

I haven't quite found the statement in the standard, yet, which explicitly states the above but there is Note in 12.8 [class.copy] paragraph 9 backing up part the above statement:

[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. —end note ]

like image 27
Dietmar Kühl Avatar answered Oct 22 '22 00:10

Dietmar Kühl


From C++ Working Draft 2012-11-02

8.4.3 Deleted definitions [dcl.fct.def.delete]
...
2 A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function is overloaded, it is referenced only if the function is selected by overload resolution. — end note ]
...
4 A deleted function is implicitly inline.

Since the deleted move constructor is referenced, the program is ill-formed.

A "usage" for a non-movable type could be to prevent moving, and so prevent returning a local object. I haven't seen such a usage myself and I don't know whether this makes sense at all, but YMMV.

like image 40
Olaf Dietsche Avatar answered Oct 22 '22 01:10

Olaf Dietsche