class CA
{
std::vector<std::unique_ptr<int> > m_V;
public:
int get_foo(const std::unique_ptr<const int>& v)const;
int set_foo(const std::unique_ptr<int>& v, const int val);
void foo()
{
for(auto& v: m_V)
{
const int val = 2 * get_foo(v);// error: невозможно преобразовать "std::unique_ptr<int, ...>&" в "std::unique_ptr<const int, ...>&"
set_foo(v, val);
};
}
};
В случае обычных указателей никаких таких проблем не было бы
class CA
{
std::vector<int*> m_V;
public:
int get_foo(const int* v)const;
int set_foo(int* v, const int val);
void foo()
{
for(auto& v: m_V)
{
const int val = 2 * get_foo(v);
set_foo(v, val);
};
}
};
Re: Проблема работы с объектами через unique_ptr (const-квалификаторы)
__> int get_foo(const std::unique_ptr<const int>& v)const;
На редкость безобразная конструкция. Голые указатели и передача ссылок на неизменяемые умные указатели — это как раз тот самый "smelly code".
В такой ситуации лучше передавать int const &.
Если же передаваемое значение потенциально может быть еще не создано (т.е. в unique_ptr хранится nullptr), то тогда имеет смысл передавать optional_reference< int const >
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, VTT, Вы писали:
__>> int get_foo(const std::unique_ptr<const int>& v)const;
VTT>На редкость безобразная конструкция. Голые указатели и передача ссылок на неизменяемые умные указатели — это как раз тот самый "smelly code". VTT>В такой ситуации лучше передавать int const &.
возможно, вы правы в плане, что передача неизменяемых объектов должна идти не по указателю, а по ссылке на сам объект, но есть же случаи, когда это неудобно, например
VTT>Если же передаваемое значение потенциально может быть еще не создано (т.е. в unique_ptr хранится nullptr), то тогда имеет смысл передавать optional_reference< int const >
ага, городить optional_reference, вовлекая сторонние библиотеки и усложняя семантику, это, конечно, красиво.
Re[3]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, _hum_, Вы писали:
__>>то есть, смарты — только для обеспечения реализации RAII и не могут полноценно заменить raw-ptr?
TB>Не, ну есть shared/weak, для них работает? Но они тут нафиг не нужны и сложноваты как-то. Да тут достаточно даже const& передавать.
в том -то и дело, что shared/weak не дружат с unique.
Re[5]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, _hum_, Вы писали:
__>>в том -то и дело, что shared/weak не дружат с unique.
TB>Да, юник минималистичен. Только зачем его по ссылке передавать, ты двойную индирекцию создал на пустом месте.
а вы не поняли? потому что его, в отличие от обычных, нельзя передавать по значению. именно из-за этого весь сыр-бор.
Re[7]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, _hum_, Вы писали:
__>а вы не поняли? потому что его, в отличие от обычных, нельзя передавать по значению. именно из-за этого весь сыр-бор.
Ударение было не на "по ссылке". Передавай ссылку на сам хранимый объект, зачем огород?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[8]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, _hum_, Вы писали:
__>>а вы не поняли? потому что его, в отличие от обычных, нельзя передавать по значению. именно из-за этого весь сыр-бор.
TB>Ударение было не на "по ссылке". Передавай ссылку на сам хранимый объект, зачем огород?
__>
__>ага, городить optional_reference, вовлекая сторонние библиотеки и усложняя семантику, это, конечно, красиво.
Да, это красиво и лаконично.
По сравнению с передачей простого указателя такой подход позволяет явно указать опциональность передаваемого значения и отсутствие передачи владения без написания SAL аннотаций и комментариев.
А по сравнению с передачей ссылки на умный указатель тут не будет возникать излишняя зависимость от деталей реализации хранения этих значений.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Здравствуйте, VTT, Вы писали:
__>>ага, городить optional_reference, вовлекая сторонние библиотеки и усложняя семантику, это, конечно, красиво.
VTT>Да, это красиво и лаконично.
VTT>По сравнению с передачей простого указателя такой подход позволяет явно указать опциональность передаваемого значения и отсутствие передачи владения без написания SAL аннотаций и комментариев.
VTT>А по сравнению с передачей ссылки на умный указатель тут не будет возникать излишняя зависимость от деталей реализации хранения этих значений.
ну, если так думать, то тогда и вообще нужно optional<const T>, ведь ссылочность — это тоже "техническая деталь реализации передачи константного объекта"
Re: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, _hum_, Вы писали:
__>Опять грабли на пустом месте. __>
__>class CA
__>{
__> std::vector<std::unique_ptr<int> > m_V;
__>public:
__> int get_foo(const std::unique_ptr<const int>& v)const;
__> int set_foo(const std::unique_ptr<int>& v, const int val);
__> void foo()
__> {
__> for(auto& v: m_V)
__> {
__> const int val = 2 * get_foo(v);// error: невозможно преобразовать "std::unique_ptr<int, ...>&" в "std::unique_ptr<const int, ...>&"
__> set_foo(v, val);
__> };
__> }
__>};
__>
std::unique_ptr<const int> и std::unique_ptr<int> — это два разных типа объектов, так что не совсем понятно, что вы хотите написать.
Есть два варианта написания get_foo:
class CA
{
std::vector<std::unique_ptr<int> > m_V;
public:
int get_foo(const int& v)const {return v;}
int get_foo(const std::unique_ptr<int>& v)const {return *v;}
int set_foo(const std::unique_ptr<int>& v, const int val){*v = val;}
void foo()
{
for(auto& v: m_V)
{
const int val = 2 * get_foo(*v);
const int val2 = 2 * get_foo(v);
set_foo(v, val);
};
}
};
__>В случае обычных указателей никаких таких проблем не было бы
Были бы иные проблемы.
И каждый день — без права на ошибку...
Re[2]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, _hum_, Вы писали:
__>>Опять грабли на пустом месте. __>>
__>>class CA
__>>{
__>> std::vector<std::unique_ptr<int> > m_V;
__>>public:
__>> int get_foo(const std::unique_ptr<const int>& v)const;
__>> int set_foo(const std::unique_ptr<int>& v, const int val);
__>> void foo()
__>> {
__>> for(auto& v: m_V)
__>> {
__>> const int val = 2 * get_foo(v);// error: невозможно преобразовать "std::unique_ptr<int, ...>&" в "std::unique_ptr<const int, ...>&"
__>> set_foo(v, val);
__>> };
__>> }
__>>};
__>>
BFE>std::unique_ptr<const int> и std::unique_ptr<int> — это два разных типа объектов, так что не совсем понятно, что вы хотите написать.
я в курсе про разные типы. а хочу написать обычный код, гарантируеющий, что мой объект, передаваемый по указателю, не будет изменен.
BFE>Есть два варианта написания get_foo:
BFE>[...]
ваш вариант int get_foo(const std::unique_ptr<int>& v)const не гарантирует, что объект *v не будет этим методом изменен.
__>>В случае обычных указателей никаких таких проблем не было бы BFE>Были бы иные проблемы.
какие? только с автоудалением?
Re[3]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
BFE>>std::unique_ptr<const int> и std::unique_ptr<int> — это два разных типа объектов, так что не совсем понятно, что вы хотите написать. __>я в курсе про разные типы. а хочу написать обычный код, гарантируеющий, что мой объект, передаваемый по указателю, не будет изменен.
А чем не устаревает передача по ссылке? int get_foo(const int& v)const {return v;}
BFE>>Есть два варианта написания get_foo: BFE>>[...] __>ваш вариант int get_foo(const std::unique_ptr<int>& v)const не гарантирует, что объект *v не будет этим методом изменен.
Если вам нужно иметь настоящие гарантии, то придётся их писать руками, например так:
#include <iostream>
#include <memory>
#include <vector>
template<class T>
class UniquePtrConstWrapper
{
public:
UniquePtrConstWrapper(const std::unique_ptr<T>& rPtr)
: m_rPtr(rPtr)
{
}
public:
const T* operator ->() const
{
return m_rPtr.operator->();
}
const T& operator*() const
{
return *m_rPtr;
}
explicit operator bool() const
{
return m_rPtr.operator bool();
}
private:
const std::unique_ptr<T>& m_rPtr;
};
class CA
{
std::vector<std::unique_ptr<int> > m_V;
public:
CA()
{
m_V.push_back(std::make_unique<int>(1));
m_V.push_back(std::make_unique<int>(2));
}
int get_foo(const int& v)const {return v;}
int get_foo(const UniquePtrConstWrapper<int>& v)const { return v ? *v : 0;}
int set_foo(const std::unique_ptr<int>& v, const int val){*v = val; return val;}
void foo()
{
for(auto& v: m_V)
{
const int val = 2 * get_foo(*v);
const int val2 = 2 * get_foo(v);
set_foo(v, val);
};
}
};
int main(int argc, char* argv[])
{
CA a;
a.foo();
return 0;
}
__>>>В случае обычных указателей никаких таких проблем не было бы BFE>>Были бы иные проблемы. __>какие? только с автоудалением?
В основном, но не только. Ещё возможно, что два указателя указывают на один объект.
И каждый день — без права на ошибку...
Re[4]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, _hum_, Вы писали:
BFE>>>std::unique_ptr<const int> и std::unique_ptr<int> — это два разных типа объектов, так что не совсем понятно, что вы хотите написать. __>>я в курсе про разные типы. а хочу написать обычный код, гарантируеющий, что мой объект, передаваемый по указателю, не будет изменен. BFE>А чем не устаревает передача по ссылке? int get_foo(const int& v)const {return v;}
уже выше писал:
__>возможно, вы правы в плане, что передача неизменяемых объектов должна идти не по указателю, а по ссылке на сам объект, но есть же случаи, когда это неудобно, например __>
BFE>>>Есть два варианта написания get_foo: BFE>>>[...] __>>ваш вариант int get_foo(const std::unique_ptr<int>& v)const не гарантирует, что объект *v не будет этим методом изменен. BFE>Если вам нужно иметь настоящие гарантии, то придётся их писать руками
ну так именно этот факт и напрягает — что чтобы воспроизвести приемы работы с обычным указателем, надо, оказывается, еще кучу доп. кода писать.
__>>>>В случае обычных указателей никаких таких проблем не было бы BFE>>>Были бы иные проблемы. __>>какие? только с автоудалением? BFE>В основном, но не только. Ещё возможно, что два указателя указывают на один объект.
что тоже наверное мешает только в случае рассинхронизации работы с объектом и его удалением. или есть еще какие-то моменты?
в общем, как бы напрашивается вывод: смарты не могут легко заменить использование обычных указателей даже в случае, когда, по логике, должны были бы (когда, например, указатель является единственным владельцем).
Re[5]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
Здравствуйте, _hum_, Вы писали:
__>ну так именно этот факт и напрягает — что чтобы воспроизвести приемы работы с обычным указателем, надо, оказывается, еще кучу доп. кода писать.
А что в этом удивительного? В стандарт входит только самый минимум, а раньше и его не было.
__>>>>>В случае обычных указателей никаких таких проблем не было бы BFE>>>>Были бы иные проблемы. __>>>какие? только с автоудалением? BFE>>В основном, но не только. Ещё возможно, что два указателя указывают на один объект. __>что тоже наверное мешает только в случае рассинхронизации работы с объектом и его удалением. или есть еще какие-то моменты?
Да. Это, например, важно при передачи объекта из одной нитки в другую.
__>в общем, как бы напрашивается вывод: смарты не могут легко заменить использование обычных указателей даже в случае, когда, по логике, должны были бы (когда, например, указатель является единственным владельцем).
гарантии единственности у обычных указателей нет, так что вы не можете заменить unique_ptr обычным указателем и, естественно, обратная замена тоже сопряжена с определёнными трудностями.