X-Macros重新定义

时间:2010-02-02 21:08:22

标签: c++ c macros

当我在多个头文件使用的头文件中包含“xmacro.h”时,我得到链接错误:

  

错误LNK2005:“char const * * iD_Strings”(?iD_Strings @@ 3PAPBDA)   已在header_file.obj中定义

1.//"xmacro.h"
2.
3.// (1) Define code generating macro
4.
5.   #ifndef XMACRO_H
6.   #define XMACRO_H
7.
8.    #define GENERATE_IDS \
9.   X(_Name, "/Name") \
10.   X(_ID, "/ID")
11.
12.  // (2) Define X-Macro for generating enum members
13.
14.  #define X(id, idString) id, 
15.   enum IDs
16.  {
17.     ID_LOWERBOUND = -1,
18.    GENERATE_IDS
19.   NUM_IDS
20.  };
21.  #undef X
22.
23.  // (3) Define X-Macro for generating string names
24.
25.  #define X(id, idString) idString,
26.  const char* iD_Strings[] =
27.  {   
28.     GENERATE_IDS
29.     NULL
30.  };
31.  #undef X
32.
33.  #endif

当我定义X-Macro在第23行生成字符串名称时会产生错误。如何在不重新定义的情况下使用单个宏?

2 个答案:

答案 0 :(得分:3)

您的标头文件包含iD_Strings定义。当您从不同的源文件中包含它时,它会多次链接。即使定义相同,也会导致冲突。

您可以将iD_Strings声明为static(C方式)或将其包装在匿名命名空间(C ++方式)中以解决此问题。

答案 1 :(得分:1)

更好的方法来做X-Macros(我一直称之为列表宏)是将运算符作为参数传递给列表,然后你可以同时保留多个“运算符”:

#define GENERATE_IDS(_) \
_(Name) \
_(Id)

enum IDs
{
    ID_LOWERBOUND = -1,
    #define MK_ID_ENUM(n) _##n,
    GENERATE_IDS(MK_ID_ENUM)
    NUM_IDS
}

const char* iD_Strings[] =
{
    #define MK_ID_STRING(n) "/" #n,
    GENERATE_IDS(MK_ID_STRING)
    NULL
};

请注意,您仍然必须唯一地声明标识符,但是调用GENERATE_IDS()宏以声明对象确实属于.c / .c ++正文而不是标题。