Циркулярная ссылка на шаблон внутреннего класса - PullRequest
5 голосов
/ 28 июня 2011

Кто-нибудь знает, как можно обмануть компилятор C ++, чтобы скомпилировать что-то подобное (с условием, что TheObservedObject остается внутри MyClass):

template< typename Type >
class Observabile
{
public:
   typename typedef Type::TheObservedObject TheObject;

   void Observe( TheObject& obj ) {}
};

class MyClass : public Observabile< MyClass >
{
public:
   class TheObservedObject
   {
   };
}

Ответы [ 3 ]

1 голос
/ 28 июня 2011

Ни вы не можете перенаправить объявление внутреннего класса, ни получить доступ к ним как к неполному типу из template Observable.Однако в таком случае у вас может быть один прием.

// make inner class external
class TheObservedObject
{
  private: // make everything private
  friend class MyClass;  // make friends with original outer class
};

Таким образом, эффективно TheObservedObject доступен только для MyClass.

Теперь вы можете изменить class Observabile<>, принимая 2параметры и передать вышеупомянутый класс также.Это может налагать определенные ограничения, но может быть близким совпадением.

1 голос
/ 28 июня 2011

Как уже говорили другие, MyClass является неполным в точке, где создается экземпляр Observable. Тем не менее, вы можете использовать класс черт. Примерно так может работать:

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;
};
1 голос
/ 28 июня 2011

К сожалению, это невозможно напрямую, так как MyClass в момент создания экземпляра Observable еще не завершен, и поэтому вы не можете получить доступ к typedef s. Вы можете обойти это, добавив небольшую оболочку:

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

Или просто положите TheObservedObject вне MyClass(Wrapper).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...