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.
See Question&Answers more detail:os