C ++ copy constructor required, although not used
Does anyone know why the compiler needs a copy constructor for Foo in this situation:
#include <iostream>
#include <list>
class Foo {
public:
Foo() {}
Foo(const Foo &&f) noexcept {}
Foo(const Foo &f) = delete;
~Foo() {}
};
void passFoo2(const Foo&& f) {
std::list<Foo> l;
l.push_back(std::move(f));
}
int main(int argc, char **argv) {
Foo f;
passFoo2(std::move(f));
return 0;
}
The compiler (g ++) complains that the copy constructor has been removed. But in this case it is not necessary?
So what am I missing here?
x@ubuntu:/tmp/c++$ g++ stackoverflow.cxx -std=c++11
In file included from /usr/include/c++/4.9/list:63:0,
from stackoverflow.cxx:2:
/usr/include/c++/4.9/bits/stl_list.h: In instantiation of std::_List_node<_Tp>::_List_node(_Args&& ...) [with _Args = {const Foo&}; _Tp = Foo]:
/usr/include/c++/4.9/ext/new_allocator.h:120:4: required from void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::_List_node<Foo>; _Args = {const Foo&}; _Tp = std::_List_node<Foo>]
/usr/include/c++/4.9/bits/stl_list.h:514:8: required from std::list<_Tp, _Alloc>::_Node* std::list<_Tp, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const Foo&}; _Tp = Foo; _Alloc = std::allocator<Foo>; std::list<_Tp, _Alloc>::_Node = std::_List_node<Foo>]
/usr/include/c++/4.9/bits/stl_list.h:1688:63: required from void std::list<_Tp, _Alloc>::_M_insert(std::list<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const Foo&}; _Tp = Foo; _Alloc = std::allocator<Foo>; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<Foo>]
/usr/include/c++/4.9/bits/stl_list.h:1029:9: required from void std::list<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Foo; _Alloc = std::allocator<Foo>; std::list<_Tp, _Alloc>::value_type = Foo]
stackoverflow.cxx:14:30: required from here
/usr/include/c++/4.9/bits/stl_list.h:114:71: error: use of deleted function Foo::Foo(const Foo&)
: __detail::_List_node_base(), _M_data(std::forward<_Args>(__args)...)
^
stackoverflow.cxx:8:3: note: declared here
Foo(const Foo &f) = delete;
^
source to share
The method push_back
has two overloads:
void push_back( const T& value );
void push_back( T&& value );
If you are using the former, T
( Foo
in your case) there should be "CopyInsertable". If you are using the second one, it must be "MoveInsertable".
Your function passFoo2
is referenced const Foo&&
, and since it is const
-qualified (see note below), the first overload is the best match. Thus, an overload is called which requires your class Foo
to be copyable.
Note: The function std::move
transforms a named object to make it anonymous, and therefore is suitable for binding with an rvalue reference, but does not change the qualification of const
that anonymous object const Foo
after movement). For this reason, the first overload is called.
source to share
the reason is that push_back has an overload for Foo&&
not const Foo&&
.
const Foo&&
is overkill. It is a legal type, but its existence is anachronistic.
this compiles:
#include <iostream>
#include <list>
class Foo {
public:
Foo() {}
Foo( Foo &&f) noexcept {}
Foo(const Foo &f) = delete;
~Foo() {}
};
void passFoo2(Foo&& f) {
std::list<Foo> list;
list.push_back(std::move(f));
}
int main(int argc, char **argv) {
Foo f;
passFoo2(std::move(f));
return 0;
}
source to share