Как переслать объявить шаблонный тип, который должен принадлежать классу?
Предположим, что у меня есть 2 класса:
class A
{
public:
typedef std::shared_ptr<A> Ref;
...
private:
B::Ref _b;
}
class B
{
public:
typedef std::shared_ptr<B> Ref;
...
private:
A::Ref _a;
}
Это, очевидно, требует прямого объявления классов B и B:: Ref. Переслать декларацию B просто, но как это сделать для B:: Ref тоже?
Ответы
Ответ 1
Вы не можете переслать объявление вложенным typedef
, поскольку в точке прямого объявления B
будет неполным. Однако вы можете решить свою проблему, как показано ниже:
class B;
class A {
std::shared_ptr<B> _b;
public:
typedef std::shared_ptr<A> Ref;
};
class B {
A::Ref _a;
public:
typedef std::shared_ptr<B> Ref;
};
Ответ 2
Одним из способов решения этой проблемы является
class A;
class B ;
template <typename T>
struct Traits {
typedef std::shared_ptr<T> Ptr;
};
class A
{
private:
Traits<B>::Ptr _b;
};
class B
{
private:
Traits<A>::Ptr _a;
};
Ответ 3
Наличие typedef для "это то, как вы относитесь к объектам X
" внутри класса X
является плохим дизайнерским решением, именно потому, что вам нужно полное определение X
, чтобы увидеть его членов, но вы хотите иметь возможность ссылаться на X
без его полного определения.
Я вижу два способа решения этого. Один из них заключается в том, чтобы отказаться от обзора и просто вызвать typedef RefA
, определяемый там, где класс объявлен вперед:
class A;
typedef std::shared_ptr<A> RefA;
В качестве альтернативы вы можете делегировать "знать, как обращаться" к отдельному классу. Вы можете сделать его шаблоном класса, чтобы классы все еще могли регистрировать свои собственные предпочтительные типы ссылок:
template <class T>
struct RefT
{
typedef T *type; // Default reference type
};
template <class T>
using Ref = typename RefT<T>::type;
class A;
template <>
struct RefT<A>
{
typedef std::shared_ptr<A> type;
};
class B
{
private:
Ref<A> _a;
};
Ответ 4
К сожалению, вы не можете перенаправить объявление вложенного typedef. Однако вы можете просто использовать глобальные typedefs, например
typedef std::shared_ptr<B> RefB ;
и т.д. Другим решением является использование поздней специализированной специализации шаблона, например:
template <typename T> class BImpl;
template <typename T>
class AImpl
{
public:
typedef std::shared_ptr<AImpl> Ref;
private:
typename BImpl<T>::Ref _b;
};
template <typename T>
class BImpl
{
public:
typedef std::shared_ptr<BImpl> Ref;
typename AImpl<T>::Ref _a;
};
typedef AImpl<void> A;
typedef BImpl<void> B;
Ответ 5
Когда мне хочется пересылать typedef, я всегда считаю наследование. Это может выглядеть так:
template<typename T>
class Ref : public std::shared_ptr<T>
{
Ref()
{}
Ref(T *t)
: std::shared_ptr<T>(t)
{}
};
class B;
class A
{
public:
//...
private:
Ref<B> _b;
};
class B
{
public:
//...
private:
Ref<A> _a;
};