I am trying to make a factory that will have the type passed in, rather then having it hard coded for types. However, when I attempt to add the type to the factory inside of the types .cpp file, I will get a linker error. For example, he is a linker error I am currently getting.
1>RandomClass.obj : error LNK2019: unresolved external symbol "public: short __thiscall TemplatedFactory::AddType(char const *)" (??$AddType#VRandomClass###TemplatedFactory##QAEFPBD#Z) referenced in function "void _cdecl `dynamic initializer for 'private: static short RandomClass::ID''(void)" (??_E?ID#RandomClass##0FA##YAXXZ)
I tried to make the test case as small as possible, though it does cross five files, they are very small
BaseClass.h : http://codepad.org/MhZMw7t0
#pragma once
class BaseClass{ };
RandomClass.h : http://codepad.org/xoObzP8G
#pragma once
#include "BaseClass.h"
class RandomClass : public BaseClass
{
private:
static short ID;
public:
RandomClass();
virtual ~RandomClass();
};
TemplatedFactory.h : http://codepad.org/qkcTBw24
#pragma once
#include <map>
using std::map;
#include "BaseClass.h"
template<typename Type> BaseClass* createType() { return new Type; }
class TemplatedFactory
{
private:
typedef BaseClass* (*ComponentFactoryFuncPtr)();
typedef map<const char*, ComponentFactoryFuncPtr> map_type;
map_type m_Map;
public:
static TemplatedFactory &GetInstance();
template<typename Type>
short AddType(const char* componentName);
};
RandomClass.cpp : http://codepad.org/ALoF3Ysb
#include "RandomClass.h"
#include "TemplatedFactory.h"
short RandomClass::ID = TemplatedFactory::GetInstance().AddType<RandomClass>("RandomClass");
RandomClass::RandomClass() { }
RandomClass::~RandomClass() { }
TemplatedFactory.cpp : http://codepad.org/iqgNqa6H
#include "TemplatedFactory.h"
TemplatedFactory &TemplatedFactory::GetInstance()
{
static TemplatedFactory instance;
return instance;
}
template<typename Type>
short TemplatedFactory::AddType(const char* componentName)
{
ComponentFactoryFuncPtr function = &createType<Type>;
m_Map.insert(std::make_pair(componentName, function));
return 0;
}
I can remove the the linker error if I move
short RandomClass::ID = TemplatedFactory::GetInstance().AddType<RandomClass>("RandomClass");
from RandomClass.cpp to TemplatedFactory.cpp, however, I would like to have the declaration in RandomClass.cpp. Does anyone know of a way to fix this or perhaps a better design (without the use of external libraries).
Templated functions cannot have their definition and declaration separated from each other without export, which your compiler probably doesn't support. You need to move the TemplateFactory::AddType definition to the header.
You cannot place implementation of class template in cpp-file
See some technique for "cheating" on http://www.parashift.com/c++-faq-lite/templates.html#faq-35.14
Related
I assume the answer will be simple, but I cannot figure out a solution.
I have a class to be used as an interface in the h-file:
template <typename T>
class MyInterface
{
public:
MyInterface();
};
In the cpp-file it is:
#include "MyInterface.h"
template<typename T>
MyInterface<T>::MyInterface()
{
}
My class using the interface is:
class Test : MyInterface<int>
{
};
When compiling I get the error, the ctor of MyInterace is not declared.
unresolved external symbol "public: __thiscall MyInterface::MyInterface(void)" (??0?$MyInterface#H##QAE#XZ) referenced in function "public: __thiscall Test::Test(void)"
Having the ctor declared in the h-file, it compiles.
Templates are instantiated on the fly. If you want to put the constructor in a cpp file, you must specialize it.
#include "MyInterface.h"
template<>
MyInterface<int>::MyInterface()
{
}
Otherwise, it must be in a header as all template functions are managed inline.
If you'd like to keep code organized, make an inl file, with all the function bodies of your code, and then include it at the bottom of your header.
// MyInterface.h
template <typename T>
class MyInterface
{
public:
MyInterface();
};
#include "MyInterface.inl"
// MyInterface.inl
template<class T>
MyInterface<T>::MyInterface()
{
}
I am new to templates and I have searched the web for this error but I don't know how to fix it it.
Already checked Why can templates only be implemented in the header file?
State.h
template <class entityType>
class State
{
public:
State() = default;
virtual void Enter(entityType * owner);
};
EnterMine.h
#include "State.h"
class Miner;
class EnterMine : public State<Miner>
{
public:
EnterMine() = default;
virtual void Enter(Miner *) {
};
};
and Miner.cpp is blank
and the problem appears in main.cpp
#include "EnterMine.h"
int main()
{
EnterMine a;
}
The error I get is a linking error :
LNK2001 unresolved external symbol "public: virtual void __thiscall State::Enter(class Miner *)" (?Enter#?$State#VMiner####UAEXPAVMiner###Z)
(Note: this answer was written for the original question, it has been completely rewritten after that.)
Every function that is declared and used, should be defined somewhere.
It seems that you declare EnterMine::EnterMine() but never define it. If this constructor does nothing, either omit it (it will be implicitly defined by a compiler), or mark it as = default;.
class EnterMine : public State<Miner>
{
public:
EnterMine() = default;
...
};
This also applies to the State::State() constructor.
Even though it's a singleton, you're still calling the constructor. Thus, you will still need to define the constructor.
In fact, you need to define every function you declare in your header.
I'm currently transitioning from C# to c++ and I'm constantly hitting road blocks. I got an event handler system from a tutorial and try to adapt it to my needs, but there is an error which I can't understand:
Event:
#pragma once
class Event
{
protected:
virtual ~Event() {};
};
Event Hander:
#pragma once
#include "Event.h"
#include "TypeInfo.h"
#include "HandlerFunctionBase.h"
#include <map>
#include <typeindex>
class EventHandler
{
public:
void HandleEvent(const Event*);
template < class T, class EventT >
void RegisterEventFunc(T*, void (T::*memFn)(EventT*));
private:
typedef std::map<std::type_index, HandlerFunctionBase* > Handlers;
Handlers _handlers;
};
[...]
#include "EventHandler.h"
template < class T, class EventT >
void EventHandler::RegisterEventFunc(T* obj, void (T::*memFn)(EventT*))
{
_handlers[std::type_index(typeid(EventT))]=
new MemberFunctionHandler< T, EventT >(obj, memFn);
}
void EventHandler::HandleEvent(const Event* event)
{
Handlers::iterator it = _handlers.find(std::type_index(typeid(*event)));
if(it != _handlers.end())
{
it->second->exec(event);
}
}
HandlerFunctionBase:
#pragma once
#include "Event.h"
class HandlerFunctionBase
{
public:
virtual ~HandlerFunctionBase() {};
void exec(const Event* event) {call(event);}
private:
virtual void call(const Event*) = 0;
};
MemberFunctionHandler:
#pragma once
#include "handlerfunctionbase.h"
template < class T, class EventT >
class MemberFunctionHandler : public HandlerFunctionBase
{
public:
typedef void (T::*MemberFunc)(EventT*);
MemberFunctionHandler(T* instance, MemberFunc memFn) : _instance(instance), _function(memFn) {};
void call(const Event* event)
{
(_instance->*_function)(static_cast< EventT* >(event));
}
private:
T* _instance;
MemberFunc _function;
};
LogHandler
(My own class, first try to use the system)
#pragma once
#include "EventHandler.h"
#include "LogEvent.h"
class LogHandler
{
public:
LogHandler(EventHandler*);
~LogHandler(void);
private:
void Handle(LogEvent*);
};
#[...]
#include "LogHandler.h"
LogHandler::LogHandler(EventHandler *handler)
{
//This line causes the error
handler->RegisterEventFunc<LogHandler, LogEvent>(this, &LogHandler::Handle);
}
LogHandler::~LogHandler(void)
{
}
void LogHandler::Handle(LogEvent* e)
{
}
What I'm getting when trying to compile this:
Error 1 error LNK2019: unresolved external symbol "public: void __thiscall EventHandler::RegisterEventFunc(class LogHandler *,void (__thiscall LogHandler::*)(class LogEvent *))" (??$RegisterEventFunc#VLogHandler##VLogEvent###EventHandler##QAEXPAVLogHandler##P81#AEXPAVLogEvent###Z#Z) referenced in function "public: __thiscall LogHandler::LogHandler(class EventHandler *)" (??0LogHandler##QAE#PAVEventHandler###Z) D:\Dropbox\C++\D-Tris\D-Tris\D-Tris\LogHandler.obj D-Tris
How is RegisterEventFunc unresolved? It's clearly implemented !?
The compiler has to know the types used to instantiate the template to actually generate the code. But it also generates code for every translation unit (one .cpp file) independently. It doesn't "ignore the files".
So at the point you have the definition of EventHandler::RegisterEventFunc, it can't know with which parameters it will be instantiated, if it's used (instantiated) outside this translation unit.
In LogHandler, it knows about the template EventHandler::RegisterEventFunc (from header file), but as there's no definition, it simply assumes theres instantiation of RegisterEventFunc<LogHandler, LogEvent> elsewhere and doesn't emit any error.
When it's linked together, the linker finds out that no one actually instantiated RegisterEventFunc<LogHandler, LogEvent> so it can't link it together and emits the error you see.
What you can do about it is either:
1) move the definition of EventHandler::RegisterEventFunc to EventHandler.h. (IMHO, this is the usual solution)
2) Or force explicit instantiation in EventHandler.cpp, like
template
void EventHandler::RegisterEventFunc<LogHandler, LogEvent>
(LogHandler* obj, void (LogHandler::*memFn)(LogEvent*))
This "solution" breaks encapsulation, adds lots of dependencies and would be hell to maintain.
3) Or use exported templates. C++ supports (supported) templates the way you want to use them through the keyword export. It was supported only by Comeau and ICC (none of GCC, CLANG, MSVC ever supported this) and now it's removed from standard (In N3690, in [diff.cpp03.temp] (Annex. C.2.7, on page 1240) the standars says: A valid C++ 2003 declaration containing export is ill-formed in this International
Standard.). Don't even try it, I added it just for sake of completeness.
Some related questions that may be interesting for you:
How do I explicitly instantiate a template function?
Using export keyword with templates
Why can templates only be implemented in the header file? (this actually seems like duplicate....)
EDIT: To your other question: You can't remove const qualifier from a variable by static_cast. Casting constness away is potentially dangerous and should be avoided, but if you absolutely need it, you can do it by const_cast< EventT* >(event).
I've been coding for a long time now but I do not understand this error. I am writing a custom system for providing unique integer ID's to specific instances of objects (I call them tags). And I am implementing one of the classes as a Singleton.
The two classes for the Tagging system are defined as such:
#include "singleton.h"
class Tag: public bear::Singleton<Tag>
{
public:
static dUINT32 RequestTag(Tagged* requester);
static void RevokeTags(void);
private:
Tag(void);
~Tag(void);
Tagged** m_tagTable; // list of all objects with active tags
dUINT32 m_tagTable_capacity, // the maximum capacity of the tag table
m_tagIndexer; // last given tag
};
class Tagged
{
friend class Tag;
public:
inline dUINT32 GetTag(void) {return m_tag;}
private:
inline void InvalidateTag(void) {m_tag=INVALID_TAG;}
dUINT32 m_tag;
protected:
Tagged();
virtual ~Tagged();
};
The Singleton class is defined as such:
template <typename T>
class Singleton
{
public:
Singleton(void);
virtual ~Singleton(void);
inline static T& GetInstance(void) {return (*m_SingletonInstance);}
private:
// copy constructor not implemented on purpose
// this prevents copying operations any attempt to copy will yield
// a compile time error
Singleton(const Singleton<T>& copyfrom);
protected:
static T* m_SingletonInstance;
};
template <typename T>
Singleton<T>::Singleton (void)
{
ASSERT(!m_SingletonInstance);
m_SingletonInstance=static_cast<T*>(this);
}
template <typename T>
Singleton<T>::~Singleton (void)
{
if (m_SingletonInstance)
m_SingletonInstance= 0;
}
I am getting the following error upon trying to compile and link together the files:
test.obj : error LNK2001: unresolved external symbol "protected: static class util::Tag * bear::Singleton::m_SingletonInstance" (?m_SingletonInstance#?$Singleton#VTag#util###bear##1PAVTag#util##A)
1>C:...\tools\Debug\util.exe : fatal error LNK1120: 1 unresolved externals
Does anyone have any idea why I am getting this error?
You should provide a definition for your static data member at namespace scope (currently, you only have a declaration):
template <typename T>
class Singleton
{
// ...
protected:
static T* m_SingletonInstance; // <== DECLARATION
};
template<typename T>
T* Singleton<T>::m_SingletonInstance = nullptr; // <== DEFINITION
If you are working with C++03, you can replace nullptr with NULL or 0.
I am trying to implement a leftist tree using heaps as a base class. The following is the contents of heap.h:
template <class T>
class heap {
public:
virtual void init(T*) = 0;
virtual void insert(T*) = 0;
virtual T delete_min() = 0;
};
The following is the contents of leftist.cpp:
#include "heap.h"
template <class T>
class leftist_tree : public heap<T> {
private:
T* root;
public:
void init(T* a) {}
void insert(T* a) {}
T delete_min() {T a; return a;}
};
I am passing another class leftist_node as a parameter to this class using the following definition:
leftist_tree<leftist_node> mytree;
I am getting an LNK 2001 unresolved external symbol error for functions init, insert and delete_min. What am I doing wrong?
Edit:
Okay the example I have given at this point is far too complex. I have tried to reproduce the same error on a smaller scale so that someone can identify the problem more easily. I have created the following sample files.
try.cpp
#include "stdafx.h"
#include "myclass.h"
int _tmain(int argc, _TCHAR* argv[])
{
myclass<int> a;
a.hello(3);
return 0;
}
myclass.h
template <class T>
class myclass {
public:
void hello(T);
};
myclass.cpp
#include "myclass.h"
#include <iostream>
using namespace std;
template <class T>
void myclass<T>::hello(T a){
cout<<a<<endl;
system("pause");
}
I get a similar error message:
1>try.obj : error LNK2001: unresolved external symbol "public: void __thiscall myclass::hello(int)" (?hello#?$myclass#H##QAEXH#Z)
1>c:\users\meher anand\documents\visual studio 2010\Projects\try\Debug\try.exe : fatal error LNK1120: 1 unresolved externals
Can you tell me where I am going wrong right now? Thanks
Template functions are treated a little differently from regular functions. The compiler doesn't actually compile the function until you try to use it. If the only place you try to use it is a .cpp where the body of the function is undefined, it assumes it must be compiled somewhere else and makes a reference for the linker to fill in later.
In your case you defined the body of the functions in leftist.cpp, but you didn't use it there, you used it somewhere else. If you had defined it in the .h file then the definition would have been available everywhere you tried to use it and all would be well. If you had used the functions somewhere in leftist.cpp then the functions would have been created and the linker would have fixed everything up.
The general rule is to define the body of all template functions in the header files.
The template isn't instantiated for the type. The easiest way is to remove the .cpp from being compiled, and include it into the cpp where you use the template.
Another easy answer is to just define the whole template in the .h.
Whenever you see this error
error LNK20XX unresolved external symbol
It means that while linking the linker is unable to find the function definition. In your case it is error
Hope this helps you.
Let me know if you need any more help
PK
The following should work (tested with g++):
// File: heap.hh --------------------------
template <class T>
class heap {
public:a
virtual void init(T*) = 0;
virtual void insert(T*) = 0;
virtual T delete_min() = 0;
};
// File: leftist_tree.hh ------------------
#include "heap.hh"
template <class T>
class leftist_tree : public heap<T> {
private:
T* root;
public:
void init(T* ) {}
void insert(T* ) {}
T delete_min() {T a; return a;}
};
// File: leftist_node.hh ------------------
struct leftist_node {
int value;
};
// File: leftist_main.cpp -----------------
#include "leftist_tree.hh"
#include "leftist_node.hh"
int main() {
leftist_tree< leftist_node > mytree;
}