2013-12-14 105 views
2

我有以下三段代碼來演示一個容易重現的問題。Clang only:一對<path, path>可以放入一個向量;所以可以配對<unique_ptr,unique_ptr>;但不是對<path,unique_ptr>:爲什麼?

using namespace boost::filesystem; 
using namespace std; 

int main() 
{ 

    path dummy_path; 

    // Snippet 1 
    // Two paths 
    // Succeeds 
    // 
    // vector<pair<path, path>> myvec; 
    // myvec.emplace_back(dummy_path, dummy_path); 

    // Snippet 2 
    // Two unique_ptr's 
    // Succeeds 
    // 
    // vector<pair<unique_ptr<int>, unique_ptr<int>>> myvec; 
    // myvec.emplace_back(unique_ptr<int>(new int(13)), unique_ptr<int>(new int(12))); 

    // Snippet 3 
    // A path and a unique_ptr. 
    // 
    // **FAILS** on Clang, succeeds in Visual Studio 
    // 
    vector<pair<path, unique_ptr<int>>> myvec; 
    myvec.emplace_back(dummy_path, unique_ptr<int>(new int(12))); 

} 

這裏是關於鏘編譯錯誤:

error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<int, std::__1::default_delete<int> >'(在參考了對所述第二構件,所述unique_ptr,很明顯)。

看來由於某種原因,失敗的情況下指出造成該對的複製構造函數,而不是移動構造函數被調用。

這是OS X 10.8.5上的Clang 5.0.2。 (和Windows 7 64位上的VS 11.0.60610.01 Update 3)。

在我的實際應用中,數據類型比較複雜,但是錯誤歸結爲這個問題中描述的錯誤。

我的問題是雙重的:爲什麼Clang上的案例顯示失敗,即使其他兩種涵蓋兩種數據類型的情況都成功了?

但也許更重要的是:我能做些什麼來解決這個問題?因爲我的實際應用程序更復雜,所以我沒有選擇不將給定對的emplace(或其他類似對象)放入向量中 - 但是如果有任何其他方法,我可以通過此Clang問題來獲得該對進入那個矢量,我會非常高興。

+0

是否'myvec.emplace_back(STD ::移動(dummy_path)的unique_ptr (新INT(12)));'工作? – jrok

+0

@jrok - 我試過(並且會包含在問題中,但希望儘可能簡化問題)。答案是否定的。否。在'path','unique_ptr'或這兩者中添加'std :: move()'都會失敗。 –

+0

來自[Coliru]的Clang版本(http://coliru.stacked-crooked.com/a/5e9f8c7e26df3674)編譯得很好。 – jrok

回答

2

這是libC++中的一個錯誤,很抱歉。它已被固定在主幹尖端。我相信你可以解決它通過添加以下到您的編譯命令:

-D_LIBCPP_TRIVIAL_PAIR_COPY_CTOR 
+0

說到快速反應 - 在報告2小時內解決問題。恭喜,並且謝謝。 –

+0

以下是錯誤報告的鏈接。 http://llvm.org/bugs/show_bug.cgi?id=18249#c1(對於任何感興趣的人)。 –

+0

我的話含糊不清。它已經固定在主幹尖端。我希望我的建議解決方法正在爲您工作。 –

2

問題來自libC++標準庫,因爲它內部的構造函數少得多pair

I.e. libstd ++具有以下構造函數:

template<class _U2, class = typename 
     enable_if<is_convertible<_U2, _T2>::value>::type> 
constexpr pair(const _T1& __x, _U2&& __y) 
: first(__x), second(std::forward<_U2>(__y)) { } 

它允許您在Linux上編譯您的示例(使用clang ++)。但是libc的++僅具有:

pair(const pair&) = default; 
pair(pair&&) = default; 
constexpr pair(); 
pair(const T1& x, const T2& y);       // constexpr in C++14 
template <class U, class V> pair(U&& x, V&& y);   // constexpr in C++14 
template <class U, class V> pair(const pair<U, V>& p); // constexpr in C++14 
template <class U, class V> pair(pair<U, V>&& p);  // constexpr in C++14 
template <class... Args1, class... Args2> 
    pair(piecewise_construct_t, tuple<Args1...> first_args, 
     tuple<Args2...> second_args); 

我想,該pair(const T1& x, const T2& y);由於第一個參數是非右值參考應用。


「硬核」解決方案是將這個構造函數手動放置在系統庫中。 pairutility文件中定義。如果你想能夠在其他地方編譯你的代碼,你可以將修改過的libC++打包到你的項目中 - 這真的沒什麼大不了的。

+0

謝謝。問題是,要在Xcode中設置什麼樣的設置來構建示例代碼?沒有組合我一直在嘗試過去一小時的作品。 –

+0

@DanNissenbaum看到我的答案更新 - 沒有標誌可以幫助。 –

+0

非常感謝。如果您可以在將修改過的'libC++'捆綁到項目中的第一步或第二步中提到,我會很感激。我在Windows上更有經驗。 –

相關問題