2016-07-18 42 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

相关问题