Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: _hum_ Беларусь  
Дата: 16.04.16 11:21
Оценка: :)
Опять грабли на пустом месте.
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-квалификаторы)
От: VTT http://vtt.to
Дата: 16.04.16 11:37
Оценка:
__> 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-квалификаторы)
От: T4r4sB Россия  
Дата: 16.04.16 11:38
Оценка:
Здравствуйте, _hum_, Вы писали:

__> int get_foo(const std::unique_ptr<const int>& v)const;


Передавай сырой указатель, что случится-то?

int get_foo(const int* v)const;
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: _hum_ Беларусь  
Дата: 16.04.16 12:05
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>> int get_foo(const std::unique_ptr<const int>& v)const;


TB>Передавай сырой указатель, что случится-то?


TB>int get_foo(const int* v)const;


то есть, смарты — только для обеспечения реализации RAII и не могут полноценно заменить raw-ptr?
Re[2]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: _hum_ Беларусь  
Дата: 16.04.16 12:22
Оценка:
Здравствуйте, VTT, Вы писали:

__>> int get_foo(const std::unique_ptr<const int>& v)const;


VTT>На редкость безобразная конструкция. Голые указатели и передача ссылок на неизменяемые умные указатели — это как раз тот самый "smelly code".

VTT>В такой ситуации лучше передавать int const &.

возможно, вы правы в плане, что передача неизменяемых объектов должна идти не по указателю, а по ссылке на сам объект, но есть же случаи, когда это неудобно, например
TNode*        next(TNode* p){ return p->m_pNext;}
const TNode* next(const TNode* p){ return p->m_pNext;}


VTT>Если же передаваемое значение потенциально может быть еще не создано (т.е. в unique_ptr хранится nullptr), то тогда имеет смысл передавать optional_reference< int const >


ага, городить optional_reference, вовлекая сторонние библиотеки и усложняя семантику, это, конечно, красиво.
Re[3]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: T4r4sB Россия  
Дата: 16.04.16 12:48
Оценка:
Здравствуйте, _hum_, Вы писали:

__>то есть, смарты — только для обеспечения реализации RAII и не могут полноценно заменить raw-ptr?


Не, ну есть shared/weak, для них работает? Но они тут нафиг не нужны и сложноваты как-то. Да тут достаточно даже const& передавать.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[4]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: _hum_ Беларусь  
Дата: 16.04.16 12:50
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>>то есть, смарты — только для обеспечения реализации RAII и не могут полноценно заменить raw-ptr?


TB>Не, ну есть shared/weak, для них работает? Но они тут нафиг не нужны и сложноваты как-то. Да тут достаточно даже const& передавать.


в том -то и дело, что shared/weak не дружат с unique.
Re[5]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: T4r4sB Россия  
Дата: 16.04.16 12:54
Оценка:
Здравствуйте, _hum_, Вы писали:

__>в том -то и дело, что shared/weak не дружат с unique.


Да, юник минималистичен. Только зачем его по ссылке передавать, ты двойную индирекцию создал на пустом месте.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[6]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: _hum_ Беларусь  
Дата: 16.04.16 13:18
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>>в том -то и дело, что shared/weak не дружат с unique.


TB>Да, юник минималистичен. Только зачем его по ссылке передавать, ты двойную индирекцию создал на пустом месте.


а вы не поняли? потому что его, в отличие от обычных, нельзя передавать по значению. именно из-за этого весь сыр-бор.
Re[7]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: T4r4sB Россия  
Дата: 16.04.16 13:22
Оценка:
Здравствуйте, _hum_, Вы писали:

__>а вы не поняли? потому что его, в отличие от обычных, нельзя передавать по значению. именно из-за этого весь сыр-бор.


Ударение было не на "по ссылке". Передавай ссылку на сам хранимый объект, зачем огород?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[8]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: _hum_ Беларусь  
Дата: 16.04.16 13:28
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


__>>а вы не поняли? потому что его, в отличие от обычных, нельзя передавать по значению. именно из-за этого весь сыр-бор.


TB>Ударение было не на "по ссылке". Передавай ссылку на сам хранимый объект, зачем огород?


__>
__>TNode*        next(TNode* p){ return p->m_pNext;}
__>const TNode* next(const TNode* p){ return p->m_pNext;}
__>
Re[3]: Проблема работы с объектами через unique_ptr (const-к
От: VTT http://vtt.to
Дата: 16.04.16 13:33
Оценка:
__>ага, городить optional_reference, вовлекая сторонние библиотеки и усложняя семантику, это, конечно, красиво.

Да, это красиво и лаконично.

По сравнению с передачей простого указателя такой подход позволяет явно указать опциональность передаваемого значения и отсутствие передачи владения без написания SAL аннотаций и комментариев.

А по сравнению с передачей ссылки на умный указатель тут не будет возникать излишняя зависимость от деталей реализации хранения этих значений.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Отредактировано 16.04.2016 13:34 VTT . Предыдущая версия .
Re[4]: Проблема работы с объектами через unique_ptr (const-к
От: _hum_ Беларусь  
Дата: 16.04.16 13:44
Оценка:
Здравствуйте, VTT, Вы писали:

__>>ага, городить optional_reference, вовлекая сторонние библиотеки и усложняя семантику, это, конечно, красиво.


VTT>Да, это красиво и лаконично.


VTT>По сравнению с передачей простого указателя такой подход позволяет явно указать опциональность передаваемого значения и отсутствие передачи владения без написания SAL аннотаций и комментариев.


VTT>А по сравнению с передачей ссылки на умный указатель тут не будет возникать излишняя зависимость от деталей реализации хранения этих значений.


ну, если так думать, то тогда и вообще нужно optional<const T>, ведь ссылочность — это тоже "техническая деталь реализации передачи константного объекта"
Re: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: B0FEE664  
Дата: 18.04.16 09:39
Оценка:
Здравствуйте, _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-квалификаторы)
От: _hum_ Беларусь  
Дата: 18.04.16 10:07
Оценка:
Здравствуйте, 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-квалификаторы)
От: B0FEE664  
Дата: 18.04.16 10:59
Оценка:
Здравствуйте, _hum_, Вы писали:


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-квалификаторы)
От: _hum_ Беларусь  
Дата: 18.04.16 11:18
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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



BFE>>>std::unique_ptr<const int> и std::unique_ptr<int> — это два разных типа объектов, так что не совсем понятно, что вы хотите написать.

__>>я в курсе про разные типы. а хочу написать обычный код, гарантируеющий, что мой объект, передаваемый по указателю, не будет изменен.
BFE>А чем не устаревает передача по ссылке? int get_foo(const int& v)const {return v;}

уже выше писал:

__>возможно, вы правы в плане, что передача неизменяемых объектов должна идти не по указателю, а по ссылке на сам объект, но есть же случаи, когда это неудобно, например

__>
__>TNode*        next(TNode* p){ return p->m_pNext;}
__>const TNode* next(const TNode* p){ return p->m_pNext;}
__>


BFE>>>Есть два варианта написания get_foo:

BFE>>>[...]
__>>ваш вариант int get_foo(const std::unique_ptr<int>& v)const не гарантирует, что объект *v не будет этим методом изменен.
BFE>Если вам нужно иметь настоящие гарантии, то придётся их писать руками

ну так именно этот факт и напрягает — что чтобы воспроизвести приемы работы с обычным указателем, надо, оказывается, еще кучу доп. кода писать.

__>>>>В случае обычных указателей никаких таких проблем не было бы

BFE>>>Были бы иные проблемы.
__>>какие? только с автоудалением?
BFE>В основном, но не только. Ещё возможно, что два указателя указывают на один объект.

что тоже наверное мешает только в случае рассинхронизации работы с объектом и его удалением. или есть еще какие-то моменты?

в общем, как бы напрашивается вывод: смарты не могут легко заменить использование обычных указателей даже в случае, когда, по логике, должны были бы (когда, например, указатель является единственным владельцем).
Re[5]: Проблема работы с объектами через unique_ptr (const-квалификаторы)
От: B0FEE664  
Дата: 18.04.16 11:34
Оценка:
Здравствуйте, _hum_, Вы писали:

__>ну так именно этот факт и напрягает — что чтобы воспроизвести приемы работы с обычным указателем, надо, оказывается, еще кучу доп. кода писать.

А что в этом удивительного? В стандарт входит только самый минимум, а раньше и его не было.

__>>>>>В случае обычных указателей никаких таких проблем не было бы

BFE>>>>Были бы иные проблемы.
__>>>какие? только с автоудалением?
BFE>>В основном, но не только. Ещё возможно, что два указателя указывают на один объект.
__>что тоже наверное мешает только в случае рассинхронизации работы с объектом и его удалением. или есть еще какие-то моменты?
Да. Это, например, важно при передачи объекта из одной нитки в другую.

__>в общем, как бы напрашивается вывод: смарты не могут легко заменить использование обычных указателей даже в случае, когда, по логике, должны были бы (когда, например, указатель является единственным владельцем).

гарантии единственности у обычных указателей нет, так что вы не можете заменить unique_ptr обычным указателем и, естественно, обратная замена тоже сопряжена с определёнными трудностями.
И каждый день — без права на ошибку...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.