My project resembles this set up, when I need to use my_template_library.h
in main_class.h
.
main.cpp
#include "main_class.h"
int main()
{
MainClass m;
return m.exec();
}
main_class.h
#ifndef MAIN_CLASS_H
#define MAIN_CLASS_H
#include "my_template_library.h"
class MainClass {
public:
MainClass();
int exec();
};
#endif // MAIN_CLASS_H
main_class.cpp
#include <iostream>
#include "main_class.h"
MainClass::MainClass(){}
int MainClass::exec()
{
std::cout << "exec!" << std::endl;
return 0;
}
my_template_library.h
#ifndef MY_TEMPLATE_LIBRARY_H
#define MY_TEMPLATE_LIBRARY_H
#include <iostream>
//#pragma message ("I'm being included past the include guards!")
class MyTemplateLibrary
{
public:
MyTemplateLibrary();
void function();
};
MyTemplateLibrary::MyTemplateLibrary(){}
void MyTemplateLibrary::function()
{
std::cout << "function called!" << std::endl;
}
#endif // MY_TEMPLATE_LIBRARY_H
In the template header-only library I write I first declare everything in a class and then define everything outside the class, like what you would usually do when you separate your class into .h
and .cpp
code, but with .cpp
file added at the end of .h
, inside include guards. This worked fine as long as my template library was included only once, but when it started to be included more than that I got some very confusing issues.
$ g++ -o test main.cpp main_class.h main_class.cpp my_template_library.h
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/ccZikorv.o:main.cpp:(.text+0x0): first defined here
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/ccZikorv.o:main.cpp:(.text+0x0): first defined here
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::function()':
main_class.cpp:(.text+0xa): multiple definition of `MyTemplateLibrary::function()'
/tmp/ccZikorv.o:main.cpp:(.text+0xa): first defined here
collect2: error: ld returned 1 exit status
I'm confused as to what is going on. I have added the #pragma message
to my_template_library.h to make some sense out of this, which you see here commented out in the code. When I uncomment it and run the code I get
$ g++ -o test main.cpp main_class.h main_class.cpp my_template_library.h
In file included from main_class.h:4:0,
from main.cpp:1:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
#pragma message ("I'm being included past the include guards!")
^
In file included from main_class.h:4:0:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
#pragma message ("I'm being included past the include guards!")
^
In file included from main_class.h:4:0,
from main_class.cpp:3:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
#pragma message ("I'm being included past the include guards!")
^
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
#pragma message ("I'm being included past the include guards!")
^
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/cc4XSnui.o:main.cpp:(.text+0x0): first defined here
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/cc4XSnui.o:main.cpp:(.text+0x0): first defined here
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::function()':
main_class.cpp:(.text+0xa): multiple definition of `MyTemplateLibrary::function()'
/tmp/cc4XSnui.o:main.cpp:(.text+0xa): first defined here
collect2: error: ld returned 1 exit status
So the header file is being included through:
So, my questions are:
Why include guards don't help?
Include guards prevent redundant code within the same compilation unit.
You are getting a linker error about different compilation units claiming to hold the same function definition.
How to prevent this from happening?
You need to make those non-template member functions inline
to avoid violating the One Definition Rule.
One way is to explicitly declare them inline.
inline MyTemplateLibrary::MyTemplateLibrary(){}
Alternately, functions defined within the class definition are implicitly inline.
class MyTemplateLibrary
{
public:
MyTemplateLibrary() {}
void function()
{
std::cout << "function called!" << std::endl;
}
};