1

I have several views in my app, that are almost the same, so I decided to create a CBaseView class and to not copy the code. So I have something like this:

template <class BASE_T, class BASE_DOC, class BASE_DLG>
class CBaseView : public CListView
{
 DECLARE_DYNCREATE(CBaseView<BASE_T, BASE_DOC, BASE_DLG>)

     void func1()
     {
      // GetData() is just another method in CBaseView
      BASE_T oData = GetData();
      ...
     }

     void func2()
     {
      BASE_DOC* pDocument = (BASE_DOC*) CView::GetDocumet();
      pDocument->DoSomething();
      ...
     }

     void func3()
     {
      ...
      BASE_DLG oBaseDlg();
      oBaseDlg.DoModal();
      ...
     }
}

IMPLEMENT_DYNCREATE(CBaseView<BASE_T, BASE_DOC, BASE_DLG>, CListView)

After that I want to use the CBaseView for the others views:

CMyView : public CBaseView <MyType, MyDocument, MyDlg> {...};

The problem is coming with:

DECLARE_DYNCREATE(CBaseView<BASE_T, BASE_DOC, BASE_DLG>)

and

IMPLEMENT_DYNCREATE(CBaseView<BASE_T, BASE_DOC, BASE_DLG>, CListView)

It gаve me some strange errors. I saw that I can't use this macros with a template class. Also found a similar topic, but I'm quite new in MFC (and in programming like all) and I can't rewrite it so to works for my three template arguments.

I'm worried that I tried everything I could think of and still haven't done it. I really need to find a way to do it or at least an alternative, so guys please help me!

  • what is `T`, `D` and `Dlg` ? What is `CBaseView` a template? – 463035818_is_not_an_ai May 18 '20 at 19:20
  • T - just a data type, used in CBaseView methods (is differenet for each view), D - the document type of the view, Dlg - CDialog class, that is also different for each view. I'm not sure if I understood your question correctly? – Milen Georgiev May 18 '20 at 19:23
  • templates are only compile-time, but `DECLARE_DYNCREATE` is for runtime. At some point you need to instantiate the template so that at runtime instances can be created by the framework. – 463035818_is_not_an_ai May 18 '20 at 21:17
  • How to instantiate the template? – Milen Georgiev May 18 '20 at 21:45
  • Pleae include a [mcve]. The question is rather unclear. Did you write `CBaseView` ? Why does it need to be a template? – 463035818_is_not_an_ai May 18 '20 at 21:50
  • Well, I hope that after the edit the question is clearer :) – Milen Georgiev May 18 '20 at 22:07
  • @MilenGeorgiev MFC used to have special macros for templates e.g. `IMPLEMENT_DYNCREATE_T` still referenced [here](https://www.codeproject.com/Articles/5170/Splitter-Views-with-Templates) for example. They have been retired since, which makes one question the wisdom of trying to redo what the library authors themselves decided to undo. – dxiv May 19 '20 at 01:56

1 Answers1

2

I don't know MFC, but the problem is quite clear: The macros do not accept template instantiations. This is understandable, because macros are expanded first and once you instantiate the template, you wont have CBaseView<BASE_T, BASE_DOC, BASE_DLG> but something like CBaseView<Foo,FooDoc,FooDlG>, ie concrete types for the parameter.

DECLARE_DYNCREATE is to enable creation of instances on the fly at runtime, while templates only exist at compiletime, so at some point you'll need to decide what instantiations of the template you want to use at runtime. You could keep the implementation in the template, but for the types used with the framework you use:

class View1 : public CBaseView<Foo1,FooDoc1,FooDlg1> {
     DECLARE_DYNCREATE(View1)
};
IMPLEMENT_DYNCREATE(View1,CListView)
class View2 : public CBaseView<Foo2,FooDoc2,FooDlg2> {
     DECLARE_DYNCREATE(View2)
};
IMPLEMENT_DYNCREATE(View2,CListView)
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185