Skip to main content
gamedev.net
🔒 Locked

template linker problem

Started by bkt Jul 31, 2005 at 10:47 AM 4 replies 950+ views
Original Post
bkt
bkt
I guess its a good thing that I am about to take a class in template metaprogramming, becuase I have just found out it has to be one of the weaker points in my programming part of my brain. I just can't seem to squash this linker bug. I'm getting an unresolved externals for a template method:

template<class Tp> bool LibraryManager::load(Tp* p,string szFilepath)
{
	// we need a path to work with anything right?
	if(szFilepath.empty())
		return false;

	// load the library and return the pointer (through OS specific functions)
	void* p = Platform::LoadLibrary( szFilepath );
	if(!p)
		return false

	m_List.push_back( p );
	p = static_cast<Tp*>( Platform::GetProcAddress(p, "ExportAPI") );
	return true;
}

class LibraryManager : public ISingleton<LibraryManager>
{
	public:
		// constructor/destructor
		LibraryManager(void);
		~LibraryManager(void);

		// methods
		template<class Tp> bool load(Tp*,string);
	private:
		// members 
		CLibraryList m_List;
};

bool VideoTask::start(void)
{
	// we're loading the video library up to make sure we have use of it
	if(!LibraryManager::ptr()->load(m_pDevice,"opengl.dll"))
		return false;
	return true;
}


The core.hpp file does include the library.hpp too. Here's the linker error:

Linking...
tasks.obj : error LNK2019: unresolved external symbol "public: bool __thiscall LibraryManager::load<class IVideoDevice>(class IVideoDevice *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)"


Anyone have any ideas? Thanks a head of time.I guess its a good thing that I am about to take a class in template metaprogramming, becuase I have just found out it has to be one of the weaker points in my programming part of my brain. I just can't seem to squash this linker bug. I'm getting an unresolved externals for a template method:

template<class Tp> bool LibraryManager::load(Tp* p,string szFilepath)
{
	// we need a path to work with anything right?
	if(szFilepath.empty())
		return false;

	// load the library and return the pointer (through OS specific functions)
	void* p = Platform::LoadLibrary( szFilepath );
	if(!p)
		return false

	m_List.push_back( p );
	p = static_cast<Tp*>( Platform::GetProcAddress(p, "ExportAPI") );
	return true;
}

class LibraryManager : public ISingleton<LibraryManager>
{
	public:
		// constructor/destructor
		LibraryManager(void);
		~LibraryManager(void);

		// methods
		template<class Tp> bool load(Tp*,string);
	private:
		// members 
		CLibraryList m_List;
};

bool VideoTask::start(void)
{
	// we're loading the video library up to make sure we have use of it
	if(!LibraryManager::ptr()->load(m_pDevice,"opengl.dll"))
		return false;
	return true;
}


The core.hpp file does include the library.hpp too. Here's the linker error:

Linking...
tasks.obj : error LNK2019: unresolved external symbol "public: bool __thiscall LibraryManager::load<class IVideoDevice>(class IVideoDevice *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)"


Anyone have any ideas? Thanks a head of time. [Edited by - bkt on August 1, 2005 10:11:35 PM]
-John "bKT" Bellone [homepage] [[email=j.bellone@flipsidesoftware.com]email[/email]]
SiCrane
SiCrane
Unless your compiler supports the export keyword, and seeing as that looks like a MSVC error code, I'm willing to bet that yours doesn't, then you can't put the definition of a template in a separate source file without explicit instantiation for specific types. Without explicit instantiation, the complete definition of the template needs to be available at point of instantiation, which means, in effect, that the definition needs to go into the header. (Or an inline file of some sort, etc.)

For more details see these articles: "Export" Restrictions, Part 1 and "Export" Restrictions, Part 2.
bkt
bkt
Hrm. Okay. I'll need to look into that.
-John "bKT" Bellone [homepage] [[email=j.bellone@flipsidesoftware.com]email[/email]]
bkt
bkt
I still don't understand this, heh, oh well.
-John "bKT" Bellone [homepage] [[email=j.bellone@flipsidesoftware.com]email[/email]]
bkt
bkt
So, basically, let me get this straight. You're telling me I'm going to have to make a template declaration for each type that I want to use? I don't understand. I thought this was how templates worked, you lost me with this export keyword, which doesn't seem to be a keyword I've ever seen--nor seen used before. I removed the template definition from the source file, but I just get syntax errors. There is a template definition in the class too.

The article tells me to do something that does not work with my compiler, then why did you tell me to look at them?
-John "bKT" Bellone [homepage] [[email=j.bellone@flipsidesoftware.com]email[/email]]
Fruny
Fruny
In your case it means that you must put the function template definition in a header file. You cannot split interface/implementation, because the source code of the template is needed to instanciate it. And it is not surprising you've not used, or seen the export keyword before, because most compilers have given up implementing it. As for the article SiCrane linked, understanding the big picture helps going beyond the current problem.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.