Reputation: 53307
Assume I have 2 classes:
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;
}
This obviously requires forward declaration of class B and B::Ref. Forward declaring B is simple, but how to do that for B::Ref too?
Upvotes: 10
Views: 1754
Reputation: 4813
When I feel like forwarding a typedef, I always consider inheritance. It could look like this:
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;
};
Upvotes: 1
Reputation: 2263
Unfortunately, you cannot forward declare nested typedef. However, you could just use global typedefs, like
typedef std::shared_ptr<B> RefB ;
and so on. Other solution is to use late template specialization, sth like the following:
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;
Upvotes: 1
Reputation: 47784
One of way to solve this is
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;
};
Upvotes: 8
Reputation: 171097
Having a typedef for "this is how you refer to objects X
" inside class X
is a bad design decision, precisely because you need the full definition of X
to see its members, but you want to be able to refer to X
without its full definition.
I can see two ways of solving this. One is to abandon scoping and simply call the typedef RefA
, defined where the class is forward-declared:
class A;
typedef std::shared_ptr<A> RefA;
Alternatively, you can delegate the "knows how to refer" to a separate class. You could make it a class template, so that classes can still register their own preferred referring types there:
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;
};
Upvotes: 2
Reputation: 42889
You can't forward declare a nested typedef
since at the point of the forward declaration B
would be an incomplete type. You can however solve your problem like below:
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;
};
Upvotes: 4