在库中使用模板

时间:2016-03-15 16:54:15

标签: c++ templates linker shared-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,并与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的实现细节。

1 个答案:

答案 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();
}