在库中使用模板

Using templates in Libraries

设置

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,并且 link 针对 libA

现在我写我的主程序,它是link针对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 的目标代码中,在那里找不到 libAs foo() 函数并抛出 linking 错误。

谁会想到呢?如果我 link main.cc 也反对 libB,它工作得很好。

但是我的问题是:我如何才能有效地使用模板,而不必 link 针对原始库 and/or 必须实例化每个我打算使用 bar<>() 的单一版本?


编辑 - 来自聊天的澄清

目标是允许 libB 提供模板,而不需要在 libB 中显式实例化,并且客户端不需要耦合到 libB 的实现细节。

模板定义是库(在本例中为 libB)的 public 接口的一部分。

将 libB 的客户端与其实现细节(在本例中:对 libA 的依赖)分离的唯一方法是通常的方法:不要创建它们 public。将它们隐藏在 libB 中。如果它们在 b.h 中可见,它们就是 public 界面的一部分。

这种情况下的简单解决方案是在 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();
}