A.H
void foo(void);
a.cc
#include "a.h"
void foo(void) { /* do something */ }
这两者都被编译为名为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();
}
这两个编译到共享库libB
,并与libA
链接。
现在我编写了我的主程序,该程序与libB
相关联,但不是 libA
。
main.cc
#include "b.h"
int main(void)
{
bar(); // Okay, compiles
baz<int>(); // Undefined symbol *foo()*, referenced from void bar<int>() in main-(...)
}
我有点,为什么这会引发错误。在libB
中,我有一个模板声明,可用于实例化函数,尽管它不会在libB
本身实例化任何函数。
然而,在main.cc
中,它会实例化void bar<int>(void)
函数,然后将其放在main.cc
的对象代码中,在其中找不到libA
s { {1}}函数并抛出链接错误。
谁会想到?如果我将foo()
与main.cc
联系起来,那就可以了。
我的问题是:我如何有效地使用模板,而无需链接原始库和/或必须实例化libB
的每个版本,我打算用?
目标是允许libB提供模板,而不需要在libB中进行显式实例化,也不需要将客户端耦合到libB的实现细节。
答案 0 :(得分:1)
模板定义是库的 public 接口的一部分(在本例中为libB)。
将libB的客户端与其实现细节(在这种情况下:依赖于libA)分离的唯一方法是通常的:不要将它们公开。将它们隐藏在libB中。如果它们在b.h中可见,则它们是公共接口的一部分。
在这种情况下,简单的解决方案是在libB中提供(非模板,非内联)函数,该函数抽象了对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();
}