With normal functions, the declaration and definition are often separated across multiple files like so:
// Foo.h
namespace Foo
{
void Bar();
}
.
// Foo.cpp
#include "Foo.h"
void Foo::Bar()
{
cout << "Inside function." << endl;
}
It is my understanding that this cannot be done with templates. The declaration and definition must not be separate because the appropriate form of the template is created "on-demand" when needed.
So, how and where are templates typically defined in a multiple-file project like this? My intuition is that it would be in Foo.cpp because that's where the "meat" of functions normally is, but on the other hand it's the header file that's going to be included.
You need to write definitions of templated methods in a .hxx file and include it at the end of your header file (.hh) in which you declare it. The .cc/.cpp is used to define non-templated methods.
So you'll have one .hh, one .hxx (included at the end of the .hh), and one .cc; so that including your templated class header file will include its definition too.
Example:
// list.hh
#IFNDEF LIST_HH
# DEFINE LIST_HH
template <typename T>
class List
{
void fun1(T a);
void fun2();
}
# include "list.hxx"
#ENDIF
// list.hxx
#IFNDEF LIST_HXX
# DEFINE LIST_HXX
# include "list.hh"
template <typename T>
void List::fun1(T a)
{
// ...
}
#ENDIF
// list.cc
#include "list.hh"
void List::fun2()
{
// ...
}
// anywhere.cc
#include "list.hh"
// ...
EDIT
There are several strategies to compile templates. The most common strategy is the one described above to let every user of the class template instantiate the code.
But, because the *.hh file includes the *.hxx file, each time a simple declaration of a template is needed, the full implementation comes with it. And if the implementation requires other declarations such as std::string, you force all the client code to parse the string header.
To avoid instantiations several times (time and space consuming), you can introduce a fourth type of file, *.hcc: files that must be compiled once for each concrete template parameter.
See Also Compile-Time Dependencies
EDIT2
Writing the template definition directly in the header file is called inclusion model. Doing so increases the cost of including the header. Not only because we added the definition of the template but because we included headers (, , whatever) which represent thousands of lines. A real problem for significant programs to compile (we are talking about hours of compilation here).
The separation model
Source
And my last argument: keep clear the header file so that it only contains the class declaration and its documentation. Like that, any other programmer is able to fastly read your header file: what is the public interface of this class, what does the documentation says.
Template code stays in the .hh file. There's no reason to make them separate files, though it is good practice to put the definitions after all the declarations.
When the compiler generates template code, it flags it so that the linker knows that the instantiation of a template in one compilation unit (i.e. .o file) is the exact same code as one in another unit. It will keep one and discard the rest, rather than bailing out with a "multiply defined symbol" error.
This is true of modern compilers with good template support. In the case of GCC, since 2.8. (I know, I wrote a lot of code for gcc 2.7.2.2 before they smartened the linker up and you had to jump through hoops to make templates build right.)
I'm disappointed that no answers mentioned that the C++ standard permits you to separate the definition from the declaration. It goes like this:
// Foo.h
export template<class T> T f();
// Foo.cpp
#include "Foo.h"
export template<class T> T f()
{
// blah blah
}
Unfortunately, almost no compilers support export. Comeau is one that does.
However, export is removed from C++ in C++0x.
Related
I am reading caffe code and find it split C++ class Template code into hpp and cpp files. For example, Net.cpp includes the template class Net implementation code and Net.hpp includes the definition. But I remembered it is not possible to split a template class into hpp and cpp files, how does caffe make this work?
Thank you.
As you noted, template definitions cannot be split up as easily from the declarations without jumping through some hoops.
One common pattern is to split them up in different files for the human reader but essentially they are still defined all in one header. For example
Foo.h
#pragma once
template <typename T>
void Foo(); // declaration
#include "Foo.inl"
Foo.inl
template <typename T>
void Foo()
{
// actual definition
}
Notice that the last thing in the .h file is to actually include the full contents of the .inl file. As far as the compiler is concerned, all of the template definitions are contained in the header to solve the initial problem you mentioned. But to the human reader, the declarations and definitions are separated.
you can not "usually" separate the template definition and deceleration. when the compiler instantiate the template it need to know exactly the definition and the declaration of the members that are used in the context. so if you only include the header file the compiler doesn't know how to instantiate the template for the template parameter.
A solution other than the one that coryKramer mentioned is after the full definition (in the .cpp file) explicitly instantiate the template for the template parameters that you need, this way the template is already instantiated for the values that you would like to use (at this point we have the full declration and definition of template). However, note that if the template is need to be instantiated for other values you may encounter errors as compiler doesn't know how to do this process if the template is not fully defined in that file!
This is the method that is used in caffe via INSTANTIATE_CLASS(Net) macro at the end of .cpp file.
I am aware that definitions of C++ templated functions have to be placed in header files. However, for reasons of improved readability and structure of a (potentially) big library I am making, I separated the declarations from the implementations, into "mock" headers (which #include the implementation files, quite like this structure of files). Note that am I am aware that the implementation of templated functions must be included at compile time, and I am doing that.
In short, I have a "multiple definition" error when I add a non-templated function declaration into the implementation file. Long explanation with examples follows.
When the pair of "mock" header + implementation files only contain the declaration/implementation pair of the templated function, everything works fine. It also works fine when I add an implementation of a new templated function only in the implementation file.
Working example (I would #include "algo.h" in my main.cpp when I wanted to use this functionality):
"Mock" header file algo.h:
#ifndef ALGO_H
#define ALGO_H
namespace fl{
template <typename Compare>
void algo(.. non-templated args .., Compare order = std::less<int>());
}
#include "tpp/algo.cpp"
#endif // ALGO_H
Implementation file tpp/algo.cpp: (currently just algo.tpp)
Note: Using the tpp/.cpp file was in the initial version, now I am using a .tpp file per #πάντα ῥεῖ's suggestion, explanation in the end.
#ifndef TPP_ALGO
#define TPP_ALGO
#include "../algo.h"
namespace fl{
template <typename Compare>
void subFunctionality(Compare order, .. args ..){ /* impl */ }
template <typename Compare>
void algo(.. non-templated args .., Compare order){
subFunctionality(order, .. args ..);
// implementation
}
}
#endif // TPP_ALGO
The problem arises when I add a non-templated function implementation in the implementation file. (Non-working) example of the tpp/algo.cpp (currently just algo.tpp) (using the same algo.h):
#ifndef TPP_ALGO
#define TPP_ALGO
#include "../algo.h"
namespace fl{
template <typename Compare>
void subFunctionality(Compare order, .. args ..){ /* impl */ }
void moreSubFun(.. args ..) { /* impl */ }
template <typename Compare>
void algo( .. non-templated args ..., Compare order){
subFunctionality(order, .. args ..);
moreSubFun(.. args ..);
// more stuff
}
}
#endif // TPP_ALGO
I get the "multiple definition" error (from where I included it in main.cpp), like so:
obj/Release/main.o In function `fl::moreSubFun(...)':
main.cpp multiple definitions of `fl::moreSubFun(..)'
obj/Release/../tpp/algo.o:algo.cpp first defined here
Why does this happen only to non-templated functions, while it works fine for the templated, and more importantly, how do I solve this problem?
I looked all around SO, and I can't find anything useful :( Ideally, I am looking for something as close to my own file-structure as possible (but I'll take anything that works while still using some separation into "mock" .h + tpp/.cpp). Do I have to take out the additional sub-functionalities into a separate, non-templated pair of .h/.cpp files, or is there other solutions? (The sub-functionalities should ideally not be visible to the end-user).
I am reluctant to use inline when defining fl::moreSubFunc(..) as the function is pretty big (and I was taught inline should ideally only be used with small functions). This does solve the problem, but I'm looking to see if there is a different solution.
I am working in Code::Blocks, using gcc version 4.7.2. This is the initial reason my implementation file is tpp/.cpp (.cpp extension), since Code::Blocks does not support it by default. This is changed in the current implementation following #πάντα ῥεῖ's suggestion (look below).
Late edit (After I taught the solution was found) I taught #πάντα ῥεῖ's answer solves the problem. I tweaked Code::Blocks to accept .tpp files (either treating it as header or source files). Initially, this solution worked.
However, this solution worked only when the algo.h file was included in only one other file: when I included it only in main.cpp. However, as soon as I tried including it in another source file (e.g. algo2.cpp) that would use those algorithms (in addition to main.cpp), the multiple definition problem came back.
Bottom line, the problem still persists as soon as I include the algo.h in more than one file, and I am still looking for a solution.
Your problem occurs because function templates are treated differently at link time from "plain" free functions. Functions must obey the One Definition Rule (ODR); that is, they must be defined in no more than one translation unit. Otherwise, when you get to link time, you end up with multiple definition errors like the one you cited. This same rule also applies to classes, types, and objects in general.
This would seem to preclude the use of templates at all; they must be fully included in every translation unit in which they are used. However, the ODR makes an exception for a few cases. Quoting from Wikipedia:
Some things, like types, templates, and extern inline functions, can be defined in more than one translation unit. For a given entity, each definition must be the same. Non-extern objects and functions in different translation units are different entities, even if their names and types are the same.
This is why you don't run into multiple definition errors with the template functions. At link time, the linker finds the duplicate symbol definitions and removes all duplicates (as long as they are all equivalent; otherwise, this would be an error). Therefore, your program links successfully with exactly one definition of each required symbol.
For your case, your problem occurs because you are including non-template functions in more than one translation unit (everywhere that the .cpp file is included). There would be a few ways of fixing this:
If the template functions are part of a class, you could move the non-template functions to lie in that class as well. This would bring it under the symbol-deduplicating umbrella of the owning template class.
Mark the functions as inline.
Break the non-template functions out into another .cpp file that you then compile separately. That will be the only translation unit that houses them.
In general you should compile .cpp file separately and link it later. But if you want (or must) do it this way, mark all non-template functions as inline. This should help.
As a good rule of thumb:
"Never ever include a .cpp file."
You shouldn't give these template implementation files a .cpp extension. Your build system might include them automatically then.
The conventionally used extensions for such files are e.g. .tcc or .icc. Add these to your project, as you would add other header files.
Don't include them in the project as separately build and linked translation units, if they are used with an #include statement from another header file.
UPDATE:
As you were asking for Code Blocks specifically, you'll just need to tweak your file extension settings a bit, to get these files included in your project correctly, and have them syntax colored as usual:
1. Add the new file type to the file extension settings
2. Add the file type to the project file extension settings Project->Project Tree->Edit file types & categories
As soon a .tcc file is added to the project now, it will be opened using the text editor, and syntax colored as usual:
The corresponding .hpp file looks like this
Thinking Time - Why do you want to split your file anyway?
As the title suggests, the end problem I have is multiple definition linker errors. I have actually fixed the problem, but I haven't fixed the problem in the correct way. Before starting I want to discuss the reasons for splitting a class file into multiple files. I have tried to put all the possible scenarios here - if I missed any, please remind me and I can make changes. Hopefully the following are correct:
Reason 1 To save space:
You have a file containing the declaration of a class with all class members. You place #include guards around this file (or #pragma once) to ensure no conflicts arise if you #include the file in two different header files which are then included in a source file. You compile a separate source file with the implementation of any methods declared in this class, as it offloads many lines of code from your source file, which cleans things up a bit and introduces some order to your program.
Example: As you can see, the below example could be improved by splitting the implementation of the class methods into a different file. (A .cpp file)
// my_class.hpp
#pragma once
class my_class
{
public:
void my_function()
{
// LOTS OF CODE
// CONFUSING TO DEBUG
// LOTS OF CODE
// DISORGANIZED AND DISTRACTING
// LOTS OF CODE
// LOOKS HORRIBLE
// LOTS OF CODE
// VERY MESSY
// LOTS OF CODE
}
// MANY OTHER METHODS
// MEANS VERY LARGE FILE WITH LOTS OF LINES OF CODE
}
Reason 2 To prevent multiple definition linker errors:
Perhaps this is the main reason why you would split implementation from declaration. In the above example, you could move the method body to outside the class. This would make it look much cleaner and structured. However, according to this question, the above example has implicit inline specifiers. Moving the implementation from within the class to outside the class, as in the example below, will cause you linker errors, and so you would either inline everything, or move the function definitions to a .cpp file.
Example: _The example below will cause "multiple definition linker errors" if you do not move the function definition to a .cpp file or specify the function as inline.
// my_class.hpp
void my_class::my_function()
{
// ERROR! MULTIPLE DEFINITION OF my_class::my_function
// This error only occurs if you #include the file containing this code
// in two or more separate source (compiled, .cpp) files.
}
To fix the problem:
//my_class.cpp
void my_class::my_function()
{
// Now in a .cpp file, so no multiple definition error
}
Or:
// my_class.hpp
inline void my_class::my_function()
{
// Specified function as inline, so okay - note: back in header file!
// The very first example has an implicit `inline` specifier
}
Reason 3 You want to save space, again, but this time you are working with a template class:
If we are working with template classes, then we cannot move the implementation to a source file (.cpp file). That's not currently allowed by (I assume) either the standard or by current compilers. Unlike the first example of Reason 2, above, we are allowed to place the implementation in the header file. According to this question the reason is that template class methods also have implied inline specifiers. Is that correct? (It seems to make sense.) But nobody seemed to know on the question I have just referenced!
So, are the two examples below identical?
// some_header_file.hpp
#pragma once
// template class declaration goes here
class some_class
{
// Some code
};
// Example 1: NO INLINE SPECIFIER
template<typename T>
void some_class::class_method()
{
// Some code
}
// Example 2: INLINE specifier used
template<typename T>
inline void some_class::class_method()
{
// Some code
}
If you have a template class header file, which is becoming huge due to all the functions you have, then I believe you are allowed to move the function definitions to another header file (usually a .tpp file?) and then #include file.tpp at the end of your header file containing the class declaration. You must NOT include this file anywhere else, however, hence the .tpp rather than .hpp.
I assume you could also do this with the inline methods of a regular class? Is that allowed also?
Question Time
So I have made some statements above, most of which relate to the structuring of source files. I think everything I said was correct, because I did some basic research and "found out some stuff", but this is a question and so I don't know for sure.
What this boils down to, is how you would organize code within files. I think I have figured out a structure which will always work.
Here is what I have come up with. (This is my class code file organization/structure standard, if you like. Don't know if it will be very useful yet, that's the point of asking.)
1: Declare the class (template or otherwise) in a .hpp file, including all methods, friend functions and data.
2: At the bottom of the .hpp file, #include a .tpp file containing the implementation of any inline methods. Create the .tpp file and ensure all methods are specified to be inline.
3: All other members (non-inline functions, friend functions and static data) should be defined in a .cpp file, which #includes the .hpp file at the top to prevent errors like "class ABC has not been declared". Since everything in this file will have external linkage, the program will link correctly.
Do standards like this exist in industry? Will the standard I came up with work in all cases?
Your three points sound about right. That's the standard way to do things (although I've not seen .tpp extension before, usually it's .inl), although personally I just put inline functions at the bottom of header files rather than in a separate file.
Here is how I arrange my files. I omit the forward declare file for simple classes.
myclass-fwd.h
#pragma once
namespace NS
{
class MyClass;
}
myclass.h
#pragma once
#include "headers-needed-by-header"
#include "myclass-fwd.h"
namespace NS
{
class MyClass
{
..
};
}
myclass.cpp
#include "headers-needed-by-source"
#include "myclass.h"
namespace
{
void LocalFunc();
}
NS::MyClass::...
Replace pragma with header guards according to preference..
The reason for this approach is to reduce header dependencies, which slow down compile times in large projects. If you didn't know, you can forward declare a class to use as a pointer or reference. The full declaration is only needed when you construct, create or use members of the class.
This means another class which uses the class (takes parameters by pointer/reference) only has to include the fwd header in its own header. The full header is then included in the second class's source file. This greatly reduces the amount of unneeded rubbish you get when pulling in a big header, which pulls in another big header, which pulls in another...
The next tip is the unnamed namespace (sometimes called anonymous namespace). This can only appear in a source file and it is like a hidden namespace only visible to that file. You can place local functions, classes etc here which are only used by the the source file. This prevents name clashes if you create something with the same name in two different files. (Two local function F for example, may give linker errors).
The main reason to separate interface from implementation is so that you don't have to recompile all of your code when something in the implementation changes; you only have to recompile the source files that changed.
As for "Declare the class (template or otherwise)", a template is not a class. A template is a pattern for creating classes. More important, though, you define a class or a template in a header. The class definition includes declarations of its member functions, and non-inine member functions are defined in one or more source files. Inline member functions and all template functions should be defined in the header, by whatever combination of direct definitions and #include directives you prefer.
Do standards like this exist in industry?
Yes. Then again, coding standards that are rather different from the ones you expressed can also be found in industry. You are talking about coding standards, after all, and coding standards range from good to bad to ugly.
Will the standard I came up with work in all cases?
Absolutely not. For example,
template <typename T> class Foo {
public:
void some_method (T& arg);
...
};
Here, the definition of class template Foo doesn't know a thing about that template parameter T. What if, for some class template, the definitions of the methods vary depending on the template parameters? Your rule #2 just doesn't work here.
Another example: What if the corresponding source file is huge, a thousand lines long or longer? At times it makes sense to provide the implementation in multiple source files. Some standards go to the extreme of dictating one function per file (personal opinion: Yech!).
At the other extreme of a thousand-plus line long source file is a class that has no source files. The entire implementation is in the header. There's a lot to be said for header-only implementations. If nothing else, it simplifies, sometimes significantly, the linking problem.
Instead of doing
#include "MyClass.cpp"
I would like to do
#include "MyClass.h"
I've read online that not doing so is considered bad practice.
Separate compilation in a nutshell
First, let's get some quick examples out there:
struct ClassDeclaration; // 'class' / 'struct' mean almost the same thing here
struct ClassDefinition {}; // the only difference is default accessibility
// of bases and members
void function_declaration();
void function_definition() {}
extern int global_object_declaration;
int global_object_definition;
template<class T> // cannot replace this 'class' with 'struct'
struct ClassTemplateDeclaration;
template<class T>
struct ClassTemplateDefinition {};
template<class T>
void function_template_declaration();
template<class T>
void function_template_definition() {}
Translation Unit
A translation unit (TU) is a single source file (should be a **.cpp* file) and all the files it includes, and they include, etc. In other words: the result of preprocessing a single file.
Headers
Include guards are a hack to work around lack of a real module system, making headers into a kind of limited module; to this end, including the same header more than once must not have an adverse affect.
Include guards work by making subsequent #includes no-ops, with the definitions available from the first include. Because of their limited nature, macros which control header options should be consistent throughout a project (oddball headers like <assert.h> cause problems) and all #includes of public headers should be outside of any namespace, class, etc., usually at the top of any file.
See my include guard naming advice, including a short program to generate include guards.
Declarations
Classes, functions, objects, and templates may be declared almost anywhere, may be declared any number of times, and must be declared before referring to them in any way. In a few weird cases, you can declare classes as you use them; won't cover that here.
Definitions
Classes may be defined at most once[1] per TU; this typically happens when you include a header for a particular class. Functions and objects must be defined once in exactly one TU; this typically happens when you implement them in a **.cpp* file. However, inline functions, including implicitly inline functions inside class definitions, may be defined in multiple TUs, but the definitions must be identical.
For practical purposes[2], templates (both class templates and function templates) are defined only in headers, and if you want to use a separate file, then use another header[3].
[1] Because of the at-most-once restriction, headers use include guards to prevent multiple inclusion and thus multiple definition errors.
[2] I won't cover the other possibilities here.
[3] Name it blahblah_detail.hpp, blahblah_private.hpp, or similar if you want to document that it's non-public.
Guidelines
So, while I'm sure everything above is all a big ball of mud so far, it's less than a page on what should take up a few chapters, so use it as a brief reference. Understanding the concepts above, however, is important. Using those, here's a short list of guidelines (but not absolute rules):
Always name headers consistently in a single project, such as **.h* for C and **.hpp* for C++.
Never include a file which is not a header.
Always name implementation files (which are going to be directly compiled) consistently, such as **.c* and **.cpp*.
Use a build system which can compile your source files automatically. make is the canonical example, but there are many alternatives. Keep it simple in simple cases. For example, make can be used its built-in rules and even without a makefile.
Use a build system which can generate header dependencies. Some compilers can generate this with command-line switches, such as -M, so you can make a surprisingly useful system easily.
Build Process
(Here's the tiny bit that answers your question, but you need most of the above in order to get here.)
When you build, the build system will then go through several steps, of which the important ones for this discussion are:
compile each implementation file as a TU, producing an object file (**.o*, **.obj*)
each is compiled independently of the others, which is why each TU needs declarations and definitions
link those files, along with libraries specified, into a single executable
I recommend you learn the rudiments of make, as it is popular, well-understood, and easy to get started with. However, it's an old system with several problems, and you'll want to switch to something else at some point.
Choosing a build system is almost a religious experience, like choosing an editor, except you'll have to work with more people (everyone working on the same project) and will likely be much more constrained by precedent and convention. You can use an IDE which handles the same details for you, but this has no real benefit from using a comprehensive build system instead, and you really should still know what it's doing under the hood.
File Templates
example.hpp
#ifndef EXAMPLE_INCLUDE_GUARD_60497EBE580B4F5292059C8705848F75
#define EXAMPLE_INCLUDE_GUARD_60497EBE580B4F5292059C8705848F75
// all project-specific macros for this project are prefixed "EXAMPLE_"
#include <ostream> // required headers/"modules"/libraries from the
#include <string> // stdlib, this project, and elsewhere
#include <vector>
namespace example { // main namespace for this project
template<class T>
struct TemplateExample { // for practical purposes, just put entire
void f() {} // definition of class and all methods in header
T data;
};
struct FooBar {
FooBar(); // declared
int size() const { return v.size(); } // defined (& implicitly inline)
private:
std::vector<TemplateExample<int> > v;
};
int main(std::vector<std::string> args); // declared
} // example::
#endif
example.cpp
#include "example.hpp" // include the headers "specific to" this implementation
// file first, helps make sure the header includes anything it needs (is
// independent)
#include <algorithm> // anything additional not included by the header
#include <iostream>
namespace example {
FooBar::FooBar() : v(42) {} // define ctor
int main(std::vector<std::string> args) { // define function
using namespace std; // use inside function scope, if desired, is always okay
// but using outside function scope can be problematic
cout << "doing real work now...\n"; // no std:: needed here
return 42;
}
} // example::
main.cpp
#include <iostream>
#include "example.hpp"
int main(int argc, char const** argv) try {
// do any global initialization before real main
return example::main(std::vector<std::string>(argv, argv + argc));
}
catch (std::exception& e) {
std::cerr << "[uncaught exception: " << e.what() << "]\n";
return 1; // or EXIT_FAILURE, etc.
}
catch (...) {
std::cerr << "[unknown uncaught exception]\n";
return 1; // or EXIT_FAILURE, etc.
}
This is called separate compilation model. You include class declarations into each module where they are needed, but define them only once.
In addition to hiding implementation details in cpp files (check other replies), you can additionally hide structure details by class forward declaration.
class FooPrivate;
class Foo
{
public:
// public stuff goes here
private:
FooPrivate *foo_private;
};
The expression class FooPrivate says that FooPrivate is completely defined somewhere else (preferably in the same file where Foo's implementation resides, before Foo's stuff comes. This way you make sure that implementation details of Foo(Private) aren't exposed via the header file.
You needn't include .c or .cpp files - the compiler will compile them regardless whether they're #included in other files or not. However, the code in the .c/.cpp files is useless if the other files are unaware of the classes/methods/functions/global vars/whatever that's contained in them. And that's where headers come into play. In the headers, you only put declarations, such as this one:
//myfile.hpp
class MyClass {
public:
MyClass (void);
void myMethod (void);
static int myStaticVar;
private:
int myPrivateVar;
};
Now, all .c/.cpp files that will #include "myfile.hpp" will be able to create instances of MyClass, operate on myStaticVar and call MyClass::myMethod(), even though there's no actual implementation here! See?
The implementation (the actual code) goes into myfile.cpp, where you tell the compiler what all your stuff does:
//myfile.cpp
int MyClass::myStaticVar = 0;
MyClass::MyClass (void) {
myPrivateVar = 0;
}
void MyClass::myMethod (void) {
myPrivateVar++;
}
You never include this file anywhere, it's absolutely not necessary.
A tip: create a main.hpp (or main.h, if you prefer - makes no difference) file and put all the #includes there. Each .c/.cpp file will then only need to have have this line: #include "main.hpp". This is enough to have access to all classes, methods etc. you declared in your entire project :).
You should not include a source file (.c or .cpp). Instead you should include the corresponding header file(.h) containing the declarations. The source files needs to be compiled separately and linked together to get the final executable.
Cpp files should be defined in your compiler script to be compiled as object files.
What ide are you using?
I am going to assume you are compiling with gcc, so here is the command to compile two .cpp files into one executable
gcc -o myclasses.out myclass.cpp myotherclass.cpp
You should only use #include to include class definitions, not the implentation
One thing you will want to watch out for when including you class declarations from a .h/.hpp is make sure it only ever gets included once. If you don't do this you will get some possibly cryptic compiler errors that will drive you up the wall.
To do this you need to tell the compiler, using a #define, to include the file only if the #define does not already exist.
For example (MyClass.h):
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass
{
// Memebers and methods
}
#endif
// End of file
This will guarantee your class declaration only gets included once even if you have it included in many different .cpp files.
I have a problem I don't really understand. I have a class Node.
template<class T>
class node {
protected:
T _data;
public:
node(T data);
};
This is in "node.h" file. In "node.cpp" file, there is this constructor:
#include "node.h"
template<class T>
node<T>::node (T data) {
_data = data;
}
While the compiler finds no error, the linker (ld) tells me:
/usr/bin/ld: Undefined symbols:
node<int>::node(int)
the weird part... if I move the constructor from .cpp to .h file, everything works fine. Where is the problem?
The problem is that templates aren't classes - you don't normally write them in two separate files. Template classes are code that the compiler uses to generate classes. As such, your implementation code needs to effectively be inline, i.e., in the header as you discovered.
For a fuller explanation of why it has to be this way, see the C++ FAQ Lite.
As a general rule, you must put all template members inside of the header file. Templates are compiled in an as-used basis, and hence the entire definition needs to be available wherever they are used. Putting the code in the header file will solve that problem.
The only time you can put a template definition in a CPP file is when the template will only be used within that CPP file. The reason being is that it meets the standard that the entire definition is available for compilation.
Moving the contents of node.cpp to node.h will fix the problem.
Strange Scenarios
Then again, you can also put everything in a CPP file and include the CPP file. C++ is flexible in this way. I only mention this because I've seen in done before. I actually bruised my jaw when it hit the top of my desk.
When you use node<int>, you have not most likely included node.cpp. Therefore the compiler cannot instantiate the node<int>::node<int> constructor. Usually you put all the template code, including all the implementations of the methods, in the header file, or something included from it.
The commonly accepted practice is to put all of the implementation in the .h file, so that the classes can be generated from the template as needed.
If you know ahead of time which types your template will be instantiated with, you might be able to cheat a little. Just make sure your .cpp includes a use case for each type and method you will need. It is important that the use case come after the template code. E.g. for "node.cpp", use
#include "node.h"
template<class T>
node<T>::node (T data) {
_data = data;
}
void dummy(void)
{
node<int> intnode(0);
node<double> doublenode(0.0);
}
// You can put templates declaration in header and definition in source
// node.h or wherever you include file gets included
extern template class node<int>;
// node.cpp or where ever source file you want to use it
// But use it only once for each type of generated class
template class node<int>;
Unless there's a call to the function, the compiler won't output any code and the linker won't find it.
You should put the function in the header where it belongs.
implicit instantiation is turned off, you need
template class node<int>;
somewhere in your code (node.cpp maybe)
EDIT: bad answer, it's probably not the case.