您可以使用初始化列表中的 unique_ptr 初始化 STL 容器吗?

Can you initialize an STL container with unique_ptr from an initializer list?

我想知道这个。考虑一下:

#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 来做吗?如果是这样,我错过了什么?如果不是,为什么不呢?

没有

无法修改 initializer_list 的元素。

unique_ptr不能被移动(因为它是常量)也不能被复制(因为它是一个只能移动的类型),所以你完蛋了。

好的,没问题。

首先,智能 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> const& l ):il(l) {} // const& here matters

  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.