C 预处理器计算特定产品包括

C Preprocessor to compute product specific include

我必须维护同时具有通用组件和产品特定组件的 C 代码。我想简化我的代码,以便我只有一个通用的 product.h 文件,其结构类似于

#if (PRODUCT_ID == 1)
    #define PRODUCT_NAME Product1
#else
    #if (PRODUCT_ID == 2)
        #define PRODUCT_NAME Product2
    #else
        #error "Unsupported product id"
    #endif
#endif

然后,每当我有一个 header foo.h 具有特定于产品的组件时,我想使用这样的语法

#include "product.h"
#include PRODUCT_SPECIFIC_INCLUDE

其中 PRODUCT_SPECIFIC_INCLUDE 应该从 __FILE__PRODUCT_NAME 宏以这样一种方式派生,它会转换为

#include "Product1/foo.h"

也就是说,特定于产品的 header 文件与通用文件具有相同的文件名,但位于特定于产品的文件夹中,其名称是 PRODUCT_NAME 宏的值。

似乎无论我尝试什么都存在预处理器字符串化问题。我不可能是第一个想要这种结构的人。我错过了什么?

更新

这是我目前为 PRODUCT_SPECIFIC_INCLUDE 准备的,但没有用

#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define PRODUCT_SPECIFIC_INCLUDE TOKENPASTE2(PRODUCT_SPECIFIC, __FILE__)

第一个代码可以简化为:

#if (PRODUCT_ID == 1)
    #define PRODUCT_NAME Product1
#elif (PRODUCT_ID == 2)
    #define PRODUCT_NAME Product2
#else
    #error "Unsupported product id"
#endif

其次,您正在尝试获取所需的包含 header 名称,但问题出在这两行中:

#define TOKENPASTE(x, y) x ## y
#define PRODUCT_SPECIFIC_INCLUDE TOKENPASTE2(PRODUCT_SPECIFIC, __FILE__)

__FILE__ : This macro expands to the name of the current input file, in the form of a C string constant

TOKENPASTE(PRODUCT_SPECIFIC, __FILE__) |--> product ## "foo.h"

product" 永远无法给出有效的令牌。这就是 CPP 给你错误的原因。您需要的是将 文件名写成纯文本 以便您可以将它与其他宏组合。

你可以这样做:

#define TOKENPASTE(x) #x
#define TOKENPASTE2(x) TOKENPASTE(x)
#define PRODUCT_SPECIFIC_INCLUDE TOKENPASTE2(PRODUCT_SPECIFIC/foo.h)
#include PRODUCT_SPECIFIC_INCLUDE

你可以这样做

#define STR2(F) #F
#define STR(F) STR2(F)
#define MAKE_PRODUCT_INCLUDE(FILE) STR(PRODUCT_SPECIFIC/FILE)

#include MAKE_PRODUCT_INCLUDE(foo.h)

但我不知道如何避免重复文件名。使用 __FILE__ 给出一个字符串,我不知道如何在预处理器中连接字符串(连接并列字符串的事实是一个解析器功能,## 不能用于 "foo""bar" 不是有效标记的拼写)。