Linker error 'unresolved external symbol' : working with templates - c++

I have a template based class [Allotter.h & Allotter.cpp]:
template <typename allotType> class Allotter {
public:
Allotter();
quint32 getAllotment(allotType*);
bool removeAllotment(quint32, int auto_destruct = 0);
private:
QVector<QPair<quint32, allotType*>> indexReg;
int init_topIndex;
};
and it's usage is shown as [ActiveListener.h & ActiveListener.cpp]:
class ActiveListener: public QObject {
Q_OBJECT
public:
ActiveListener();
private slots:
void processConnections();
void readFromSocket(int);
private:
QTcpServer* rootServer;
QSignalMapper* signalGate;
Allotter<QTcpSocket> TcpAllotter;
};
I am not showing the complete definitions, since it doesn't really matter. The problem is when I compile, all files compile properly. The files are in a VC++ project. Earlier when I did not use a template-based approach for Allotter, everything was compiling and linking fine. But now, I get this error:
1>ActiveListener.obj : error LNK2019: unresolved external symbol "public: __thiscall Allotter<class QTcpSocket>::Allotter<class QTcpSocket>(void)" (??0?$Allotter#VQTcpSocket####QAE#XZ) referenced in function "public: __thiscall ActiveListener::ActiveListener(void)" (??0ActiveListener##QAE#XZ)
1>ActiveListener.obj : error LNK2019: unresolved external symbol "public: unsigned int __thiscall Allotter<class QTcpSocket>::getAllotment(class QTcpSocket *)" (?getAllotment#?$Allotter#VQTcpSocket####QAEIPAVQTcpSocket###Z) referenced in function "private: void __thiscall ActiveListener::processConnections(void)" (?processConnections#ActiveListener##AAEXXZ)
The surprising thing is, that the constructor, ActiveListener::ActiveListener() does not make any reference at all Allotter<QTcpSocket>::Allotter(). The second reference however does exist. But I don't understand why the linker isn't able to resolve this external symbol.
The build output just before the errors appear is:
1>Moc'ing ActiveListener.h...
1>Compiling...
1>stdafx.cpp
1>Compiling...
1>ActiveListener.cpp
1>Allotter.cpp
1>moc_ActiveListener.cpp
1>main.cpp
1>Generating Code...
1>Linking...
I don't understand if any of this is relevant, mostly because all this used to work perfectly before. It's just that after I use templates a problem is caused.
Any help will be appreciated. Thanks a lot.

You cannot split templates into .h and .cpp files - you need to put the complete code for the template in the .h file.

Generally speaking it is considered best practice to write your template code entirely inside header files. There is an important technical reason for this: when you instantiate a template, the C++ compiler needs to generate code from that template that is specific to the template parameters that you have specified. If your template code is placed entirely in your headers, this is done for you automatically.
It is definitely possible to write template code the way that you have, with the implementation placed in cpp files. If you do this, however, you are required to explicitly instantiate the template instance that you intend to use.
In your case, you need to add the following line to a .cpp file in your project:
template class Allotter<QTcpSocket>;

Since you can't place template implementation in .cpp files, it is considered a good practice to use .inl files for the template implementation and include them from the template headers.

Related

CMake not linking .obj files properly LNK2019 __thiscall

Firstly, I've been working on this for days now and I've tried all possible fixes (went to 10th Google search page searching for a fix) but I can't get it to work.
I'm porting Unix app (G++/Bison/Flex) to Windows (MSVC/WinBison/WinFlex). I'm using CMake as a build system and the idea is to build the project from VS CMD and get VS project ready for modification. The project is meant to work on both platforms so all the modifications should be done in CMakeLists.txt so that I don't have to write special instructions done in VS.
Problematic line in preprocessor.cc is
State current(task->CPFs);
while the method State(std::vector<ConditionalProbabilityFunction*> const& cpfs) is declared in states.h with following code:
struct State {
State(std::vector<ConditionalProbabilityFunction*> const& cpfs);
State(State const& other) : state(other.state) {}
State(int stateSize) : state(stateSize, 0.0) {}
and implemented in states.cc:
State::State(vector<ConditionalProbabilityFunction*> const& cpfs) {
for (unsigned int i = 0; i < cpfs.size(); ++i) {
state.push_back(cpfs[i]->getInitialValue());
}
}
states.h is included in states.cc and rddl.h (which is included in preprocessor.cc) and class States is forward declared in preprocessor.h (which is included in preprocessor.cc).
The errors I'm getting are
[ 36%] Linking CXX executable rddl-parser.exe
preprocessor.cc.obj : error LNK2019: unresolved external symbol "public: __thiscall State::State(class std::vector<struct ConditionalProbabilityFunction *,class std::allocator<struct ConditionalProbabilityFunction *> > const &)" (??0State##QAE#ABV?$vector#PAUConditionalProbabilityFunction##V?$allocator#PAUConditionalProbabilityFunction###std###std###Z) referenced in function "private: void __thiscall Preprocessor::prepareActions(void)" (?prepareActions#Preprocessor##AAEXXZ)
rddl.cc.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall LogicalExpression::evaluate(double &,struct State const &,class ActionState const &)const " (?evaluate#LogicalExpression##UBEXAANABUState##ABVActionState###Z)
Linking, when build on Unix, works perfectly. But when I run it on Windows, I get this error.
This is the part of CMake code that does the linking:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG")
add_executable(rddl-parser ${RDDL_PARSER_SOURCES} ${FLEX_scanner_OUTPUTS} ${BISON_parser_OUTPUTS})
target_link_libraries(rddl-parser ${FLEX_LIBRARIES} ${BISON_LIBRARIES})
The option to copy the definition of the function to the source file is a no go.
OK, there was some almost duplicate code in this project where I noted that State was defined as struct and not as a class. When I switched it to being defined as class with all public methods, the compilation passed. It's interesting that this wasn't an issue on Unix and is on Windows.
Check whether the declaration of the function/class match exactly their definitions.
It could happen that when you compile logical_expressions.cc you define something that is not identical to the forward declaration for preprocessor.cc and rddl.cc files.

LNK2019 unresolved external symbol after moving functions to another header file

I had two array templates in one of my header files, everything worked well. Then I thought, I'd better get some more pedantism into my code, so I moved them all into another header file, mostly just for them (and for another function, that wants to use one of them). And then I got LNK2019 error every time I used functions from these templates in other header files.
Since everything was good before I pasted my code elsewhere, I assume the code is okay, it's just my lack of understanding. Basically, the question is: why do I get a linker error when I moved my function to another header file?
Here is an example of one of my errors:
Error LNK2019 unresolved external symbol "public: char __thiscall C2DArray::Get(int,int)" (?Get#?$C2DArray#D##QAEDHH#Z) referenced in function "public: char __thiscall SGame::GetRecordOutput(int,int)" (?GetRecordOutput#SGame##QAEDHH#Z) Mastermind C:\Users\Master\Documents\Visual Studio 2015\Projects\Mastermind\Mastermind\Menu.obj 1
I'm using Visual Studio 2015 if it matters.
Thank you for the reply. As it seems, I have resolved my problem. The cause was the class templats, which were not specialized (and had to be). All I had to do is include what types of these templates I wanted. Sorry for posting before doing more extensive research.

static library linkage failure in visual c

In visual c++, I created a static library with two files, myLib.h and myLib.cpp. I also have a console application project with the file testSequence.cpp that references this library.
Within myLib.h I have defined a class template<class prec> class sequence which has the function declaration prec *getPrimes(int numToGet) this function is then defined in myLib.cpp. However, when I build testSequence, there is a linking error, and it says error LNK2019: unresolved external symbol "public: int * __thiscall mathLib::sequence<int>::getPrimes(int)" (?getPrimes#?$sequence#H#mathLib##QAEPAHH#Z) referenced in function "char * __cdecl codeString(char *,char *,bool)" (?codeString##YAPADPAD0_N#Z)
So, yeah, help would be nice.
Read this for an explanation of the error.
Basically, what you're trying to do cannot be done. The compiler must be able to see the implementation of the class template when it tries to instantiate it for a given template type parameter. You need to move the implementations for all the member functions to the header file.

unresolved external symbol for __declspec(dllimport) when using dll to export class

I want to define a derived class based on a dll exported class. The base class is defined in Project A, and the derived class is in Project B.
Firstly, in Project A, preprocessor MYDLL_BUILD is defined. And I use a header file to specify export/import:
#if !defined(MYDLL_BUILD)
# pragma comment(lib, "myDll.lib")
#endif
#if defined(MYDLL_BUILD)
# define MYDLL_API __declspec(dllexport)
#else
# define MYDLL_API __declspec(dllimport)
#endif
Then I define the base class:
class MYDLL_API DllObject
{
public:
virtual ~DllObject() {}
protected:
DllObject() { m_count = 3; }
private:
int m_count;
};
In Project B, the preprocessor MYDLL_BUILD is not defined. Here is the derived class:
class MyClass : public DllObject
{
public:
~MyClass(){}
MyClass() { m_data = 20; }
private:
int m_data;
};
I have included the dll and lib file, but still I get the unresolved external symbol error:
2>Test_Entry.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall ADAI::DllObject::~DllObject(void)" (__imp_??1DllObject#ADAI##UAE#XZ) referenced in function "public: virtual __thiscall MyClass::~MyClass(void)" (??1MyClass##UAE#XZ)
2>Test_Entry.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) protected: __thiscall ADAI::DllObject::DllObject(void)" (__imp_??0DllObject#ADAI##IAE#XZ) referenced in function "public: __thiscall MyClass::MyClass(void)" (??0MyClass##QAE#XZ)
2>c:\Users\Adai\Documents\Visual Studio 2010\Projects\Test_Main\Debug\Test_Main.exe : fatal error LNK1120: 2 unresolved externals
I searched online, most of the answers claim that the lib is missing. But those instructions do not solve my problem.
When I change
class MYDLL_API DllObject
to
class __declspec(dllexport) DllObject
The solution compiles with no error. I really do not understand the reason. Can someone please help? Thanks in advance.
The reason is inlining.
In short, to make inline functions possible C++ must allow the same definition of function to be included and compiled in multiple compilation units (basically .cpp files) without causing errors. Compiler can, but doesn't have to emit code for any of this definitions. Then linker is allowed to chose one copy.
This complicates dll creation because you need to export exactly one copy but compiler doesn't know which copy is the right one. In this case by adding some code to DllObject.cpp you made the compiler emit code for DllObject and linker had some copy of DllObject::~DllObject to export.
I cannot give you more detailed explanation of your particular case because I don't know full source and compilation options for your project.
I had the same issue today. I was including the .dll and .lib files from my version of DllObject, But it wasn't helping.
To fix, What I had to do was add the .lib files name to my MyCLass version's project's Properties->Linker->Input->Additional dependencies.
If this doesn't work, You might want to add the .lib location's directory address in Properties->Linker->General->Additional library directories.

Linking error in C++ - implementing a indexList

Linking...
Directory.obj : error LNK2019: unresolved external symbol "public: void __thiscall indexList<class entry,100>::read(class std::basic_istream<char,struct std::char_traits<char> > &)" (?read#?$indexList#Ventry##$0GE###QAEXAAV?$basic_istream#DU?$char_traits#D#std###std###Z) referenced in function _main
Getting this error and others associated with indexList implementation. I have included all the right files, not sure what this means?
indexList.h
indexList.cpp
Also, using VS .NET 2003 - They are under the "Source Files" and "Header Files" However, I tested with deleting the indexLish.h and the error doesn't change?
What you have is a class template. This means when the compiler needs to call a function, it will look at your template definition and generate the corresponding code as needed.
For example, the following probably has a compile-time error in it if tried to call it:
template <typename T>
void doSomething(const T& x) {
x->_this_function_does_not_exist_ever_();
}
But as long as you don't call doSomething you won't get errors.
The problem you have is that your header file tells the compiler "hey, these functions exist", but when the compiler tries to generate them it cannot find any definitions. (You cannot "compile" definitions in a source file and link them in, they must be visible to the caller.)
The most common solution is to simply define the entire class template in the .h or .hpp file.
Are you using visual studio then include both the files into the solution and then run.
Since you are using templates, the best way is to include the definition in .H file.
I read something from this book . And here is something it may help you too.