Как я могу предотвратить сохранение класса на основе intrusive_ptr в других умных указателях - PullRequest
2 голосов
/ 16 августа 2010

На работе у нас есть базовый класс, назовем его IntrusiveBase, который действует как миксины, позволяя классу храниться в boost: intrusive_ptr. То есть он предоставляет своим подклассам счетчик ссылок и определяет перегрузки intrusive_ptr_add_ref и intrusive_ptr_release. Проблема в том, что кому-то слишком легко забыть, что определенный подкласс наследуется от IntrusiveBase, и они затем сохраняют его в каком-то другом умном указателе, таком как scoped_ptr или shared_ptr. Это не работает, потому что, например, scoped_ptr удалит объект, когда он выйдет из области видимости, независимо от того, каков будет счетчик ссылок. В ~ IntrusiveBase у нас есть утверждение, что количество ссылок равно единице, но это не является надежной задачей, потому что часто в конечном итоге будет только исходный экземпляр к тому моменту, когда scoped_ptr выйдет из области видимости. Это оставляет коварный сбой в ожидании того, что произойдет в те несколько раз, когда счетчик ссылок будет , а не один.

Есть ли способ вызвать сбой во время компиляции, если кто-то случайно сделает это? Даже если мне придется что-то повторять для каждого из основных классов интеллектуальных указателей, это того стоит.

Ответы [ 2 ]

6 голосов
/ 16 августа 2010

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

В этом случае вы можете специализировать их на ваших типах наследования InstrusiveBase.

  namespace boost
  {
    template<>
    class scoped_ptr<InstrusiveBaseSubclass> { }; // scoped_ptr<InstrusiveBaseSubClass> p(new InstrusiveBaseSubClass) won't compile, neither will p->, p.get() etc.

  }

Это раздражает, но это макро-возможность, например:

 class A : InstrusiveBase
 { 
     ...
 }
 NO_SCOPED_PTR(A)
 NO_SHARED_PTR(A)
5 голосов
/ 16 августа 2010

Другой вариант - перегрузить новые и удалить для этих классов и сделать удаление закрытым или защищенным. Затем instrusive_ptr_release можно сделать функцией-другом или аналогичным методом, используемым для фактического вызова удаления, когда число ссылок упало до нуля.

...