Шаблоны, компилируемые с MSVC, а не с GCC


У меня есть следующий код (упрощенный, чтобы выделить текущую проблему):

template <class ENUM_EVENTS>
class CFiniteStateEventBase {};
template <class DATA,class ENUM_STATES,class ENUM_EVENTS>
class CFiniteStateCursor {};
template <class DATA,class ENUM_STATES,class ENUM_EVENTS>
class CFiniteStateBase {};

template <class DATA,class ENUM_STATES,class ENUM_EVENTS>
class CFiniteStateTransitionBase
{
protected:
  CFiniteStateBase<DATA,ENUM_STATES,ENUM_EVENTS> * m_pfsbTo;
public:
  CFiniteStateTransitionBase(CFiniteStateBase<DATA,ENUM_STATES,ENUM_EVENTS> * pfsbTo)
    : m_pfsbTo(pfsbTo) {}

  virtual ~CFiniteStateTransitionBase() {}

  virtual int VTransition() = 0;
};

template <class DATA,class ENUM_STATES,class ENUM_EVENTS>
class CFiniteStateYesTransition
  : public CFiniteStateTransitionBase<DATA,ENUM_STATES,ENUM_EVENTS>
{
public:
  CFiniteStateYesTransition(CFiniteStateBase<DATA,ENUM_STATES,ENUM_EVENTS> * pfsbTo)
    : CFiniteStateTransitionBase<DATA,ENUM_STATES,ENUM_EVENTS>(pfsbTo) {}

  virtual int VTransition()
  {
    m_pfsbTo = 0;
    return 0;
  }
};

Он прекрасно компилируется на MSVC (6 и 2012), но в GCC (3.4.6 и 4.1.2 на CentOS 5.10) я получаю следующую ошибку:

ФСБ.cpp: в функции-члене ' virtual int CFiniteStateYesTransition:: VTransition(CFiniteStateEventBase , DATA, CFiniteStateBase, CFiniteStateBase*, CFiniteStateCursor)’: ФСБ.cpp: 33: erreur: ‘m_pfsbTo’ не был объявлен в этом область применения

Что плохого в объявлении m_pfsbTo?

1   2   2014-04-04 19:13:49

1 ответ:

Изменить m_pfsbTo на

CFiniteStateTransitionBase<DATA,ENUM_STATES,ENUM_EVENTS>::m_pfsbTo

Внутри виртуальной функции.

Скотт Мейерс обращается к проблеме в пункте 43 эффективного C++, из которого я цитирую:

Проблема заключается в том, что когда компиляторы сталкиваются с определением для шаблон класса LoggingMsgSender, они не знают, что это за класс наследует от. Конечно, это MsgSender<Company>, но Company - это параметр шаблона, который будет известен только позже (когда LoggingMsgSender является экземпляром). Не зная, что такое компания, нет никакого способа это сделать. знайте, как выглядит класс MsgSender<Company>. В частности, нет никакого способа узнать, имеет ли он функцию sendClear.

По модулю имен, это прекрасно применимо к вашему случаю.