Как я могу сделать shared_ptr из непрозрачного указателя typedef? (или: как я могу "развернуть" typedef?)

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

struct Foo; // Forward declared struct
typedef Foo* FooPtr; // Opaque pointer

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

std::shared_ptr<struct Foo> theSharedPtr;

Есть ли способ определить такой указатель без "ручного" разворачивания непрозрачного указателя typedef? Я чувствую, что, должно быть, мне не хватает чего-то очевидного, но вы можете представить что-то подобное (обратите внимание: они не работают):

std::shared_ptr<*FooPtr> theSharedPointer;
// or
std::shared_ptr<pointedto(FooPtr)> theSharedPointer;

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

РЕДАКТИРОВАТЬ: Еще несколько раз, но в общем случае shared_ptr<T> хочет взять sizeof(T). Вы можете обойти это, предоставив конструктору конструктор. Я подозреваю, что это делает это немного краевым случаем, но по-прежнему кажется, что со всеми типами конфликтов в С++ я должен "разворачивать" тип указателя, не делая этого вручную.

Ответы

Ответ 1

В С++ 11:

#include <type_traits>

typedef std::shared_ptr< std::remove_pointer< FooPtr >::type > theSharedPtr;

В С++ 03 вы можете использовать boost::remove_pointer точно так же.

Если вы не хотите включать boost, запись метафайла remove_pointer довольно проста:

template<class T> struct remove_pointer;
template<class T> struct remove_pointer<T*> { typedef T type; };

Ответ 2

Да, поскольку вы уже используете возможности С++ 11, вы можете сделать это с помощью свойств типа. В частности, используя std::remove_pointer:

std::remove_pointer<Foo*>::type; // Foo

Конечно, вам нужно будет указать стандартный стандартный заголовок, который:

#include <type_traits>

чтобы использовать его.

Ответ 3

Есть ли способ определить такой указатель без "ручного" разворачивания непрозрачного указателя typedef?

#include <type_traits>
std::shared_ptr<std::remove_pointer<FooPtr>::type> theSharedPointer;

кажется, что в общем случае shared_ptr<T> хочет взять sizeof(T).

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