hey, got a quick question regarding template classes. I've made several data structures that I've found to be very useful (using template classes) but it's getting tiresome making a new explicit specialization every time I implement it in a new way. Such as if I want to do this in one of my programs:

Structure<std::string> temp;

I need to have this in the data structure .cpp file

template class Structure<std::string>;

Is there any way to avoid having to do this (the explicit specialization)? The standard containers (vectors, lists, etc) have this ability, I just couldn't find anywhere where it said how to do it. Thanks!

~J

Recommended Answers

All 10 Replies

Well you've kind of defeated the purpose of templates there.

Use template <class T> as the specifier in your structure then wherever you use the type, use T instead and it will be resolved at compile time.

So for example:

template <class T>
class Container
{
  Container(T _data){ data = _data; }
  ~Container(){}
  T data;
};

Which you can use by Container<std::string> *my_string_container = new Container<std::string>("Hello");

thanks for the link sid, here's my understanding of those articles: I should either live with it or use a compiler that supports "export"?

thanks to microsoft: http://msdn.microsoft.com/en-us/library/4w5cfxs1.aspx

so am I stuck? how is this accomplished with the standard containers then?

stinomus: I apologize if you misunderstood what I was asking. Give the following a try:

create a separate .cpp and header file of your template class, compile it into an object and try linking that to the object where you give your declaration (if you do that stuff manually) or just build it in VS. Example:

//container.h
template <class T>
class Container
{
  Container(T _data){ data = _data; }
  ~Container(){}
  T data;
};

//container.cpp
#include "container.h"
//functions etc
//make sure you don't put explicit specializations in here, that'd be cheating!

//main.cpp
#include "container.h"

Container<std::string> stringContainer;
//etc.

you will get linker errors and then you will understand what the problem is.

~J

>I should either live with it or use a compiler that supports "export"?
If the question is whether you should use export or live with keeping template class definitions with the declarations, you should just live with it. export is...problematic. You'd be better off not using it until everybody has more experience with it.

>stinomus: I apologize if you misunderstood what I was asking.
Actually, I was terribly confused by your original question as well. I'm still not 100% sure that export is what you were looking for.

ah, well if it's still confusing I'll state the question how I would have stated it originally. I just found my original questions in my posts have gotten bloated if I include too much. anyway, maybe 'export' is still what I was looking for, it seemed to be that way from the link, but maybe not if my question was misunderstood. Condensed version:

I have this:

//structure.h
template <class T> class Structure
{
	//stuff goes here
};

//structure.cpp
#include "structure.h"
//functions etc
template class Structure<std::string>;
template class Structure<double>;
template class Structure<unsigned int>; //dont want these

Whenever I use this structure in a new program, I usually need it for a different type (say, char) which means I need to go back to "structure.cpp" and add "template class Structure<char>;". But if it's a non-standard class (say, Shapes) not only do I need to add "template class Structure<Shapes>;" to "structure.cpp" I have to link the objects that have "Shapes" in it (add '#include "shapes.h"' to "structure.cpp"). As you can see it would quickly get tiresome.

Hopefully that cleared up the question, if 'export' is still the answer, ok; but I figure it's worth a shot clarifying.

Thanks!
~J

>Hopefully that cleared up the question
It's about as clear as it was when I first read it, but at least I have a rough idea of what to recommend.

>if 'export' is still the answer, ok
Fortunately, export is not likely to solve anything close to the problem you're having. It looks more like either poor design of the Structure template such that you need to keep specializing it (the standard containers all follow strict rules concerning the abilities of the template parameter type to avoid this).

Would it be possible to show us the definition of the Structure template and a few of the different ways you use it that require specialization?

ok, I don't know how I'd do it any differently, but here's a chuck of my structure (it's a modified doubly linked list). None of the functions do anything but move the data around and stores it (ie. I don't do T.c_str() or anything like that)

#pragma once
#include "cell.h"

template <class T> class Row
{
	private:
		unsigned int size;
		Cell<T> *firstCell, *lastCell;
		Row<T> *nextRow, *currentRow, *prevRow;

	public:
		Row();
		~Row();

		T& operator [] (unsigned int index);
		Cell<T>& operator () (unsigned int index);
		void operator = (Row<T> &value);

		void Clear();
		void AddCell(T newValue, unsigned int position);
		//other functions and accessors
};

So that's a small part of the class, as for how I use it that requires specialization, any instance of a different data type requires an explicit specialization, for example:

#include "row.h"
#include "classification.h"
#include "main.h"
using std::string;

//functions etc

function test()
{
          Row<Classification> newNodeValue, tempNodeValue;
          Row<double> coefficients1, coefficients2;
          Row<string> sectionValues1, sectionValues2;

          //blah blah blah
}

this compiles fine but gives linker errors until I include all of the following in "row.cpp"

template class Row<std::string>;
template class Row<Classification>;
template class Row<double>;

I hope I understood correctly what you were asking for.

create a separate .cpp and header file of your template class, compile it into an object and try linking that to the object where you give your declaration (if you do that stuff manually) or just build it in VS. Example:

Ah I see what you're doing now. Essentially you need to remember that templates are resolved at compile time - not link time - so if you declare your explicit type implementations and compile them into an object then that's all you get.
You get unresolved linker errors because an implementation cannot be found, when you built the structure object the only implementations were the ones that were declared in the cpp so if you declare new ones in your other project they cannot be generated because there is no code to generate from.

So just do it like the STL does, have the implementation in the structure.h as you have done and #include that file in the implementation files that you want to use it in and declare the typed version in them.

//main.cpp
#include "structure.h"

int main( int argc, char **argv )
{
  Structure<std::string> s;
  return 0;
}

No need to link to any external objects as the code for Structure<std::string> will be generated when main is compiled.

That's because you didn't read (or didn't understand) what was said in this link:
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12

The whole cause of the problem stems from the fact that the compiler needs definitions of the template before it can generate instantiations of it. All you need to do is move all your implementation code (including your function definitions) into your header file.

thanks for the responses

That's because you didn't read (or didn't understand) what was said in this link:
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12

thanks for the link sid, here's my understanding of those articles: I should either live with it or use a compiler that supports "export"?

I'll leave that one where it lies :)

As for the suggestions, adding the cpp file contents into the header worked perfectly, thank you. I guess I was too used to splitting everything into 2 parts.;)

~J

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.