2016-02-12 35 views
2

我一直在使用一對類。前者存儲元數據,後者用作容器並支持基於元數據的各種索引。精簡版本在下面發佈。std :: set成員變量複製,而不是移動類實例時移動

後一類使用std :: set來管理前一類的對象集合,原因與相關的穩定性有關(指向組成元數據對象的指針在添加和刪除元素時必須保持有效)。

由於我不明白的原因,索引類的set成員正在調用它的(刪除的)複製構造函數,即使移動語義應該被調用。我編譯了Apple LLVM 7.0.0(使用libC++)和GCC 4.9(libstdC++),並收到類似的錯誤。

移動構造函數在這種情況下不能被調用嗎?

#include <ctime> 
#include <functional> 
#include <set> 
#include <string> 
#include <memory> 
#include <vector> 

// used to store meta data about some class T 
template<typename T> 
struct Foo { 
    std::unique_ptr<T> data; // T being some abstract class 
    std::string label; 
    std::time_t stamp; 
    const Foo* parentPtr; 

    Foo(std::unique_ptr<T>&& data, 
     const std::string& label, 
     const std::time_t stamp, 
     const Foo* parent) : data(std::move(data)), 
         label(label), 
         stamp(stamp), 
         parentPtr(parent){} 
}; 

// ordering of Foo objects should be in terms of the label. Necessary for std::set. 
namespace std { 
template<typename T> 
struct less< Foo<T> > { 
    constexpr bool 
    operator()(const Foo<T>& lhs, 
       const Foo<T>& rhs) const { 
    return lhs.label < rhs.label; 
    } 
}; 
} 

// collection of Foos 
template<typename T> 
class Bar{ 
public: 
    Bar() = default; 
    Bar(std::set< Foo<T> >&& foos) : foos(std::move(foos)){} 
    ~Bar() = default; 

    // irrelevant helpers omitted 

    std::set< Foo<T> > foos; 
}; 

// causes compilation to fail 
auto returnTest0 = [](){ 
    std::set< Foo< std::vector<int> > > S = {}; 
    return Bar< std::vector<int> >(std::move(S)); 
    // This is an r-value. Why isn't RVO or move semantics occuring? 
}; 

// also causes compilation to fail 
auto returnTest1 = [](Bar< std::vector<int> >&& b){ 
    return std::move(b); 
}; 

從GCC 4.9的編譯器錯誤被再現下面

 In file included from /usr/include/x86_64-linux-gnu/c++/4.9/bits/c++allocator.h:33:0, 
        from /usr/include/c++/4.9/bits/allocator.h:46, 
        from /usr/include/c++/4.9/string:41, 
        from /usr/include/c++/4.9/stdexcept:39, 
        from /usr/include/c++/4.9/array:38, 
        from /usr/include/c++/4.9/tuple:39, 
        from /usr/include/c++/4.9/functional:55, 
        from 2: 
    /usr/include/c++/4.9/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Foo<std::vector<int> >; _Args = {const Foo<std::vector<int, std::allocator<int> > >&}; _Tp = std::_Rb_tree_node<Foo<std::vector<int> > >]': 

    /usr/include/c++/4.9/bits/alloc_traits.h:253:4: required from 'static std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = Foo<std::vector<int> >; _Args = {const Foo<std::vector<int, std::allocator<int> > >&}; _Alloc = std::allocator<std::_Rb_tree_node<Foo<std::vector<int> > > >; std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> = void]' 

    /usr/include/c++/4.9/bits/alloc_traits.h:399:57: required from 'static 
decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = Foo<std::vector<int> >; _Args = {const Foo<std::vector<int, std::allocator<int> > >&}; _Alloc = std::allocator<std::_Rb_tree_node<Foo<std::vector<int> > > >; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]' 

    /usr/include/c++/4.9/bits/stl_tree.h:423:42: required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const Foo<std::vector<int, std::allocator<int> > >&}; _Key = Foo<std::vector<int> >; _Val = Foo<std::vector<int> >; _KeyOfValue = std::_Identity<Foo<std::vector<int> > >; _Compare = std::less<Foo<std::vector<int> > >; _Alloc = std::allocator<Foo<std::vector<int> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<Foo<std::vector<int> > >*]' 

    /usr/include/c++/4.9/bits/stl_tree.h:445:53: required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_clone_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type) [with _Key = Foo<std::vector<int> >; _Val = Foo<std::vector<int> >; _KeyOfValue = std::_Identity<Foo<std::vector<int> > >; _Compare = std::less<Foo<std::vector<int> > >; _Alloc = std::allocator<Foo<std::vector<int> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<Foo<std::vector<int> > >*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<Foo<std::vector<int> > >*]' 

    /usr/include/c++/4.9/bits/stl_tree.h:1207:43: required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_copy(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = Foo<std::vector<int> >; _Val = Foo<std::vector<int> >; _KeyOfValue = std::_Identity<Foo<std::vector<int> > >; _Compare = std::less<Foo<std::vector<int> > >; _Alloc = std::allocator<Foo<std::vector<int> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<Foo<std::vector<int> > >*; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<Foo<std::vector<int> > >*]' 

    /usr/include/c++/4.9/bits/stl_tree.h:676:50: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Rb_tree(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&) [with _Key = Foo<std::vector<int> >; _Val = Foo<std::vector<int> >; _KeyOfValue = std::_Identity<Foo<std::vector<int> > >; _Compare = std::less<Foo<std::vector<int> > >; _Alloc = std::allocator<Foo<std::vector<int> > >]' 
    /usr/include/c++/4.9/bits/stl_set.h:197:22: required from 'std::set<_Key, _Compare, _Alloc>::set(const std::set<_Key, _Compare, _Alloc>&) [with _Key = Foo<std::vector<int> >; _Compare = std::less<Foo<std::vector<int> > >; _Alloc = std::allocator<Foo<std::vector<int> > >]' 
    36:7: required from here 
    /usr/include/c++/4.9/ext/new_allocator.h:120:4: error: use of deleted function 'Foo<std::vector<int> >::Foo(const Foo<std::vector<int> >&)' 
     { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } 
     ^
    9:8: note: 'Foo<std::vector<int> >::Foo(const Foo<std::vector<int> >&)' is implicitly deleted because the default definition would be ill-formed: 
    9:8: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = std::vector<int>; _Dp = std::default_delete<std::vector<int> >]' 
    In file included from /usr/include/c++/4.9/memory:81:0, 
        from 5: 
    /usr/include/c++/4.9/bits/unique_ptr.h:356:7: note: declared here 
      unique_ptr(const unique_ptr&) = delete; 
    ^

回答

8

的用戶聲明的析構函數

~Bar() = default; 

抑制Bar的舉動構造的隱式生成並移動賦值運算符。

要麼刪除析構函數,或者明確違約,此舉特殊成員:

Bar(Bar&&) = default; 
Bar& operator=(Bar&&) = default;