C++ 使用#ifdef进行代码选择会创建难看的结构-替代方案?

C++ 使用#ifdef进行代码选择会创建难看的结构-替代方案?,c++,optimization,preprocessor,C++,Optimization,Preprocessor,目前,我的代码大致如下 #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_s

目前,我的代码大致如下

#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链接其他库/头。如果这些头/库是链接的,调用包含的函数是有意义的,否则编译将失败。这允许我在有或没有附加库的情况下运行程序(例如,如果我只想测试
func_C()
,而不需要
func_B()
func_A()
,或者如果库A和B在系统上不可用)。

尽管如此,这使得代码相当难看,有相当多的ifdef。因此,有没有一种方法可以获得相同的功能(最好是由cmake脚本控制),但不必使用所有这些
#ifdef

根据库a和B的大小,您可以编写存根库,使用不做任何事情或返回硬编码值或任何有意义的函数。然后,您可以链接到真实库或存根库进行测试
func\u 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
,如果不使用库,只需链接存根文件。

您可以创建称为存根库/实现的内容,然后决定是链接到该库还是链接到具有真正实现的库

文件
a_stub.c

#include "include_a.h"

void func_A() {} // Does nothing. Returns a placeholder value if necessary.
#include "include_a.h"

void func_A() { do_stuff_a(); }
文件
a_real.c

#include "include_a.h"

void func_A() {} // Does nothing. Returns a placeholder value if necessary.
#include "include_a.h"

void func_A() { do_stuff_a(); }
B和C也是一样。然后根据您的兴趣选择
*\u real.C
*\u stub.C
(即定义
A
B
C
宏的情况)


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

根据
A
B
所代表的内容,您可能可以使用CMake有条件地构建不同的源文件?如果
,您可以尝试使用
#if
<代码>#如果定义(A)和定义(B)
可以测试
A
B
是否都定义了<代码>#如果定义(A)&&!已定义(B)可以测试是否定义了
A
,而未定义
B
。也可以考虑使用<代码>αeLIF < /COD>(例如:代码>αILIF定义(b)& &定义(a)< /COD>)。这些东西允许在一行中测试多个条件,而不是跨多行测试,如果只使用
#ifdef
#else
则可能会发生这种情况,但我仍然必须从主程序中删除相当多的代码(如
func_B()
func_a()所示)
,因此省略库的链接不会有多大帮助…@arc\u lube No。您将编写一个库,其中包含函数
do\u stuff\u a()
do\u stuff()
,但实际上什么都不做(空函数)。然后您可以链接到真实的库或存根库。如果您只对检查功能C感兴趣,那么如果我愿意,A和B什么都不做并不重要,但对于类函数(即func_A()、func_B()和func_C()现在是类的成员),在这种情况下,我将如何解决它?@arc\u luse这将是完全相同的事情。无论库A的API是什么(即
中的任何内容都包括A.h
),您将为存根库实现相同的API。这意味着:1.将类声明放入库的头中。2.将类函数放入库的cpp文件中,其中一个文件带有存根,另一个文件带有实函数。3.为存根和函数创建不同的cmake路径。4.成功?