2016-07-18 44 views
3

我在想這個。考慮這個:您是否可以使用初始化程序列表中的unique_ptr初始化STL容器?

#include <iostream> 
#include <map> 
#include <memory> 

int main() { 
    std::map< int, std::unique_ptr<int> > m = 
    { { 1, std::unique_ptr<int>(new int(3)) } }; 

    return(0); 
} 

這是C++ 11。它無法與GCC錯誤消息的長令來編譯,其中包括一個

/usr/include/c++/4.9/ext/new_allocator.h:120:4: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’ 
    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } 

是否有可能在所有做什麼,我想在這裏做什麼?我注意到,使用shared_ptr,它工作正常。是否有可能與unique_ptr做到這一點?如果是這樣,我錯過了什麼?如果不是,爲什麼不呢?

回答

4

一個initializer_list的元素號不能被修改。

unique_ptr不能被移動(因爲它是常量)並且它不能被複制(因爲它是一個移動類型),所以你被弄糊塗了。

+0

啊,謝謝。我懷疑像這樣的事情 - 「constexpr」似乎是一個線索。 –

+0

@ mike4ty4真正的線索,證明Marshall說的是'使用刪除函數對(const std :: pair <_T1, _T2>&)[with _T1 = const int; _T2 = std :: unique_ptr]'。也就是說:這是因爲它是一個拷貝構造函數,它會嘗試複製這兩個元素,但是當然,'std :: unique_ptr'是不可複製的。如果你設法調用它,移動構造函數會給你同樣的錯誤 –

0

當然,沒問題。

首先,智能的unique_ptr代理,所以我們可以創建並在const背景下移動它們:

template<class T> 
struct il_up { 
    mutable std::unique_ptr<T> ptr; 
    template<class U, 
    std::enable_if_t< std::is_convertible<U*, T*>{}, int>* =nullptr 
    > 
    il_up(std::unique_ptr<U> o): ptr(std::move(o)) {} 

    operator std::unique_ptr<T>() const { 
    return std::move(ptr); 
    } 
}; 

然後,我們希望這些信息存儲在一個initializer_list。即使它是const,它也可以通過unique_ptr

然後容器製作代理存儲臨時初始化列表:

template<class T> 
struct make_container { 
    std::initializer_list<T> il; 
    make_container(std::initializer_list<T> l):il(l) {} 

    template<class C> 
    operator C()&&{ 
    return {il.begin(), il.end()}; 
    } 
}; 

和我們正在這樣做:

std::vector<std::unique_ptr<int>> vec = make_container<il_up<int>>{ 
    std::make_unique<int>(1), std::make_unique<int>(2), 
    std::make_unique<int>(3), std::make_unique<int>(4) 
}; 

live example

相關問題