设定



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的目标代码中,在该代码中找不到libAfoo()函数并引发链接错误。

谁会想到?如果我也将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();
}

10-06 00:53