预处理器:使用动态名称生成函数。多个定义问题

时间:2013-08-30 09:35:33

标签: c++ c c-preprocessor

我有一个预处理器宏,它根据宏参数生成函数和变量。

使用A,B随后调用宏,宏将生成类似

的内容
Inst* AActivate() { ... }
bool Atemp;

Inst* BActivate() { ... }
bool Btemp;

由于宏是在头文件中定义的,因此我收到链接器错误,通知我已定义的符号。 我正在使用#pragma一次,但我想问题在于在头文件中实现函数。

这是宏:

    #define REGISTER(ns, id, type) \
        Inst* type##Activate() { return new type(); }\
        bool type##temp = RegisterType(ns << 8 | id, &type##Activate);

现在我想知道如何处理这些问题。 我的第一个想法是使用了一些#define-Guards,但显然这需要嵌套的#defines,这在C ++中是不可能的。 我读到了一个可能的提升解决方案,但不幸的是,我无法使用这些库。

有什么想法吗?

提前谢谢你......

3 个答案:

答案 0 :(得分:3)

您的宏在标头中生成函数 definitions ,与任何普通函数一样,如果标头包含在多个转换单元中,则标头中的非内联函数会违反ODR。所以只需将生成的函数内联。

对于全局变量,ODR也适用,您必须将它们声明为static或const以获取内部链接。这反过来将为您提供变量的多个独立实例,每个转换单元一个包含标头。无论如何,全局变量被认为是不好的风格,所以也许你应该想到别的东西。

答案 1 :(得分:0)

使用.cpp文件中的宏或内联函数。使用#pragma一次并没有什么帮助,因为这只会阻止每个.cpp文件包含多个标头。编译多个.cpp文件时,会多次定义函数。

答案 2 :(得分:0)

你标记了C和C ++,你真的应该决定使用哪一个。

如果您的函数定义为inline,那么这样的事情只能在两种语言中起作用。然后,您必须有两个宏,一个用于内联定义,您将在每个头文件中调用该宏来查看该函数。

此外,您必须拥有第二个宏,该宏仅在一个.c或.cpp文件中调用,以便为您执行“实例化”。对于C或C ++,语法可能略有不同。

在C中,它应该类似于

    #define REGISTER(ns, id, type)                                          \
       inline Inst* type##Activate() { return new type(); }                 \
       extern bool type##temp

    #define INSTANTIATE(ns, id, type)                                       \
       Inst* type##Activate();                                              \
       bool type##temp = RegisterType(ns << 8 | id, &type##Activate)