Можете ли вы инициализировать контейнер STL с помощью unique_ptr из списка инициализаторов?

c++11 stl unique-ptr

602 просмотра

2 ответа

436 Репутация автора

Мне было интересно об этом. Учти это:

#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? Если так, что я пропускаю? Если нет, то почему нет?

Автор: The_Sympathizer Источник Размещён: 18.07.2016 12:23

Ответы (2)


4 плюса

9624 Репутация автора

Решение

Нет.

Элементы не initializer_listмогут быть изменены.

unique_ptrНе может быть перемещен (потому что это Const) , и он не может быть скопирован (потому что это движение только тип), так что вы обливали.

Автор: Marshall Clow Размещён: 18.07.2016 01:21

1 плюс

199555 Репутация автора

Конечно, нет проблем.

Во-первых, умный прокси 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)
};

живой пример .

Автор: Yakk - Adam Nevraumont Размещён: 18.07.2016 05:41
Вопросы из категории :
32x32