Templates and .h/.cpp files

Started by
7 comments, last by Nerusai 20 years ago
(MSVC++.NET) Does anyone have a clue why I can make templates if the whole thing is in a .h file, but when I place the non-header part in a .cpp files the compiler will start spitting out errors like: Main.obj : error LNK2019: unresolved external symbol "public: __thiscall CDatabase::CDatabase(void)" (??0?$CDatabase@VCTest@@@@QAE@XZ) referenced in function _main So the following would work:

### IN DATABASE.H ###

template <class TDatabase>
class CDatabase
{
public:
		 CDatabase ( void ); /* Constructor */
		~CDatabase ( void ); /* Destructor  */

// private:

};

/* Constructor */
template <class TDatabase>
CDatabase <TDatabase> ::CDatabase ( void )
{
}

/* Destructor */
template <class TDatabase>
CDatabase <TDatabase> ::~CDatabase ( void )
{
}

### IN MAIN.CPP ###
#include "Database.h"

void main ( void )
{
	CDatabase <CTest> *pDatabase;

	pDatabase = new CDatabase <CTest> ( );

	delete pDatabase;
	pDatabase = 0;
}


But this would not:

   
### IN DATABASE.H ###

template <class TDatabase>
class CDatabase
{
public:
		 CDatabase ( void ); /* Constructor */
		~CDatabase ( void ); /* Destructor  */

// private:

};

### IN DATABASE.CPP ###
#include "Database.h"

/* Constructor */
template <class TDatabase>
CDatabase <TDatabase> ::CDatabase ( void )
{
}

/* Destructor */
template <class TDatabase>
CDatabase <TDatabase> ::~CDatabase ( void )
{
}

### IN MAIN.CPP ###
#include "Database.h"

void main ( void )
{
	CDatabase <CTest> *pDatabase;

	pDatabase = new CDatabase <CTest> ( );

	delete pDatabase;
	pDatabase = 0;
}
I really can't stand weird things like these, is it anything I did wrong, or anyway to bypass this, because I like to be consistent and headers are headers and are not to contain source. [edited by - Siaon on March 24, 2004 9:53:48 AM]
---Yesterday is history, tomorrow is a mystery, today is a gift and that's why it's called the present.
Advertisement
I had posted this question a while back too.

You need to have all the implementation for the classes functions in the header file as the linker doesn''t know what sort of data you will be using in your template.
You can''t split templates into multiple files. You should be able to, according to the standard, using the export keyword, but Comeau C++ is the only compiler I''ve ever heard of that supported that feature; it''s just too much trouble to implement.

So stick your entire template structure back in the header and enjoy life!
It''s not excactly enjoy life ^^ It''d be breaking my standard whic is horrible enough, also the templates can grow quite large since I derive from them and specialize and the whole bunch, so it adds greatly to the compiling time.

This is a major annoyance, but alas, thanks for the quick replies though, basically they force you to recompile the entire bunch even if you didnt instantiate a new template instance, while they just could check if you did and only then build a new .obj

Ah well, guess this is easier on them.
---Yesterday is history, tomorrow is a mystery, today is a gift and that's why it's called the present.
Anyway, how excactly do I EXPORT it in this example so I could use it?

Hmmm, MSDN says:

quote:
The export keyword is not supported on templates. For example, the following sample will not compile:

export template void fun(T);
export template class A;


[edited by - Siaon on March 24, 2004 10:28:31 AM]
---Yesterday is history, tomorrow is a mystery, today is a gift and that's why it's called the present.
You can split the source in two files (H and CPP), but, when you use these files (in main.cpp, for example), you must to include the CPP file. It''s strange, but it works.

However, because you are using templates, no object file will be generated for these source files. So, the source will be re-compiled each time.

//// IN DATABASE.H
template
class CDatabase
{
public:
CDatabase ( void ); /* Constructor */
};

//// IN DATABASE.CPP
/* Constructor */
template
CDatabase <tdatabase> ::CDatabase ( void )
{
// code
}

//// IN MAIN.CPP
#include "database.cpp"



Eduardo
[<(~)>]
Eduardo[<(~)>]

quote:Original post by ewbasso
You can split the source in two files (H and CPP), but, when you use these files (in main.cpp, for example), you must to include the CPP file. It''s strange, but it works.

However, because you are using templates, no object file will be generated for these source files. So, the source will be re-compiled each time.

//// IN DATABASE.H
template
class CDatabase
{
public:
CDatabase ( void ); /* Constructor */
};

//// IN DATABASE.CPP
/* Constructor */
template
CDatabase <tdatabase> ::CDatabase ( void )
{
// code
}

//// IN MAIN.CPP
#include "database.cpp"



Eduardo
[<(~)>]


Including the .cpp file will work, but I prefer to use .inl files. I find it a bit cleaner and avoids confusion.
Instantiator: A (Mostly) Portable Framework for Separate Compilation of Templates


[edited by - petewood on March 24, 2004 11:15:17 AM]
Also this is a Frequently Asked Question.

This topic is closed to new replies.

Advertisement