Подтвердить что ты не робот

Использует std::vector <std:: shared_ptr <const T>> антипаттерн?

Долгое время я использовал std::vector и std::shared_ptr рука об руку. Недавно я начал использовать std::shared_ptr<const T> всякий раз, когда нужен указатель на объект const. Все в порядке, так как std::shared_ptr<T> можно отнести к std::shared_ptr<const T>, а затем они используют один и тот же счетчик ссылок, и все кажется естественным.

Но когда я пытаюсь использовать конструкции, такие как std::vector< std::shared_ptr<const T> >, я сталкиваюсь с проблемами. Для упрощения я буду обозначать две структуры:

template <class T>
using SharedPtrVector = std::vector< std::shared_ptr<T> >;

template <class T>
using SharedConstPtrVector = std::vector< std::shared_ptr<const T> >;

Проблема заключается в том, что хотя SharedPtrVector и SharedConstPtrVector очень похожи, SharedConstPtrVector нельзя отнести к SharedPtrVector.

Поэтому каждый раз, когда я хочу быть константой корректно и записываю такую ​​функцию, как:

void f(const SharedConstPtrVector<T>& vec);

я не могу передать const SharedPtrVector<T> в f.

Я много думал об этом и рассматривал несколько альтернатив:

  • Запись функций преобразования

    template <typename T>
    SharedConstPtrVector<T> toConst(const SharedPtrVector<T>&);
    
  • Введите код в общей форме:

    template <typename T>
    void f(const std::vector< std::shared_ptr<T> >& vec);
    

    или

    template <typename TIterator>
    void f(TIterator begin, TIterator end);
    
  • Отбросить идею std::vector< std::shared_ptr<const T> >

Проблема с 1. - это вычислительные накладные расходы и повышенная уродство кода, а 2. дает код "все является шаблоном".

Я неопытный программист, и я не хочу идти в неправильном направлении. Я хотел бы услышать совет от кого-то, у кого есть опыт в этой проблеме.

4b9b3361

Ответ 1

Я бы предложил рассмотреть ваш дизайн с целью установить четкого владельца этого объекта. Это отсутствие четкой собственности, которая заставляет людей использовать общие умные указатели.

Bjarne Stroustrup рекомендует использовать интеллектуальные указатели только в крайнем случае. Его рекомендации (от самого лучшего к худшему):

  • Сохранять объект по значению.
  • Хранить многие объекты в контейнере по значению.
  • Если ничего не работает, используйте интеллектуальные указатели.

См. Bjarne Stroustrup - Суть С++: с примерами в С++ 84, С++ 98, С++ 11 и С++ 14 в 0:37:40.

Ответ 2

1 Проблема не связана с shared_ptr<>, но встречается уже для обычных указателей:

template<typename T>
void foo(std::vector<const T*>);

int a,b;
std::vector<int*> bar={&a,&b};
foo<???>(bar);        // no value for ??? works

2 Конструкция vector<shared_ptr<T>> разумно только в том случае, если у владельца нет владельца.

Ответ 3

Это допустимый способ хранения неизменяемых (и, следовательно, потокобезопасных) объектов, строительного блока для кеша для копирования по одной записи. Определенно не анти-шаблон.

Ответ 4

если вы настаиваете на сохранении std::vector, вы можете попытаться инкапсулировать его в структуру идиомы дескриптора.

это позволяет сохранить общий указатель не const в дескрипторе const.