Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving std::list<std::unique_ptr> into vector attempts to reference a deleted function

Tags:

Here is a complete program which reproduces my problem.

#include <vector>
#include <list>
#include <memory>
#include <utility>

int main()
{
    std::vector<std::list<std::unique_ptr<int>>> v;

    std::list<std::unique_ptr<int>> l;
    l.push_back(std::make_unique<int>(0));
    l.push_back(std::make_unique<int>(1));

    v.push_back(std::move(l)); // error
}

On the last line the compiler is complaining that the deleted copy constructor of std::unique_ptr is being referenced.

Since I'm moving the list into the vector, I assume no copy constructors will be called on the elements of the list.

Why is this happening? How would I go about fixing it?

I'm using MSVC 2017.

live example on godbolt

Full text from the error:

example.cpp
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xmemory0(840): error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
        with
        [
            _Ty=int
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/memory(1857): note: see declaration of 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr'
        with
        [
            _Ty=int
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xmemory0(959): note: see reference to function template instantiation 'void std::allocator<_Other>::construct<_Objty,const std::unique_ptr<int,std::default_delete<_Ty>>&>(_Objty *,const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled
        with
        [
            _Other=std::_List_node<std::unique_ptr<int,std::default_delete<int>>,void *>,
            _Objty=std::unique_ptr<int,std::default_delete<int>>,
            _Ty=int
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xmemory0(959): note: see reference to function template instantiation 'void std::allocator<_Other>::construct<_Objty,const std::unique_ptr<int,std::default_delete<_Ty>>&>(_Objty *,const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled
        with
        [
            _Other=std::_List_node<std::unique_ptr<int,std::default_delete<int>>,void *>,
            _Objty=std::unique_ptr<int,std::default_delete<int>>,
            _Ty=int
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xmemory0(1097): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,const std::unique_ptr<int,std::default_delete<int>>&>(std::allocator<_Other> &,_Objty *,const std::unique_ptr<int,std::default_delete<int>> &)' being compiled
        with
        [
            _Alloc=std::allocator<std::_List_node<std::unique_ptr<int,std::default_delete<int>>,void *>>,
            _Ty=std::unique_ptr<int,std::default_delete<int>>,
            _Other=std::_List_node<std::unique_ptr<int,std::default_delete<int>>,void *>,
            _Objty=std::unique_ptr<int,std::default_delete<int>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xmemory0(1096): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,const std::unique_ptr<int,std::default_delete<int>>&>(std::allocator<_Other> &,_Objty *,const std::unique_ptr<int,std::default_delete<int>> &)' being compiled
        with
        [
            _Alloc=std::allocator<std::_List_node<std::unique_ptr<int,std::default_delete<int>>,void *>>,
            _Ty=std::unique_ptr<int,std::default_delete<int>>,
            _Other=std::_List_node<std::unique_ptr<int,std::default_delete<int>>,void *>,
            _Objty=std::unique_ptr<int,std::default_delete<int>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(853): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Other>>::construct<_Ty,const std::unique_ptr<int,std::default_delete<int>>&>(_Ty *,const std::unique_ptr<int,std::default_delete<int>> &)' being compiled
        with
        [
            _Other=std::_List_node<std::unique_ptr<int,std::default_delete<int>>,void *>,
            _Ty=std::unique_ptr<int,std::default_delete<int>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(851): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Other>>::construct<_Ty,const std::unique_ptr<int,std::default_delete<int>>&>(_Ty *,const std::unique_ptr<int,std::default_delete<int>> &)' being compiled
        with
        [
            _Other=std::_List_node<std::unique_ptr<int,std::default_delete<int>>,void *>,
            _Ty=std::unique_ptr<int,std::default_delete<int>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(1086): note: see reference to function template instantiation 'std::_List_node<std::unique_ptr<int,std::default_delete<_Ty>>,void *> *std::_List_buy<std::unique_ptr<_Ty,std::default_delete<_Ty>>,_Alloc>::_Buynode<const std::unique_ptr<_Ty,std::default_delete<_Ty>>&>(std::_List_node<std::unique_ptr<_Ty,std::default_delete<_Ty>>,void *> *,std::_List_node<std::unique_ptr<_Ty,std::default_delete<_Ty>>,void *> *,const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled
        with
        [
            _Ty=int,
            _Alloc=std::allocator<std::unique_ptr<int,std::default_delete<int>>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(1085): note: see reference to function template instantiation 'std::_List_node<std::unique_ptr<int,std::default_delete<_Ty>>,void *> *std::_List_buy<std::unique_ptr<_Ty,std::default_delete<_Ty>>,_Alloc>::_Buynode<const std::unique_ptr<_Ty,std::default_delete<_Ty>>&>(std::_List_node<std::unique_ptr<_Ty,std::default_delete<_Ty>>,void *> *,std::_List_node<std::unique_ptr<_Ty,std::default_delete<_Ty>>,void *> *,const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled
        with
        [
            _Ty=int,
            _Alloc=std::allocator<std::unique_ptr<int,std::default_delete<int>>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(1463): note: see reference to function template instantiation 'void std::list<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::_Insert<const std::unique_ptr<_Ty,std::default_delete<_Ty>>&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>,std::_Iterator_base0>,const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled
        with
        [
            _Ty=int
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(1463): note: see reference to function template instantiation 'void std::list<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::_Insert<const std::unique_ptr<_Ty,std::default_delete<_Ty>>&>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>,std::_Iterator_base0>,const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled
        with
        [
            _Ty=int
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(1423): note: see reference to function template instantiation 'void std::list<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
        with
        [
            _Ty=int,
            _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<int,std::default_delete<int>>>>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(1422): note: see reference to function template instantiation 'void std::list<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::_Insert_range<_Iter>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>,std::_Iterator_base0>,_Iter,_Iter,std::forward_iterator_tag)' being compiled
        with
        [
            _Ty=int,
            _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<int,std::default_delete<int>>>>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(939): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<int,std::default_delete<_Ty>>>>> std::list<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>>>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>>,_Iter,_Iter)' being compiled
        with
        [
            _Ty=int,
            _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<int,std::default_delete<int>>>>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(939): note: see reference to function template instantiation 'std::_List_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<int,std::default_delete<_Ty>>>>> std::list<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::insert<std::_List_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>>>(std::_List_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>>,_Iter,_Iter)' being compiled
        with
        [
            _Ty=int,
            _Iter=std::_List_const_iterator<std::_List_val<std::_List_simple_types<std::unique_ptr<int,std::default_delete<int>>>>>
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/list(935): note: while compiling class template member function 'std::list<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::list(const std::list<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &)'
        with
        [
            _Ty=int
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xmemory0(840): note: see reference to function template instantiation 'std::list<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::list(const std::list<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &)' being compiled
        with
        [
            _Ty=int
        ]
<source>(10): note: see reference to class template instantiation 'std::list<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
        with
        [
            _Ty=int
        ]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/memory(1857): note: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': function was explicitly deleted
        with
        [
            _Ty=int
        ]
Microsoft (R) C/C++ Optimizing Compiler Version 19.10.25017 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.
Compiler exited with result code 2
like image 423
DeiDei Avatar asked Apr 05 '17 15:04

DeiDei


People also ask

Can Unique_ptr be moved?

A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it. We recommend that you restrict an object to one owner, because multiple ownership adds complexity to the program logic.

What happens when Unique_ptr goes out of scope?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.


1 Answers

Since I'm moving the list into the vector, I assume no copy constructors will be called on the elements of the list.

The move constructor of std::list is not noexcept ([list.overview]), so std::vector needs to call its copy constructor in order to provide strong exception guarantee. The copy constructor of std::list (unsurprisingly) calls copy constructors on the elements of the list.

Apparently libstdc++ declares std::list's move constructor as noexcept, which is permitted but not required by the standard. ([res.on.exception.handling]/5)

like image 59
cpplearner Avatar answered Oct 24 '22 02:10

cpplearner