开发者

Inner class template circular reference

Does anyone knows how you can trick the C++ compiler to compile something 开发者_C百科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
   {
   };
}


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 typedefs. 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).


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.


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;
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜