Reputation: 5648
a.h
void foo(void);
a.cc
#include "a.h"
void foo(void) { /* do something */ }
These both are compiled to a shared library called libA
b.h
#include "a.h"
void bar(void);
template <typename T>
void baz(void)
{
foo();
}
b.cc
#include "b.h"
void bar(void)
{
foo();
}
These two get compiled to the shared library libB
, and are linked against libA
.
Now I write my main program, which is linked against libB
, but not libA
.
main.cc
#include "b.h"
int main(void)
{
bar(); // Okay, compiles
baz<int>(); // Undefined symbol *foo()*, referenced from void bar<int>() in main-(...)
}
I kinda get, why this throws up an error. In libB
I have a template declaration, which can be used to instantiate functions, although it doesn't instantiate any in libB
itself.
In main.cc
however it instantiates the function void bar<int>(void)
, which is then placed in the object code for main.cc
, where it can't find libA
s foo()
function and throws the linking error.
And who would have thought? If I link main.cc
against libB
as well, it works just fine.
My question is however: How can I work with templates efficiently, without without having to link against the original library and/or having to instantiate every single version of bar<>()
, that I intend to use?
The goal is to allow libB to provide templates, without requiring explicit instantiation in libB, and without the client being coupled to libB's implementation details.
Upvotes: 0
Views: 116
Reputation: 67713
Template definitions are part of the public interface of your library (libB, in this case).
The only way to decouple a client of libB from its implementation details (in this case: the dependency on libA), is the usual: don't make them public. Hide them inside libB. If they're visible in b.h, they're part of the public interface.
The simple solution in this case is to provide a (non-template, non-inline) function in libB which abstracts the dependency on libA:
// b.h
void do_fooish_things();
template <typename T>
void baz(void)
{
do_fooish_things();
}
// b.cc
#include <libA/a.h>
void do_fooish_things() {
// hidden implementation detail
libA::foo();
}
Upvotes: 1