首页 > 解决方案 > 仅移动结构在 MSVC 中的 std::map 中调用复制构造函数

问题描述

我有一个地图矢量。地图包含一个只能移动的结构。

当我尝试与此结构交互时,我在 MSVC 上遇到编译错误。

这是一个示例代码:

#include <map>
#include <memory>
#include <vector>

struct S {
    std::unique_ptr<int> a;
};

int main() {
    std::vector<std::map<float, S>> s;
    
    s.emplace_back();

    return 0;
}

我收到一条错误s.emplace_back()消息:

C:/data/msvc/14.28.29333/include\xmemory(701): error C2280: 'std::pair<const float,S>::pair(const std::pair<const float,S> &)': attempting to reference a deleted function
C:/data/msvc/14.28.29333/include\utility(209): note: see declaration of 'std::pair<const float,S>::pair'
C:/data/msvc/14.28.29333/include\utility(209): note: 'std::pair<const float,S>::pair(const std::pair<const float,S> &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'S::S(const S &)'
<source>(7): note: 'S::S(const S &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)'
C:/data/msvc/14.28.29333/include\memory(2686): note: 'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)': function was explicitly deleted
C:/data/msvc/14.28.29333/include\xtree(358): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,_Ty&>(_Alloc &,_Objty *const ,_Ty &)' being compiled
        with
        [
            _Alloc=std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<std::allocator<std::pair<const float,S>>>::void_pointer>>,
            _Ty=std::pair<const float,S>,
            _Objty=std::pair<const float,S>
        ]
C:/data/msvc/14.28.29333/include\xtree(358): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,_Ty&>(_Alloc &,_Objty *const ,_Ty &)' being compiled
        with
        [
            _Alloc=std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<std::allocator<std::pair<const float,S>>>::void_pointer>>,
            _Ty=std::pair<const float,S>,
            _Objty=std::pair<const float,S>
        ]
C:/data/msvc/14.28.29333/include\xtree(2027): note: see reference to function template instantiation 'std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer>::_Buynode<std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer>>,_Ty&>(std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer>> &,std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *,_Ty &)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Ty=std::pair<const float,S>
        ]
C:/data/msvc/14.28.29333/include\xtree(2027): note: see reference to function template instantiation 'std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer>::_Buynode<std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer>>,_Ty&>(std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer>> &,std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *,_Ty &)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Ty=std::pair<const float,S>
        ]
C:/data/msvc/14.28.29333/include\xtree(1741): note: see reference to function template instantiation 'std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Buynode<std::pair<const float,S>&>(std::pair<const float,S> &)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>
        ]
C:/data/msvc/14.28.29333/include\xtree(1741): note: see reference to function template instantiation 'std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Buynode<std::pair<const float,S>&>(std::pair<const float,S> &)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>
        ]
C:/data/msvc/14.28.29333/include\xtree(1762): note: see reference to function template instantiation 'std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy_or_move<std::pair<const float,S>,std::integral_constant<bool,false>>(std::pair<const float,S> &,std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy_tag,_Is_set)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>,
            _Is_set=std::integral_constant<bool,false>
        ]
C:/data/msvc/14.28.29333/include\xtree(1762): note: see reference to function template instantiation 'std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy_or_move<std::pair<const float,S>,std::integral_constant<bool,false>>(std::pair<const float,S> &,std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy_tag,_Is_set)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>,
            _Is_set=std::integral_constant<bool,false>
        ]
C:/data/msvc/14.28.29333/include\xtree(1728): note: see reference to function template instantiation 'std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy_nodes<_Moveit>(std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *,_Moveit)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>,
            _Moveit=std::_Tree<std::_Tmap_traits<float,S,std::less<float>,std::allocator<std::pair<const float,S>>,false>>::_Copy_tag
        ]
C:/data/msvc/14.28.29333/include\xtree(1728): note: see reference to function template instantiation 'std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy_nodes<_Moveit>(std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *,std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer> *,_Moveit)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>,
            _Moveit=std::_Tree<std::_Tmap_traits<float,S,std::less<float>,std::allocator<std::pair<const float,S>>,false>>::_Copy_tag
        ]
C:/data/msvc/14.28.29333/include\xtree(902): note: see reference to function template instantiation 'void std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy<std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy_tag>(const std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>> &,_Moveit)' being compiled
        with
        [
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>,
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Moveit=std::_Tree<std::_Tmap_traits<float,S,std::less<float>,std::allocator<std::pair<const float,S>>,false>>::_Copy_tag
        ]
C:/data/msvc/14.28.29333/include\xtree(902): note: see reference to function template instantiation 'void std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy<std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Copy_tag>(const std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>> &,_Moveit)' being compiled
        with
        [
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>,
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Moveit=std::_Tree<std::_Tmap_traits<float,S,std::less<float>,std::allocator<std::pair<const float,S>>,false>>::_Copy_tag
        ]
C:/data/msvc/14.28.29333/include\map(111): note: see reference to function template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Tree<std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer>>>(const std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>> &,_Any_alloc &&)' being compiled
        with
        [
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>,
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Any_alloc=std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<std::allocator<std::pair<const float,S>>>::void_pointer>>
        ]
C:/data/msvc/14.28.29333/include\map(111): note: see reference to function template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::_Tree<std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<_Alloc>::void_pointer>>>(const std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>> &,_Any_alloc &&)' being compiled
        with
        [
            _Kty=float,
            _Ty=S,
            _Pr=std::less<float>,
            _Alloc=std::allocator<std::pair<const float,S>>,
            _Any_alloc=std::allocator<std::_Tree_node<std::pair<const float,S>,std::_Default_allocator_traits<std::allocator<std::pair<const float,S>>>::void_pointer>>
        ]
C:/data/msvc/14.28.29333/include\map(111): note: while compiling class template member function 'std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>>::map(const std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>> &)'
C:/data/msvc/14.28.29333/include\xmemory(701): note: see reference to function template instantiation 'std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>>::map(const std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>> &)' being compiled
C:/data/msvc/14.28.29333/include\vector(687): note: see reference to class template instantiation 'std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>>' being compiled
C:/data/msvc/14.28.29333/include\vector(705): note: see reference to function template instantiation 'void std::vector<std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>>,std::allocator<std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>>>>::_Emplace_back_with_unused_capacity<>(void)' being compiled
<source>(12): note: see reference to function template instantiation 'void std::vector<std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>>,std::allocator<std::map<float,S,std::less<float>,std::allocator<std::pair<const float,S>>>>>::emplace_back<>(void)' being compiled
Compiler returned: 2

您可以在此处查看 Godbolt 上的实际代码:https ://godbolt.org/z/qvMPYdc5q

它适用于 clang 和 GCC,但不适用于 MSVC(最新和 v19.28)。

我在某处看到 MSVC 要求 ctor & dtor 为 noexcept 以使地图使用移动构造函数,但即使在为S结构定义 noexcept ctors & dtors 时,我也会遇到相同的错误。

MSVC 在做什么需要在这段代码中复制?我怎样才能在这里强制移动?

标签: c++visual-c++

解决方案


推荐阅读