使用#ifdefs 进行代码选择会创建丑陋的结构 - 替代方案?

Using #ifdefs for code selection creates ugly constructs - alternatives?

目前我的代码看起来大致像

#ifdef A
#include "include_a.h"
#endif

#ifdef B
#include "include_b.h"
#endif

void func_A()
{
#ifdef A
    do_stuff_a();
#endif
}

void func_B()
{
#ifdef B
    do_stuff_b();
#else
    do_other_stuff();
#endif
}

void func_C()
{
    do_stuff_c();
}
int main(void)
{
#ifdef A
#ifdef B
    do_AB_stuff();
#else
    do_A_stuff();
#endif
func_A();
func_B();
func_C();
return 0;
}

原因是:我正在使用 cmake 链接额外的 libraries/headers。如果那些 headers/libraries 是链接的,那么调用包含的函数是有意义的,如果不是,编译将失败。这使我可以 运行 使用和不使用附加库的程序(例如,如果我只想测试 func_C(),而没有 func_B()func_A() 的计算过载,或者如果库 A 和 B 在系统上不可用)。
尽管如此,这仍然是相当丑陋的代码,周围有很多 #ifdefs 。因此,有没有办法获得相同的功能(最好由 cmake 脚本控制),但不必使用所有这些 #ifdefs?

根据库 A 和 B 的大小,您可以编写存根库,其中包含不执行任何操作的函数或 return 硬编码值或任何有意义的内容。然后你可以 link 使用真实库或存根库进行测试 func_C()

举个例子,如果真库的API就是

include_a.h:

void do_stuff_a();
void do_A_stuff();

您的存根可能是:

stub_a.cpp:

void do_stuff_a() {}
void do_A_stuff() {}

如果不使用该库,那么您可以删除所有 #ifdef A,只使用存根文件 link。

您可以创建所谓的存根 library/implementation,然后决定是 link 到该库还是具有实际实现的库。

文件a_stub.c:

#include "include_a.h"

void func_A() {} // Does nothing. Returns a placeholder value if necessary.

文件a_real.c:

#include "include_a.h"

void func_A() { do_stuff_a(); }

B 和 C 相同。然后根据您的兴趣选择 *_real.c*_stub.c(即您定义 ABC 宏)。

编辑:这可能是@Baruch 在另一个答案中评论的内容。我在发布答案后看到了他的评论。