Здравствуйте, Sm0ke, Вы писали:
S>У меня другой вопрос по unique_ptr
S>Если взять в него завернуть некий some_type S>А сам умный указатель положить в map S>То при v_map.try_emplace(v_key, std::make_unique<some_type>() ); Будет создан экземляр, даже если в мапе есть запись с тем-же ключом. S>Т.е будет создан и разрушен лишний раз unique_ptr со своим динамическим экземпляром some_type
S>Вот если бы у unique_ptr был конструктор по принципу std::in_place_type, то этого оверхеда можно было избежать!
Можно подменить аргумент для конструктора — передавать туда не сам объект-к-хранению, с тем чтобы впоследствии его двинуть/скопировать в map-node или выкинуть если ключ уже есть, а передавать некую фабрику, которую map активирует только если действительно нужно будет построить новый node. Примерно так:
Здравствуйте, Shmj, Вы писали:
S>Видно что 2 параметра в шаблоне — _Ty и _Dx. Тут коммент — типа _Dx имеет значение по умолчанию = default_delete<_Ty>. Но где это значение установлено — почему его можно не указывать явно, если инструкция = default_delete<_Ty> — закомментирована?
Очевидно, в предварительном объявлении.
Поищи выше по тексту, найдешь вот такое объявление:
_EXPORT_STD template <class _Ty, class _Dx = default_delete<_Ty>>
class unique_ptr;
S>Зачем во friend добавляет сам себя? Вот что думает GPT- что это ошибка или недоразумение:
Смотри, это не просто класс, а шаблон класса, от которого можно произвести множество разных воплощений, которые не являются дружественными друг другу автоматически. Этим объявлением как раз и говорится, что все воплощения данного шаблона являются дружественными друг другу.
P.S. Хорошо ли они делают — это вопрос, на самом деле. Лично я к таким объявлениям отношусь с настороженностью. Ведь с таким объявлением приватный доступ взламывается "на раз" путем добавления какой-нибудь специализации-пустышки. Когда у меня возникает соблазн написать подобное всеобъемлющее объявление дружбы, я превым делом проверяю, все ли у меня в порядке с дизайном.
Вот такой еще вариант. Это, по-моему, даже лучше — можно легко адаптировать как под создание различных поинтеров, так и под непосредственное создание объектов:
Здравствуйте, rg45, Вы писали:
R>Очевидно, в предварительном объявлении.
Благодарю. Чего-то протупил — поиском не нашел.
И можно еще вопрос. Вот в этом же классе есть:
template <class _Ty, class _Dx>
class unique_ptr
{
// ...private:
template <class, class>
friend class unique_ptr;
};
Зачем во friend добавляет сам себя? Вот что думает GPT- что это ошибка или недоразумение:
Класс по умолчанию имеет доступ к своим приватным членам без необходимости объявления friend class для себя. В данном случае, добавление friend class unique_ptr внутри класса unique_ptr является излишним и необязательным.
Вероятно, это было сделано по ошибке или по недоразумению. Добавление friend class unique_ptr внутри класса unique_ptr не имеет реальной практической пользы и может быть удалено без влияния на функциональность класса.
Здравствуйте, qaz77, Вы писали:
Q>Здравствуйте, vopl, Вы писали:
V>>Можно подменить аргумент для конструктора — передавать туда не сам объект-к-хранению, с тем чтобы впоследствии его двинуть/скопировать в map-node или выкинуть если ключ уже есть, а передавать некую фабрику, которую map активирует только если действительно нужно будет построить новый node.
Q>Только еще надо будет озаботиться, чтобы при исключении в конструкторе или bad_alloc нода как-то удалялась.
Здравствуйте, Sm0ke, Вы писали:
S>В мейкер придётся ещё передавать параметры создания объекта, и в нём хранить. Но в целом идея ясна, спасибо
Можно передавать, а можно и не передавать и не хранить, а просто активацию фабрики вынести на уровень выше и пусть прикладник сам реализует создание объекта-к-хранению
S>upd: Хотя выглядит как костыль)
Ну, хз, это все субъективно. Вынести переиспользуемый код в библиотеку и пользовать оттуда — как по мне, с этим вполне можно комфортно жить.
Здравствуйте, Sm0ke, Вы писали:
S>В мейкер придётся ещё передавать параметры создания объекта, и в нём хранить. Но в целом идея ясна, спасибо S>upd: Хотя выглядит как костыль)
Можно заморочиться, и сделать универсальный Maker:
Вот такая у меня открылась декларация класса unique_ptr в VS:
_EXPORT_STD template <class _Ty, class _Dx /* = default_delete<_Ty> */>
class unique_ptr { // non-copyable pointer to an objectpublic:
using pointer = typename _Get_deleter_pointer_type<_Ty, remove_reference_t<_Dx>>::type;
using element_type = _Ty;
using deleter_type = _Dx;
Видно что 2 параметра в шаблоне — _Ty и _Dx. Тут коммент — типа _Dx имеет значение по умолчанию = default_delete<_Ty>. Но где это значение установлено — почему его можно не указывать явно, если инструкция = default_delete<_Ty> — закомментирована?
Если взять в него завернуть некий some_type
А сам умный указатель положить в map
То при v_map.try_emplace(v_key, std::make_unique<some_type>() ); Будет создан экземляр, даже если в мапе есть запись с тем-же ключом.
Т.е будет создан и разрушен лишний раз unique_ptr со своим динамическим экземпляром some_type
Вот если бы у unique_ptr был конструктор по принципу std::in_place_type, то этого оверхеда можно было избежать!
using my_ptr = std::unique_ptr<some_type>;
using my_map = std::map<bool, my_ptr>;
my_map v_map;
v_map.try_emplace(true, std::in_place_type<some_type>); // Жалко, что так нельзя!
v_map.try_emplace(true, std::make_unique<some_type>() ); // Так можно, но увы лишнее создание объектов может произойти!
Просто в своем примере я использовал emplace, а он отличается от try_emplace по формальным параметрам. try_emplace более прост в использовании, а emplace позволяет работать с ключами произвольной сложности конструирования.
Здравствуйте, vopl, Вы писали:
V>Можно подменить аргумент для конструктора — передавать туда не сам объект-к-хранению, с тем чтобы впоследствии его двинуть/скопировать в map-node или выкинуть если ключ уже есть, а передавать некую фабрику, которую map активирует только если действительно нужно будет построить новый node. Примерно так:
V>
Здравствуйте, vopl, Вы писали:
V>Можно подменить аргумент для конструктора — передавать туда не сам объект-к-хранению, с тем чтобы впоследствии его двинуть/скопировать в map-node или выкинуть если ключ уже есть, а передавать некую фабрику, которую map активирует только если действительно нужно будет построить новый node.
Только еще надо будет озаботиться, чтобы при исключении в конструкторе или bad_alloc нода как-то удалялась.