But when I build, the compiler throws errors in every instance of the template class:

undefined reference to `cola(float)::cola()'... (it's actually cola'<'float'>'::cola(), but this doesn't let me use it like that.)

And so on. Altogether, 17 warnings, counting the ones for the member functions being called in the program.

Why is this? Those functions and constructors WERE defined. I thought that the compiler could replace the "T" in the template with "float", "string" or whatever; that was the advantage of using templates.

I read somewhere here that I should put the declaration of each function in the header file for some reason. Is that right? And if so, why?

marked as duplicate by Praetorian c++Users with the c++ badge can single-handedly close c++ questions as duplicates and reopen them as needed.May 9 '15 at 1:15

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

1

You are missing an #endif at the end of nodo_colaypila.h
– Aaron McDaidJan 6 '12 at 3:11

1

and maybe nodo_colaypila<T>* ult, pri; should be nodo_colaypila<T> *ult, *pri;. Both should be pointers, right?
– Aaron McDaidJan 6 '12 at 3:24

1

And there's a third minor typo: If the parameter to a function has a default value, then this should be defined in the header file, not in the implementation. (More precisely, the (first) declaration should have the default.)
– Aaron McDaidJan 6 '12 at 3:55

@LightnessRacesinOrbit, answered often yes. Not always fully correctly though :-) There are ways to keep the implementation of a template's member functions in one translation unit, while allowing other translation units to link to them. See my answer.
– Aaron McDaidJan 6 '12 at 3:57

19

@LightnessRacesinOrbit: Answered a million times, perhaps! but you didn't even provide a single link and marked this as duplicate...
– Alok SaveJan 6 '12 at 17:03

3 Answers
3

This is a common question in C++ programming. There are two valid answers to this. There are advantages and disadvantages to both answers and your choice will depend on context. The common answer is to put all the implementation in the header file, but there's another approach will will be suitable in some cases. The choice is yours.

The code in a template is merely a 'pattern' known to the compiler. The compiler won't compile the constructors cola<float>::cola(...) and cola<string>::cola(...) until it is forced to do so. And we must ensure that this compilation happens for the constructors at least once in the entire compilation process, or we will get the 'undefined reference' error. (This applies to the other methods of cola<T> also.)

Understanding the problem

The problem is caused by the fact that main.cpp and cola.cpp will be compiled separately first. In main.cpp, the compiler will implicitly instantiate the template classes cola<float> and cola<string> because those particular instantiations are used in main.cpp. The bad news is that the implementations of those member functions are not in main.cpp, nor in any header file included in main.cpp, and therefore the compiler can't include complete versions of those functions in main.o. When compiling cola.cpp, the compiler won't compile those instantiations either, because there are no implicit or explicit instantiations of cola<float> or cola<string>. Remember, when compiling cola.cpp, the compiler has no clue which instantiations will be needed; and we can't expect it to compile for every type in order to ensure this problem never happens! (cola<int>, cola<char>, cola<ostream>, cola< cola<int> > ... and so on ...)

The two answers are:

Tell the compiler, at the end of cola.cpp, which particular template classes will be required, forcing it to compile cola<float> and cola<string>.

Put the implementation of the member functions in a header file that will be included every time any other 'translation unit' (such as main.cpp) uses the template class.

Answer 1: Explicitly instantiate the template, and its member definitions

At the end of cola.cpp, you should add lines explicitly instantiating all the relevant templates, such as

This will ensure that, when the compiler is compiling cola.cpp that it will explicitly compile all the code for the cola<float> and cola<string> classes. Similarly, nodo_colaypila.cpp contains the implementations of the nodo_colaypila<...> classes.

In this approach, you should ensure that all the of the implementation is placed into one .cpp file (i.e. one translation unit) and that the explicit instantation is placed after the definition of all the functions (i.e. at the end of the file).

Answer 2: Copy the code into the relevant header file

The common answer is to move all the code from the implementation files cola.cpp and nodo_colaypila.cpp into cola.h and nodo_colaypila.h. In the long run, this is more flexible as it means you can use extra instantiations (e.g. cola<char>) without any more work. But it could mean the same functions are compiled many times, once in each translation unit. This is not a big problem, as the linker will correctly ignore the duplicate implementations. But it might slow down the compilation a little.

Summary

The default answer, used by the STL for example and in most of the code that any of us will write, is to put all the implementations in the header files. But in a more private project, you will have more knowledge and control of which particular template classes will be instantiated. In fact, this 'bug' might be seen as a feature, as it stops users of your code from accidentally using instantiations you have not tested for or planned for ("I know this works for cola<float> and cola<string>, if you want to use something else, tell me first and will can verify it works before enabling it.").

Finally, there are three other minor typos in the code in your question:

You are missing an #endif at the end of nodo_colaypila.h

in cola.h nodo_colaypila<T>* ult, pri; should be nodo_colaypila<T> *ult, *pri; - both are pointers.

nodo_colaypila.cpp: The default parameter should be in the header file nodo_colaypila.h, not in this implementation file.

To clear the confusion, this approach is not a hack, it is perfectly valid and explicit template instantation is supported & approved by the C++ standard.However, it is not the cleanest approach(my perspective): It needs you to know all types needed by the program and One needs to provide explicit instantiations for all types that you will ever use,in a big project this can be a considerable overhead while creating the possibility where you end up breaking the ODR.
– Alok SaveJan 6 '12 at 5:54

You will have to define the functions inside your header file.
You cannot separate definition of template functions in to the source file and declarations in to header file.

When a template is used in a way that triggers its intstantation, a compiler needs to see that particular templates definition. This is the reason templates are often defined in the header file in which they are declared.

Reference:C++03 standard, § 14.7.2.4:

The definition of a non-exported function template, a non-exported member function template, or a non-exported member function or static data member of a class template shall be present in every translation unit in which it is explicitly instantiated.

EDIT:
To clarify the discussion on the comments:
Technically, there are three ways to get around this linking problem:

To move the definition to the .h file

Add explicit instantiations in the .cpp file.

#include the .cpp file defining the template at the .cpp file using the template.

Each of them have their pros and cons,

Moving the defintions to header files may increase the code size(modern day compilers can avoid this) but will increase the compilation time for sure.

Using the explicit instantiation approach is moving back on to traditional macro like approach.Another disadvantage is that it is necessary to know which template types are needed by the program. For a simple program this is easy but for complicated program this becomes difficult to determine in advance.

While including cpp files is confusing at the same time shares the problems of both above approaches.

I find first method the easiest to follow and implement and hence advocte using it.

Not quite true. This issue has come up before, but I can't find the relevant line. If you know which templates will be instantiated, you can put them into a cpp file as usual. See my answer.
– Aaron McDaidJan 6 '12 at 3:05

@AaronMcDaid: Then find the relevant line/examples/samples, quote the same and enlighten us before downvoting.
– Alok SaveJan 6 '12 at 3:11

Ah. interesting. Is there a distinction between 'explicitly instantiated' and merely 'instantiated'. The explicit instantiation at the end of my answer satisfies this, in that the definition is present in cola.cpp. When the template is instantiated in main.cpp, perhaps that is a non-explicit instantiation, and maybe my answer stands up?
– Aaron McDaidJan 6 '12 at 3:16

PS: when I gave a similar answer on that other thread, nobody complained. I therefore became more confident it was correct. (Maybe I'm wrong, but curious about the word 'explicit')
– Aaron McDaidJan 6 '12 at 3:19

@Aaron McDaid Explicit instantiation is what you've done: You've explicitly told the compiler to generate source for those instances of the cola template. HOWEVER: C/C++ translation units colloquially correspond to cpp files, hence your definition of the cola templates will be absent until the linker kicks in and finds them in a different translation unit. This is why your solution works, it creates something for the linker to find.
– Liam MJan 6 '12 at 3:31

However this requires you to anticipate how your template will be used and, as a general solution, is counter-intuitive. It does solve the corner case though where you develop a template to be used by some internal mechanism, and you want to police the manner in which it is used.