I'd like to provide a library that provides template code. But I would also like to keep the most possible the ownership of this code (generated code) when I can guess the usage of different usual types of my template. Here is an example of what I am trying to do:
lib1.h
#include <iostream>
template<int N>
void print_me() {
std::cout << "I am function number " << N << std::endl;
}
lib1.cpp
#include "lib1.h"
/* Force symbols to be defined here. */
template void print_me<0>();
template void print_me<1>();
I compile my library using:
g++ -shared -fPIC lib1.cpp -o lib1.so
And when I use my library:
main.cpp
#include <lib1.h>
int main() {
print_me<0>();
print_me<1>();
print_me<2>();
}
Compiled with:
g++ main.cpp -l1
Here I would expect that the symbol print_me<0>() and print_me<1>() are defined and used from lib1.so and print_me<2>() defined and used for my executable (checked with nm --defined-only). But it seems that this is not the case! The symbols for 0 and 1 are well defined in lib1.so but as weak symbols. And are redefined in my executable (0, 1 and 2) again, weak. That implies that the code for 0 and 1 for my executable is taken from main.cpp which is not what I want (I checked with specification in main.cpp).
Is there a way (in the lib1.h for instance) to say at compile time of main.cpp that the symbols are already defined somewhere and that it does not need to add these symbols?
C++11 solution: use extern templates. Simply add these strings to your main.cpp
file:
extern template void print_me<0>();
extern template void print_me<1>();
Thus you tell compiler not to instantiate print_me
function template in main.cpp
(for template arguments 0 and 1). So linker should search definition of void print_me<0>();
and void print_me<1>();
in other translation units.
I would separate the implementation and the interface, using template specialization:
lib1.h:
#include <iostream>
template <int T> void print_me(void);
template <> void print_me<0>(void);
template <> void print_me<1>(void);
lib1_internal.h (NOTE: this does not need to be disclosed):
#include <iostream>
template<int N>
void print_me_internal() {
std::cout << "I am function number " << N << std::endl;
}
lib1.cpp:
#include "lib1.h"
#include "lib1_internal.h"
template <> void print_me<0>() {
print_me_internal<0>();
}
template <> void print_me<1>() {
print_me_internal<1>();
}
your main.cpp will correctly lead to a linker error:
$ g++ main.cpp -L. -l1
/tmp/ccZSDqkp.o: In function `main':
main.cpp:(.text+0xf): undefined reference to `void print_me<2>()'
collect2: ld returned 1 exit status
Just add the definition of template <int T> void print_me(void)
in lib1.h
in place of its declaration and it will be used whenever not found in the specialized versions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With