Может ли пользовательское окно / диалог MFC быть экземпляром шаблона класса? - PullRequest
1 голос
/ 09 июня 2010

Существует множество специальных макросов, которые MFC использует при создании диалогов, и в моих быстрых тестах я получаю странные ошибки, пытаясь скомпилировать шаблонный класс диалога. Это может быть большая боль для достижения?

Вот что я попробовал:

MyDlg.h

template <class W>
class CMyDlg : public CDialog
{
    typedef CDialog super;
    DECLARE_DYNAMIC(CMyDlg <W>)

public:
    CMyDlg (CWnd* pParent);   // standard constructor
    virtual ~CMyDlg ();

// Dialog Data
    enum { IDD = IDD_MYDLG };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    DECLARE_MESSAGE_MAP()

private:
    W *m_pWidget; //W will always be a CDialog
};



IMPLEMENT_DYNAMIC(CMyDlg<W>, super) <-------------------

template <class W>
CMyDlg<W>::CMyDlg(CWnd* pParent)
    : super(CMyDlg::IDD, pParent)
{
  m_pWidget = new W(this);
}

Я получаю кучу ошибок, но главная из них выглядит так:

ошибка C2955: «CMyDlg»: использование класса шаблон требует аргумента шаблона список

Я пытался использовать некоторые специализированные версии шаблонов макросов, но это мало помогает, другие ошибки меняются, но эта остается. Обратите внимание, что мой код находится в одном файле, так как шаблоны C ++ не любят .h / .cpp, как обычно.

Я предполагаю, что кто-то должен был делать это в прошлом, возможно, создавая собственные версии макросов, но я не могу найти его с помощью поиска, так как «шаблон» имеет другие значения.

Ответы [ 3 ]

3 голосов
/ 09 июня 2010

У вас могут быть и другие проблемы, но одна вещь - это использование super.Это Java, а не C ++.Вместо super вам нужно использовать CDialog.

После изучения IMPLEMENT_DYNAMIC определение макроса не совместимо с шаблонами, оно не использует синтаксис template <class T> перед определениями функций.Что вам нужно сделать, это определить производные классовые специализации вашего шаблона, а затем использовать макрос для них.Таким образом, вы можете сделать это:

class MyDlgA : public CMyDlg<A>
{
};

IMPLEMENT_DYNAMIC(MyDlgA, CDialog);

И затем сделать это для всех специализаций, которые вы хотите.Если это невозможно, посмотрите на макрос и создайте его собственную шаблонную версию.

Редактировать: Следуя моему комментарию, вы можете сделать макрос следующим образом:

#define INSTANTIATE_DLG_TEMPLATE(T)  \
class MyDlg##T : public CMyDlg<T>    \
{                                    \
};                                   \
                                     \
IMPLEMENT_DYNAMIC(MyDlg##T, CDialog);

И затем просто используйте это везде, где вы обычно определяете специализацию шаблона в заголовочном файле с помощью typedef.

2 голосов
/ 10 июня 2010

Вот рабочее решение, хотя и некрасивое ... Я не успел переписать макрос после расширения существующего и исправления для шаблонов:

//Template-enabled expansion of IMPLEMENT_DYNAMIC(CMyDlg,super)
template <class W> CRuntimeClass* PASCAL CMyDlg<W>::_GetBaseClass(){ return RUNTIME_CLASS(super); }
template <class W> AFX_COMDAT const CRuntimeClass CMyDlg<W>::CMyDlg= {
        "CMyDlg", sizeof(CMyDlg<W>), 0xFFFF, NULL,&CMyDlg<W>::_GetBaseClass, NULL, NULL };
template <class W> CRuntimeClass* PASCAL CMyDlg<W>::GetThisClass()  { return _RUNTIME_CLASS(CMyDlg); }
template <class W> CRuntimeClass* CMyDlg<W>::GetRuntimeClass() const { return _RUNTIME_CLASS(CMyDlg); }
1 голос
/ 09 июня 2010

Я не сделал этого для диалога, только для некоторых пользовательских элементов управления, но я не вижу причин, по которым он не будет работать.
Я знаю, что есть по крайней мере версия шаблона для определения карт сообщений, BEGIN_TEMPLATE_MESSAGE_MAP.Проверить http://msdn.microsoft.com/en-us/library/aa991537(VS.80).aspx

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