Deleter unique_ptr для ostream
От: _agg  
Дата: 19.04.23 03:04
Оценка:
Всем привет, как обычно писал код на одной из библиотек и там было макроопределение:
#define OSTREAM std::ostream


В примерах было показано использование типа такого:
...
OSTREAM *ost = new std::ofstream("file.txt", std::ios::app);
...
delete ost;
...


Все как бы работает, я решил переделать это под std::unique_ptr, если использовать вот таким образом то все работает:
std::unique_ptr < OSTREAM  > pstm (new std::ofstream("file.txt", std::ios::app));


но нужно было отложить инициализацию и сделать что то вроде вот этого:
std::unique_ptr < OSTREAM > pstm;
pstm = new std::ofstream("file.txt", std::ios::app);


Получил вот такие ошибки:
error C2679: binary '=': no operator found which takes a right-hand operand of type 'std::ofstream *' (or there is no acceptable conversion)
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\memory(2338): note: could be 'std::unique_ptr<std::ostream,std::default_delete<_Ty>> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)'
1>        with
1>        [
1>            _Ty=std::ostream
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\memory(2276): note: or       'std::unique_ptr<std::ostream,std::default_delete<_Ty>> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(std::unique_ptr<_Ty,std::default_delete<_Ty>> &&) noexcept'
1>        with
1>        [
1>            _Ty=std::ostream
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\memory(2202): note: or       'std::unique_ptr<std::ostream,std::default_delete<_Ty>> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(std::nullptr_t) noexcept'
1>        with
1>        [
1>            _Ty=std::ostream
1>        ]
1>d:\projects\custom_deleter\custom_deleter.cpp(19): note: while trying to match the argument list '(std::unique_ptr<std::ostream,std::default_delete<_Ty>>, std::ofstream *)'
1>        with
1>        [
1>            _Ty=std::ostream
1>        ]


Пробовал добавлять кастомный делетер, но ничего с этого не вышло и эта тема осталась для меня не раскрыта, я конечно сделал по старинке с вызовом delete, но все же хочу понять как сие блюдо приготовить?
Спасибо.
Re: Deleter unique_ptr для ostream
От: fdn721  
Дата: 19.04.23 04:00
Оценка: +1
Читай документацию внимательнее...

std::unique_ptr < OSTREAM > pstm;
pstm.reset(new std::ofstream("file.txt", std::ios::app));
Отредактировано 19.04.2023 4:01 fdn721 . Предыдущая версия .
Re[2]: Deleter unique_ptr для ostream
От: _agg  
Дата: 19.04.23 04:22
Оценка:
Здравствуйте, fdn721, Вы писали:

F>Читай документацию внимательнее...


F>
F>std::unique_ptr < OSTREAM > pstm;
F>pstm.reset(new std::ofstream("file.txt", std::ios::app));
F>



Спасибо большое, самое интересное что я это читал и смотрю что в старых проектах использовал, но похоже успешно забыл.
Re: Deleter unique_ptr для ostream
От: rg45 СССР  
Дата: 19.04.23 06:00
Оценка:
Здравствуйте, _agg, Вы писали:

_>но нужно было отложить инициализацию и сделать что то вроде вот этого:

_>
_>std::unique_ptr < OSTREAM > pstm;
_>pstm = new std::ofstream("file.txt", std::ios::app);
_>


Оператор присваивания тоже можно использовать (как альтернативу reset, про который сказали выше), но для этого в правой части оператора присваивания нужно скорструировать unique_ptr:

pstm = std::make_unique<OSTREAM>("file.txt", std::ios::app);


что равнозначно следующиему:

    pstm = std::unique_ptr<OSTREAM>(new OSTREAM("file.txt", std::ios::app));


P.S. Ну и мелкое замечание: если уже заведен макрос OSTREAM, то его следует либо использовать регулярно, либо не использовать вообще. А если будет в одном месте OSTREAM, а в другом std::ofstream, то можно получить нежданчик, если вдруг в один прекрасный день кто-то подредактирует это макроопределение.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Deleter unique_ptr для ostream
От: K13 http://akvis.com
Дата: 19.04.23 06:10
Оценка: +3
R>P.S. Ну и мелкое замечание: если уже заведен макрос OSTREAM, то его следует либо использовать регулярно, либо не использовать вообще. А если будет в одном месте OSTREAM, а в другом std::ofstream, то можно получить нежданчик, если вдруг в один прекрасный день кто-то подредактирует это макроопределение.

А еще лучше вместо макроса сделать
using OSTREAM = std::ofstream;

Макросы -- зло. Иногда необходимое, но если можно обойтись инлайн-функцией, typedef или constexpr -- лучше обойтись
Re[3]: Deleter unique_ptr для ostream
От: rg45 СССР  
Дата: 19.04.23 06:11
Оценка:
Здравствуйте, K13, Вы писали:

K13>Макросы -- зло. Иногда необходимое, но если можно обойтись инлайн-функцией, typedef или constexpr -- лучше обойтись


Полностью согласен.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Deleter unique_ptr для ostream
От: _agg  
Дата: 19.04.23 08:43
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, _agg, Вы писали:


_>>но нужно было отложить инициализацию и сделать что то вроде вот этого:

_>>
_>>std::unique_ptr < OSTREAM > pstm;
_>>pstm = new std::ofstream("file.txt", std::ios::app);
_>>


R>Оператор присваивания тоже можно использовать (как альтернативу reset, про который сказали выше), но для этого в правой части оператора присваивания нужно скорструировать unique_ptr:


R>
R>pstm = std::make_unique<OSTREAM>("file.txt", std::ios::app);
R>


R>что равнозначно следующиему:


R>
R>    pstm = std::unique_ptr<OSTREAM>(new OSTREAM("file.txt", std::ios::app));
R>


R>P.S. Ну и мелкое замечание: если уже заведен макрос OSTREAM, то его следует либо использовать регулярно, либо не использовать вообще. А если будет в одном месте OSTREAM, а в другом std::ofstream, то можно получить нежданчик, если вдруг в один прекрасный день кто-то подредактирует это макроопределение.



Внимательнее читайте, этот макрос объявлен в библиотеке, и эта библиотека использует этот поток, а пользователь библиотеки уже сам назначает куда же этот std::ostream будет писать, поэтому и было написано таким образом:
//объявление  OSTREAM это std::ostream 
std::unique_ptr<OSTREAM> ostm;
...
//инициализация 
ostm.reset(new std::ofstream("file.txt", std::ios::app))   // это рабочий вариант

//вот это не рабочий вариант потому что OSTREAM это std::ostream а инициализировать его нужно файловым потоком std::ofstream
pstm = std::make_unique<OSTREAM>("file.txt", std::ios::app)
Отредактировано 19.04.2023 8:44 _agg . Предыдущая версия .
Re[3]: Deleter unique_ptr для ostream
От: rg45 СССР  
Дата: 19.04.23 09:02
Оценка:
Здравствуйте, _agg, Вы писали:

_>Внимательнее читайте, этот макрос объявлен в библиотеке, и эта библиотека использует этот поток, а пользователь библиотеки уже сам назначает куда же этот std::ostream будет писать, поэтому и было написано таким образом:
_>//объявление  OSTREAM это std::ostream 
_>std::unique_ptr<OSTREAM> ostm;
_>...
_>//инициализация 
_>ostm.reset(new std::ofstream("file.txt", std::ios::app))   // это рабочий вариант

Да, виноват, невнимательно посмотрел.


_>//вот это не рабочий вариант потому что OSTREAM это std::ostream а инициализировать его нужно файловым потоком std::ofstream
_>pstm = std::make_unique<OSTREAM>("file.txt", std::ios::app)

Вариант с присваиванием тоже вполне рабочий, нужно просто использовать std::ofstream вместо OSTREAM:

pstm = std::make_unique<std::ofstream>("file.txt", std::ios::app);

А ковариантное преобразование типов обеспечивает сам unique_ptr.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 19.04.2023 9:32 rg45 . Предыдущая версия . Еще …
Отредактировано 19.04.2023 9:31 rg45 . Предыдущая версия .
Отредактировано 19.04.2023 9:15 rg45 . Предыдущая версия .
Отредактировано 19.04.2023 9:12 rg45 . Предыдущая версия .
Отредактировано 19.04.2023 9:07 rg45 . Предыдущая версия .
Отредактировано 19.04.2023 9:05 rg45 . Предыдущая версия .
Отредактировано 19.04.2023 9:03 rg45 . Предыдущая версия .
Re[3]: Deleter unique_ptr для ostream
От: qaz77  
Дата: 19.04.23 09:02
Оценка:
Здравствуйте, _agg, Вы писали:
_>
_>//вот это не рабочий вариант потому что OSTREAM это std::ostream а инициализировать его нужно файловым потоком std::ofstream
_>pstm = std::make_unique<OSTREAM>("file.txt", std::ios::app)

_>


Надо так:
//вот это не рабочий вариант потому что OSTREAM это std::ostream а инициализировать его нужно файловым потоком std::ofstream
pstm = std::make_unique<std::ofstream>("file.txt", std::ios::app)
Re[4]: Deleter unique_ptr для ostream
От: _agg  
Дата: 19.04.23 09:51
Оценка: +1
Здравствуйте, qaz77, Вы писали:

Q>Здравствуйте, _agg, Вы писали:

_>>
_>>//вот это не рабочий вариант потому что OSTREAM это std::ostream а инициализировать его нужно файловым потоком std::ofstream
_>>pstm = std::make_unique<OSTREAM>("file.txt", std::ios::app)

_>>


Q>Надо так:

Q>
Q>//вот это не рабочий вариант потому что OSTREAM это std::ostream а инициализировать его нужно файловым потоком std::ofstream
Q>pstm = std::make_unique<std::ofstream>("file.txt", std::ios::app)
Q>



Заметил уже который раз когда погружаюсь в новую библиотеку начинаю что-нибудь забывать что знал ).

Ну а в целом огромное вам всем спасибо коллеги, всем добра !
Отредактировано 19.04.2023 9:52 _agg . Предыдущая версия .
Re[5]: Deleter unique_ptr для ostream
От: rg45 СССР  
Дата: 19.04.23 09:54
Оценка:
Здравствуйте, _agg, Вы писали:

_> Заметил уже который раз когда погружаюсь в новую библиотеку начинаю что-нибудь забывать что знал ).


В этом нет ничего удивительного — помимо замечательной способности запоминать у человеческого мозга есть не менее замечательная способность — забывать. Без этой способности мы все с ума посходили бы.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Deleter unique_ptr для ostream
От: flаt  
Дата: 20.04.23 06:02
Оценка:
Здравствуйте, rg45, Вы писали:

R>В этом нет ничего удивительного — помимо замечательной способности запоминать у человеческого мозга есть не менее замечательная способность — забывать. Без этой способности мы все с ума посходили бы.


Кроме бинарного режима (забывать или не забывать), можно было бы и гибкость проявить. А ещё лучше — отдать это на управление человеку — позволить самому решать, что забывать, а что нет.

Оффтоп.
Re[7]: Deleter unique_ptr для ostream
От: rg45 СССР  
Дата: 20.04.23 08:17
Оценка:
Здравствуйте, flаt, Вы писали:

F>Кроме бинарного режима (забывать или не забывать), можно было бы и гибкость проявить.


Так он и проявил — пришел на форум и спросил. Чем не гибкость?
--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.