2013-05-05 75 views
7

下面的代碼是否應該根據C++ 11產生編譯錯誤(如果是這樣,爲什麼?),還是VC11有問題?對持有unique_ptr向量的對象列表進行排序

#include <vector> 
#include <list> 
#include <memory> 
struct A 
{ 
    std::vector<std::unique_ptr<int>> v; 
}; 
int main() 
{ 
    std::list<A> l; 
    l.sort([](const A& a1, const A& a2){ return true; }); 
} 

的Visual C++ 2012產生以下編譯錯誤:

1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(606): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 
1>   with 
1>   [ 
1>    _Ty=int 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 11.0\vc\include\memory(1447) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr' 
1>   with 
1>   [ 
1>    _Ty=int 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' 
1>   with 
1>   [ 
1>    _Ty=std::unique_ptr<int> 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(751) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled 
1>   with 
1>   [ 
1>    _Ty=std::unique_ptr<int> 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits(743) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled 
1>   with 
1>   [ 
1>    _Ty=std::unique_ptr<int> 
1>   ] 
1>   c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector(655) : see reference to class template instantiation 'std::is_empty<_Ty>' being compiled 
1>   with 
1>   [ 
1>    _Ty=std::allocator<std::unique_ptr<int>> 
1>   ] 
1>   d:\test2\test2.cpp(213) : see reference to class template instantiation 'std::vector<_Ty>' being compiled 
1>   with 
1>   [ 
1>    _Ty=std::unique_ptr<int> 
1>   ] 
+0

作爲參考,我可以在Clang和GCC編譯這很好。所以它不是你的編譯器就是你的設置。 – chrisaycock 2013-05-05 14:31:32

+0

@chrisaycock很好,我們將在Microsoft Connect上創建另一個VC11錯誤報告... – PowerGamer 2013-05-05 14:39:34

+3

我寧願放棄它。 – 2013-05-05 14:41:08

回答

0

它是用Visual C的一個問題++ 2012(Microsoft在連接承認:Compile error in C++ code sorting a list of objects holding a vector of unique_ptr),它已經被固定在Visual C++ 2013年

另外,我想指出的問題與事實無關,Visual C++不會隱式生成移動構造函數。如果你明確地刪除了結構A中的所有拷貝和移動構造函數(是的,在我的原始示例中,將不可能將類型A的對象插入到列表中,但這不是那麼重要),代碼仍然不應該複製或移動任何對象,並因此產生編譯錯誤:

#include <vector> 
#include <list> 
#include <memory> 
struct A 
{ 
    std::vector<std::unique_ptr<int>> v; 
    A(A&&) = delete; 
    A(const A&) = delete; 
}; 
int main() 
{ 
    std::list<A> l; 
    l.sort([](const A& a1, const A& a2){ return true; }); 
} 
4

這是 「與VC有問題」,但僅僅是因爲你濫用的Visual Studio。

VC++實現了r值引用,但它確實執行了而不是實現了編譯器生成的移動構造函數/賦值操作符。這意味着,如果你想要一個類型是可移動的,你必須自己寫一個類型。

A不是一個可移動的類型,所以各種std::list函數將嘗試複製它們。當他們試圖複製vectorunique_ptr時,他們會失敗。因此編譯器錯誤。

如果你想在VC++中感知移動的對象,你必須自己編寫移動構造函數/賦值。

+2

爲什麼排序列表(而不是向量)需要複製任何東西?不排序是否應該通過更改雙鏈表節點的「上一個」和「下一個」指針來實現? – PowerGamer 2013-05-05 18:51:48

3

這個問題真的出現在VC11中,正如it doesn't implement C++11 feature of automatically generating move operations(正如Nicol Bolas所指出的那樣)。

以下代碼與VC10 SP1一起編譯;在此代碼示例中,移動構造函數是明確寫入(而不是移動operator=,則使用copy-and-swap idiom)。

#include <algorithm> // for std::swap (for copy-and-swap idiom) 
#include <list> 
#include <memory> 
#include <vector> 

struct A 
{ 
    std::vector<std::unique_ptr<int>> v; 

    A(A&& other) 
     : v(std::move(other.v)) 
    { 
    } 

    A& operator=(A other) 
    { 
     swap(*this, other); 
     return *this; 
    } 

    friend void swap(A& lhs, A& rhs) 
    { 
     using std::swap; 
     swap(lhs.v, rhs.v); 
    } 
}; 

int main() 
{ 
    std::list<A> l; 
    l.sort([](const A& , const A&){ return true; }); 
} 
+1

我很清楚移動構造函數是什麼,以及VC11不隱式生成它們的事實。這並不能解釋爲什麼VC11希望在執行* list *排序時複製或移動類型A的對象。 – PowerGamer 2013-05-06 06:38:26

+0

那麼你可以在STL源代碼中找到答案。我明白你的觀點。 – 2013-05-06 09:36:16

相關問題