2016-07-18 4 views
3

Мне было интересно об этом. Рассмотрим это:Можно ли инициализировать контейнер STL с уникальным_ptr из списка инициализаторов?

#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. Он не может скомпилировать с длинной пачке сообщений об ошибках на НКУ, в том числе один

/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 не может быть перемещен (потому что он const), и он не может быть скопирован (потому что это тип только для перемещения), поэтому вы попадаете.

+0

Ах, спасибо. Я подозревал, что что-то вроде этого происходит - «constexpr» выглядел как подсказка. –

+0

@ mike4ty4 Настоящий ключ там, свидетельствующий о том, что сказал Маршалл, - «использование удаленной функции [...] pair (const std :: pair <_T1, _T2> &) [с _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.

 Смежные вопросы

  • Нет связанных вопросов^_^