Class templates and method definition location

Aug 26, 2014 at 12:23pm
Hello, I am writing a linked list to practice coding in C++.
I am using class templates to make the list universal.

In my header file I define the class template and the members and functions.
I thought that I need to implement the functions in a separate cpp file but I am getting an error, and after a bit of reading it turns out that I need to stuff all the implementation in the header file.

Is this true and if so, isn't this a bad practice? Sticking all the code in the header file?

Thanks
Aug 26, 2014 at 12:27pm
It is not bad practice by any means. The only reason implementations are typically in source files instead of headers is because it reduces compile time and means that changing the implementation of one source file only requires recompiling that one source file. If it weren't for those two things, we'd probably use source files a lot less often.
Last edited on Aug 26, 2014 at 12:27pm
Aug 26, 2014 at 12:43pm
Hmm interesting.
So I can basically implement my whole linked list inside the .h file, and then whenever I want to use it in another project, just include it and boom, I have a linked list?
Aug 26, 2014 at 12:44pm
If it's a template class, that's how you're required to do it. How do you think the C++ standard library works?
Aug 26, 2014 at 3:14pm
I've seem the declaration in a .h file and the implementation in a .i file. At the end of the .h file you #include "file.i" this just provides a way to separate the two but there's no functional difference.

The reason you have to do it this way is that when you instantiate a template class, the compiler creates a whole set of methods specific for that class. It has to. That means that the compiler must have access to the definition of the methods, not just the declarations. Note also that this means that if you instantiate a template for 5 different classes, then you get 5x the code. If you can factor out some code then you can save a lot of space in your executable.

This does NOT mean that you get twice the code if you instantiate MyTemplate<int> in two different source files. The linker is smart enough to know that the two are the same and includes only one copy of the code in your final executable.
Aug 26, 2014 at 3:58pm

This does NOT mean that you get twice the code if you instantiate MyTemplate<int> in two different source files. The linker is smart enough to know that the two are the same and includes only one copy of the code in your final executable.

Actually templates are usually expanded inline.

The reason you have to do it this way is that when you instantiate a template class, the compiler creates a whole set of methods specific for that class.

But remember because templates are created inline it is sometimes possible for the compiler to remove functions that are not used for that particular instance of the class.

This does NOT mean that you get twice the code if you instantiate MyTemplate<int> in two different source files. The linker is smart enough to know that the two are the same and includes only one copy of the code in your final executable.

Again this is not necessarily true. Every time you create an instance of a template class the compiler creates the class inline, the code is usually not reduced to one copy since each instance may be different.

Using templates does usually add to the size of the executable. But with today's desktop systems disc space and memory usage are usually of little or no concern. Speed of the program and usually more importantly, the speed of development are of much more concern.


Aug 26, 2014 at 4:00pm
a way to separate the two but there's no functional difference.

Some older MSVC could not cope with method implementations that were outside the template class definition.

*.i, *.hpp, *.icc -- the filename extension has no strict rule. The reason to use different extension is to easily classify your files to the "sources", "headers" and "template method implementations". Your IDE might like to learn your convention though.
Aug 26, 2014 at 4:19pm
Some older MSVC could not cope with method implementations that were outside the template class definition.

But since we're talking about including the implementation at the bottom of the include file everything is in the same file. Remember when you include something you basically copy it to that location.

Also even the most modern of compilers have problems if both the implementation and definitions are not in the same compilation unit.
Aug 26, 2014 at 4:56pm
Actually templates are usually expanded inline.

Thanks! I thought that was only true if you used the inline keyword, but I see it isn't.
Aug 26, 2014 at 5:12pm
Templates are implicitly inline.
Aug 26, 2014 at 6:11pm
But since we're talking about including the implementation at the bottom of the include file everything is in the same file.

I was referring to the difference between this:
1
2
3
4
template <typename T>
class Foo {
  void bar() {}
};

and this:
1
2
3
4
5
6
7
template <typename T>
class Foo {
  void bar();
};

template <typename T>
void Foo::bar() {}

There might have been some extra minutiae, but the gist was that a MSVC failed the latter, even without any include in the picture. Might have been a decade ago.
Topic archived. No new replies allowed.