Reputation: 856
Does anyone knows how you can trick the C++ compiler to compile something like that (with the condition that TheObservedObject remains inside MyClass ):
template< typename Type >
class Observabile
{
public:
typename typedef Type::TheObservedObject TheObject;
void Observe( TheObject& obj ) {}
};
class MyClass : public Observabile< MyClass >
{
public:
class TheObservedObject
{
};
}
Upvotes: 5
Views: 575
Reputation: 1061
As others have said, MyClass
is incomplete at the point where Observable
is instantiated. However, you could use a traits class. Something like this might work:
template<class T>
struct ObservedObject {};
template<class T>
class Observable
{
public:
typedef typename ObservedObject<T>::type TheObject;
void Observe(TheObject& obj) {}
};
class MyClass; // forward decl
class MyClassObservedObject
{
// define outside of MyClass
};
template<> struct ObservedObject<MyClass>
{
typedef MyClassObservedObject type;
};
class MyClass : public Observable<MyClass>
{
//
// ...
//
private:
friend class MyClassObservedObject;
};
Upvotes: 1
Reputation: 70020
Neither you can forward declare the inner class nor you can access them as incomplete type from the template Observable
. However, in such case, you can have one trick.
// make inner class external
class TheObservedObject
{
private: // make everything private
friend class MyClass; // make friends with original outer class
};
Thus, effectively TheObservedObject
is accessible only for MyClass
.
Now you can change class Observabile<>
accepting 2 parameters and pass the above class also. This might impose certain limitations, but it can be a close match.
Upvotes: 1
Reputation: 131829
Sadly, that is not directly possible, as MyClass
, at the point of instantiation of Observable
, is not yet complete and as such you can't access any typedef
s. You can work around this by adding a small wrapper:
template< typename Type, typename Wrapper >
class Observable
{
public:
typename typedef Wrapper::TheObservedObject TheObject;
void Observe( TheObject& obj ) {}
};
struct MyClassWrapper{
class TheObservedObject
{
};
};
class MyClass : public Observable< MyClass, MyClassWrapper>
{
public:
typedef MyClassWrapper::TheObservedObject TheObservedObject;
};
Or generelly just put TheObservedObject
outside of MyClass(Wrapper)
.
Upvotes: 1