Перенаправление shared_ptr без объявления класса

ПРИМЕЧАНИЕ. Я обнаружил, что источник ошибки на самом деле не связан с shared_ptr, просто искусно замаскированным под таким сообщением в сообщении об ошибке. Таким образом, нижеследующее в основном абсурд (а не ответы, они в порядке)

-

У меня возникли проблемы с использованием shared_ptr (boost на данный момент), где мне нужно просто переслать указатель на другую функцию. Используя собственные указатели, промежуточная функция не нуждается в доступе к определению класса, но, используя smart_ptr, похоже, что это так. Есть ли способ избежать этого?

Например, заданная целевая функция:

void func( shared_ptr<SomeClass> const & obj )

const & заботится о части проблемы, но скажем, что у нас есть класс-геттер, который получает объект для другого класса, например:

shared_ptr<SomeClass> someClassInstance();

И здесь я хочу просто собрать аргументы и перейти к целевой функции:

func( someClassInstance() );

С помощью простого указателя эта точка в коде может просто использовать объявление вперед SomeClass, но с smart_ptr оно должно иметь полное определение (предположительно, поскольку smart_ptr, возможно, потребуется удалить класс).

Теперь, если someClassInstance должен был вернуть const &, эта проблема действительно исчезнет, ​​так как промежуточный код не будет копировать какие-либо объекты. Тем не менее, функция getter должна возвращать копию для соображений безопасности потока.

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

-

ОБНОВЛЕНИЕ. Написав небольшой тест, ответы правильны, что достаточно прямого объявления. Тем не менее GCC по-прежнему жалуется в одной ситуации. Мне нужно будет выяснить, что именно заставляет его потерпеть неудачу (в этой конкретной ситуации).

Я закрываю этот вопрос сейчас или что?

Ответ 1

Для каждого упоминания shared_ptr<T> вам нужно, по крайней мере, объявление вперед для T.

Только если вы используете унарные shared_ptr::operator* и shared_ptr::operator->, вам нужна полная вещь. Под капотом shared_ptr используется комбинация compiletime- и runtime-полиморфизма, что делает возможным это. См. Также этот вопрос, чтобы узнать о "волшебстве".

Пример:

// frob.h
#ifndef FROB_H
#define FROB_H

#include <shared_ptr>

class Foo;
void grind (std::shared_ptr<Foo>);

#endif

Обратите внимание, что канонический путь передачи shared_ptr равен значению (т.е. удаляет const&).

Ответ 2

Да, общие указатели специально разработаны для работы с неполными типами (функция убийцы IMO). Они требуют только прямого объявления класса, а не определения класса. Из Boost documentation:

Обратите внимание, что scoped_ptr требует, чтобы T был полным типом во время уничтожения, но shared_ptr этого не делает.

Вы можете найти обсуждение того, как это работает здесь.

Поскольку общие указатели должны работать с неполными типами, можете ли вы дать нам конкретный (минимальный) пример, в котором это не работает для вас?