Вперед объявить typedef в классе C++

какое лучшее решение для пересылки объявления typedef в классе. Вот пример того, что мне нужно решить:

class A;
class B;

class A
{
    typedef boost::shared_ptr<A> Ptr;

    B::Ptr foo();
};

class B
{
    typedef boost::shared_ptr<B> Ptr;

    A::Ptr bar();
};

полагаю, я мог бы сделать следующее:

boost::shared_ptr<B> foo();

но есть ли более изящное решение?

5 ответов


нет такой вещи, как вперед объявлении typedef к сожалению. Тем не менее, есть трюк с использованием позднего экземпляра шаблона:

template <typename T> class BImpl;

template <typename T>
class AImpl
{
public:
    typedef boost::shared_ptr<AImpl> Ptr;
    typename BImpl<T>::Ptr foo();
};

template <typename T>
class BImpl
{
public:
    typedef boost::shared_ptr<BImpl> Ptr;
    typename AImpl<T>::Ptr bar();
};

typedef AImpl<void> A;
typedef BImpl<void> B;

надеюсь, это должно выполнить то, к чему вы стремитесь.


вы столкнулись с двумя различными трудностями: 1. Нет прямых объявлений typedefs 2. Прямые объявления вложенных типов невозможны

нет никакого способа обойти второй: вы должны unnest типы.

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

говорят:

struct Ptr : shared_ptr<A> {};

Это новый тип, но он почти такой же, как синоним. Проблема, конечно, есть конструкторы, но это становится лучше с C++11.

этот ответ, Конечно, в целом. Для вашего конкретного случая, я думаю, вы должны определить PTR вне классов, и у вас не будет никаких проблем.

struct A;
struct B;
typedef shared_ptr<A> APtr;
typedef shared_ptr<B> BPtr;

а затем классы.


вы не можете.

но вы можете разделить определение Ptr классов:

class A;
class B;

template <typename T>
struct Traits {
    typedef std::shared_ptr<A>  Ptr; 
};

class A
{
    Traits<B>::Ptr foo();
};

class B
{
    Traits<A>::Ptr bar();
};

Если A и B не имеют одинаковых типов, вы всегда можете специализировать признаки для всех типов.


нет никакого способа вперед объявить либо

  1. A typedef
  2. имя в другом классе

Итак - вы не можете переслать объявление typedef и если бы вы могли, вы все равно не смогли бы этого сделать, потому что вам нужно было бы сделать это:

class B::Ptr;

и это невозможно


Как отмечали другие, вы не можете вперед объявить typedefs. Это отчасти потому, что typedefs на самом деле не являются "типами", а псевдонимами для других типов (отсюда эквивалентное понятие C++11 "псевдоним типа", такое как "использование Int = int;"). Это означает, например, что typedefs не отображаются в элементах ABI, таких как искаженные имена, и поэтому компилятор действительно должен знать достаточно базового типа, чтобы удовлетворить все требования ABI (включая как исказить имя типа).