设定
啊
void foo(void);
抄送
#include "a.h"
void foo(void) { /* do something */ }
它们都被编译到名为
libA
的共享库中身高
#include "a.h"
void bar(void);
template <typename T>
void baz(void)
{
foo();
}
抄送
#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
的foo()
函数并引发链接错误。谁会想到?如果我也将
main.cc
链接到libB
,则效果很好。但是我的问题是:如何有效使用模板,而不必链接到原始库和/或不必实例化打算使用的每个
bar<>()
版本?编辑-聊天澄清
目的是允许libB提供模板,而无需在libB中进行显式实例化,并且无需将客户端耦合到libB的实现细节。
最佳答案
模板定义是您的库(在本例中为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();
}