Custom CMDIChildWndEx template class linking errors - c++

Ok, I have defined the template class, which compiles as expected, when I implement this class in a function of the CMainFrame of the application and compile it, I receive unresolved linking errors.
void CMainFrame::OnFunc()
{
CTestList<CMyClass> list;
}
The linking errors:
1>mainfrm.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall CTestList<class CMyClass>::~CTestList<class CMyClass>(void)" (??1?$CTestList#VCWnd####UAE#XZ) referenced in function "protected: void __thiscall CMainFrame::OnFunc(void)" (?OnFunc#CMainFrame##IAEXXZ)
1>mainfrm.obj : error LNK2019: unresolved external symbol "public: __thiscall CTestList<class CMyClass>::CTestList<class CMyClass>(void)" (??0?$CTestList#VCWnd####QAE#XZ) referenced in function "protected: void __thiscall CMainFrame::OnFunc(void)" (?OnFunc#CMainFrame##IAEXXZ)
I've checked all the obvious missing headers, undefined functions, etc, but still it throws these errors at me, the files are all part of the main application and are not in static/shared libs, as this is the error I would expect if i'd done so..
Here is the basic definition of the template class cut right down, I've followed what I believe to be the correct path in constructing the class, and all my research seems to suggest its correct.
Really need to get this nailed ASAP, so if you guys & girls could help I would be very grateful.
Cheers,
DIGGIDY
/////////////////////////////////////////////////////////////////////////////
// CTestList class
template <class T>
class CTestList : public CMDIChildWndEx
{
//DECLARE_DYNAMIC(CTestList<T>)
public:
CTestList();
virtual ~CTestList();
protected:
// Generated message map functions
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
// CTestList
//IMPLEMENT_DYNCREATE(CTestList<SDCM_OBJECT_TYPE>, CMDIChildWndEx)
template <class T>
CTestList<T>::CTestList()
{
}
template <class T>
CTestList<T>::~CTestList()
{
}
BEGIN_TEMPLATE_MESSAGE_MAP(CTestList, T, CMDIChildWndEx)
ON_WM_CREATE()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTestList message handlers
template <class T>
int CTestList<T>::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if ( CMDIChildWndEx::OnCreate(lpCreateStruct) == -1 )
return -1;
// this removes the crappy un-drawn client edge on screen
ModifyStyleEx(WS_EX_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE);
return 0;
}

Your template code is not inlined in the header file. When the template class cpp file is being compiled the compiler doesn't know what instances of T will be required. When your main file is being compiled and you need to instantiate a CTestList the compiler only has the template header file. You need to add a force explicite template instantiation to your template .cpp file - so at the moment this is compiled it will generation the correct CMyClass instantiation of the template.

Related

exporting Template class in dll unresolved external

I am trying to create a class library dll that exports a template class. I have a local version of the same class and it must be coincidental, but it works correctly. I know this doesn't really mean much, clearly something is wrong.
The exported template class in the library dll is:
template <class CcmBlock>
class CCMSHARED_EXPORT CcmFilter
{
public:
CcmFilter()
{
mBlock = nullptr;
////mBlockList = new std::list<CcmBlock*>();
}
void add(CcmFrame* frame)
{
if (frame == nullptr)
return;
mBlock = new CcmBlock(
frame->getFrameData(),
frame->getSampleRate(),
0xFFFFFFFF,
frame->getBlockSize(),
frame->getDomain()
);
mBlockList->push_back(aBlock);
}
CcmBlock* get()
{
return mBlock;
}
private:
CcmBlock* mBlock;
////std::list<CcmBlock*>* mBlockList;
};
On the application side:
CcmFilter<FooBlock>* oneFilter = new CcmFilter<FooBlock>();
//Filter<Block>* filter = new Filter<Block>();
CcmFrame* frame = new CcmFrame(0, 50000, 40, 1024, Domain::Time);
oneFilter->add(frame);
CcmBlock* block = oneFilter->get();
FooBlock* fooBlock = dynamic_cast<FooBlock*>(block);
if (fooBlock == nullptr)
{ //Report Error }
else
{ // Do the work}
and the FooBlock class is derived from CcmBlock as follows:
class FooBlock : public CcmBlock
{
public:
FooBlock(int* ipblock, DWORD dwSampleRate, DWORD dwMicrophoneIndex, DWORD dwBlockSize, Domain domain);
void process();
};
The library compiles and builds the dll. When I attempt to build the application I get messages:
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl CcmFilter::CcmFilter(void)" (__imp_??0?$CcmFilter#VFooBlock####QEAA#XZ) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow##QEAA#PEAVQWidget###Z)
mainwindow.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl CcmFilter::add(class CcmFrame *)" (__imp_?add#?$CcmFilter#VFooBlock####QEAAXPEAVCcmFrame###Z) referenced in function "public: __cdecl MainWindow::MainWindow(class QWidget *)" (??0MainWindow##QEAA#PEAVQWidget###Z)
DLL-s are loaded at runtime, while templates are instantiated at compile time.
A work-around which is not ideal but might work for a very limited use case is to explicitly instantiate a template somewhere after their declaration. That is, add something like:
template class CcmFilter<FooBlock>;
For details, see https://msdn.microsoft.com/en-us/library/by56e477(VS.80).aspx
Just do not use declspec. But in your case template will be compiled each time when you include it in *.cpp file. It wont be exported.
In order to export some well-known implementations of your template you probably should use template explicit instantiation definitions in tandem with __declspec(export).

error LNK2019: unresolved external symbol "public: __thiscall

I have a class like
template <class T>
class LinkedListItem
{
public:
LinkedListItem(T value);
LinkedListItem(const LinkedListItem<T>& rhs);
T getValue(void);
LinkedListItem<T>& getNext(void);
void setNext(LinkedListItem<T>& next);
LinkedListItem<T>& operator=(const LinkedListItem<T>& rhs);
~LinkedListItem();
private:
T _value;
LinkedListItem& _next;
};
I am trying to write a unit test like
TEST_CLASS(LinkedListUnitTests)
{
public:
TEST_METHOD(Add_to_An_Empty_Linked_List)
{
LinkedListItem<int> item(1);
}
//private:
};
When I try to just build the above code I get the ugly error -
error LNK2019: unresolved external symbol "public: __thiscall cpp::libraries::datastructures::LinkedListItem::LinkedListItem(int)" (??0?$LinkedListItem#H#datastructures#libraries#cpp##QAE#H#Z) referenced in function "public: void __thiscall CppLibrariesTests::LinkedListUnitTests::Add_to_An_Empty_Linked_List(void)" (?Add_to_An_Empty_Linked_List#LinkedListUnitTests#CppLibrariesTests##QAEXXZ)
I am using Visual Studio 2012.
Interestingly, If I add template in the unit test class like below the compile error goes away but the tests are not discovered and I can't run them.
template<class T>
TEST_CLASS(LinkedListUnitTests){..}
I am trying to pick up C++ after a long time so I won't be surprised if I am doing something very stupid. Any thoughts anyone?
Templates must ideally be implemented inline. Second pass of compiler cannot re use the CPP file that has the implementation. Or, you need to #include the CPP file also.
Refer this article

linker error (unresolved symbol) with template class in DLL

I get a linker error - unresolved symbol - when using a (specialized) template class from a DLL (Visual Studio 2008 compiler). I tried to use the 'explicit template instantiation' trick described also here in Stackoverflow, but it didn't work. I broke it down to a very simple reproducable example:
I have a dynamic library (DLL) 'MyTemplates.lib' with a header file 'MyTemplates.h' (and a source file 'MyTemplates.cpp' without any code which simply includes this header file) with the following content:
template <class T>
class A
{
public:
A()
{ int x = 7; }
};
template <class T>
class B : public A<T>
{
public:
B()
{}
};
// do explicit template instantiation for classes A<int> and B<int>
// macro 'MYTEMPLATES_API' is defined in the usual way as:
//#ifdef MYTEMPLATES_EXPORTS
// #define MYTEMPLATES_API __declspec( dllexport )
//#else
// #define MYTEMPLATES_API __declspec(dllimport)
//#endif
template class MYTEMPLATES_API A<int>;
template class MYTEMPLATES_API B<int>;
Now i have another dynamic library 'UserLibary' (which links against 'MyTemplates.lib') with the files 'Util.h' and Util.cpp'. The file 'Util.h' is as follows:
#include "MyTemplates.h"
class UserClass
{
public:
UserClass();
public:
A<int> bla;
B<int> blubb;
};
and the content of the file 'Util.cpp' is:
#include "Util.h"
UserClass::UserClass()
{
}
The problem is now that my library 'UserLibrary' does compile well, but it gives two linker errors as follows:
1>Util.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall B<int>::B<int>(void)" (__imp_??0?$B#H##QAE#XZ) referenced in function "public: __thiscall UserClass::UserClass(void)" (??0UserClass##QAE#XZ)
1>Util.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall A<int>::A<int>(void)" (__imp_??0?$A#H##QAE#XZ) referenced in function "public: __thiscall UserClass::UserClass(void)" (??0UserClass##QAE#XZ)
So the linker can not find the symbols for the default constructors of classes A<int> and B<int>. Why is this possible, and how can i get rid of these linker errors ? I thought that the explict template instantiation of the class A<int> and B<int> (in file 'MyTemplates.h') would solve this, but unfortunately it doesn't seem to help - or am I using it in the wrong way ? My compiler is Visual Studio 2008, operating system is windows 7 64 bit, and code is compiled in 64bit.

Template Specialization with External Errors

When I attempted to specialize one of my template functions, Visual Studio threw me an external error, including an error for a function that was not specialized.
The three errors:
1>------ Build started: Project: Project3, Configuration: Debug Win32 ------
1>main.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall linearList<class FriendToken>::reverse(void)" (?reverse#?$linearList#VFriendToken####UAEXXZ)
1>main.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall linearList<class FriendToken>::print(void)" (?print#?$linearList#VFriendToken####UAEXXZ)
1>main.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall linearList<class FriendToken>::insertionSort(void)" (?insertionSort#?$linearList#VFriendToken####UAEXXZ)
Here is the relevant part of the code:
template<class T>
class arrayList : public linearList<T>
{
public:
//other methods
void reverse();
void print();
void insertionSort();
};
template<class T>
void arrayList<T>::reverse()
{
//method body
}
template<>
void arrayList<FriendToken>::insertionSort()
{
//method body
}
template<>
void arrayList<FriendToken>::print()
{
//method body
}
template<class T>
void arrayList<T>::insertionSort(){}
template<class T>
void arrayList<T>::print(){}
Your example shows specializations of the arrayList member functions which I assume are supposed to be overriding their virtual equivalants in linearList. The linker is saying it cant find the virtual members in the class linearList which is not included in your example.
virtual void __thiscall linearList<class FriendToken>::reverse(void)
If I add a definition of linearList like this the linker is quiet (on MSVC2010, I also added a empty FriendToken class to make things work).
template<typename T>
class linearList
{
public:
virtual void reverse() = 0; //pure virtual
virtual void print() = 0;
virtual void insertionSort() = 0;
};
If this is not your problem please post the code for linearList and I will update my answer as that is surely the source of your problem.
If needed for reference here is how I used the function reverse to test:
arrayList<FriendToken> a;
static_cast<linearList<FriendToken>&>(a).reverse();

LNK2019 linking error in C++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ template, linking error
I have two linking errors and I have no idea what's wrong with the code and how to fix them:
main.obj:-1: error: LNK2019: unresolved external symbol "public:
__thiscall A::A(void)" (??0?$A#VB####QAE#XZ) referenced in function "public: __thiscall B::B(void)" (??0B##QAE#XZ)
and
main.obj:-1: error: LNK2019: unresolved external symbol "public: void
__thiscall A::exec(void (__thiscall B::*)(void))" (?exec#?$A#VB####QAEXP8B##AEXXZ#Z) referenced in function "public:
void __thiscall B::run(void)" (?run#B##QAEXXZ)
Explaining the code a little:
This class has to execute a function from the derived class. function exec is called from the derived class with a function from the derived class parameter. Signature of this function is void function();
//header.h
#ifndef HEADER_H
#define HEADER_H
template <class T>
class A
{
public:
typedef void (T::*ExtFunc)();
A();
void funcA();
void exec(ExtFunc func);
};
#endif // HEADER_H
//header.cpp
#include "header.h"
template<typename T>
A<T>::A() { }
template<typename T>
void A<T>::funcA()
{
cout << "testA\n";
}
template<typename T>
void A<T>::exec(ExtFunc func)
{
(T().*func)();
}
In main.cpp I derive a class from A class and pass the derived class as template paramtere. Then I execute function exec through the run() function.
//main.cpp
#include <iostream>
#include "header.h"
using namespace std;
class B : public A<B>
{
public:
B() { }
void run()
{
exec(&B::funcB);
}
void funcB()
{
cout << "testB\n";
}
};
int main()
{
B ob;
ob.run();
return 0;
}
Can anyone tell me what's going on?...
When you are using templates, generally you cannot put the implementation in a .cpp file - you have to put the whole class in the header. So move all the code from header.cpp to the .h.
You can get around this by doing an explicit instantiation inside the .cpp file - instantiating the template for a particular type. But this requires that you know ahead of time which types will need an instantiation and will prevent you from adding new instantiations. The only benefit is a reduction in compile time.