What is a good reference documenting patterns of use of X-Macros in C (or possibly C++)?

前端 未结 3 1020
时光取名叫无心
时光取名叫无心 2020-11-30 02:02

A basic definition and example and a few references for \"X-Macros\" is given in this wikipedia entry on the C pre-processor:

An X-Macro is a header

3条回答
  •  心在旅途
    2020-11-30 02:40

    I use X Macros() in code a lot. The value comes from only adding new data only to the "X list" and not modifying any other code.

    The most common use of X Macros() is for associating error text with error codes. When new error codes are added, programmers must remember to add the code and the text, typically in separate places. The X Macro allows the new error data to be added in a single place and get automatically populated anywhere it is needed.

    Unfortunately, the mechanisms use a lot of pre-compiler magic that can make the code somewhat hard to read (e.g. string joining with token1##token2, string creation with #token). Because of this I typically explain what the X Macro is doing in the comments.

    Here is an example using the error/return values. All new data gets added to the "X_ERROR" list. None of the other code hast to be modified.

    /* 
     * X Macro() data list
     * Format: Enum, Value, Text
     */
    #define X_ERROR \
      X(ERROR_NONE,   1, "Success") \
      X(ERROR_SYNTAX, 5, "Invalid syntax") \
      X(ERROR_RANGE,  8, "Out of range")
    
    /* 
     * Build an array of error return values
     *   e.g. {0,5,8}
     */
    static int ErrorVal[] =
    {
      #define X(Enum,Val,Text)     Val,
       X_ERROR
      #undef X
    };
    
    /* 
     * Build an array of error enum names
     *   e.g. {"ERROR_NONE","ERROR_SYNTAX","ERROR_RANGE"}
     */
    
    static char * ErrorEnum[] = {
      #define X(Enum,Val,Text)     #Enum,
       X_ERROR
      #undef X
    };
    
    /* 
     * Build an array of error strings
     *   e.g. {"Success","Invalid syntax","Out of range"}
     */
    static char * ErrorText[] = {
      #define X(Enum,Val,Text)     Text,
       X_ERROR
      #undef X
    };
    
    /* 
     * Create an enumerated list of error indexes
     *   e.g. 0,1,2
     */
    enum {
      #define X(Enum,Val,Text)     IDX_##Enum,
       X_ERROR
      #undef X
      IDX_MAX   /* Array size */
    };
    
    void showErrorInfo(void)
    {
        int i;
    
        /* 
         * Access the values
         */
        for (i=0; i

    You can also use X Macros() to generate code. For example to test if an error value is "known", the X Macro can generate cases in a switch statement:

     /*
      * Test validity of an error value
      *      case ERROR_SUCCESS:
      *      case ERROR_SYNTAX:
      *      case ERROR_RANGE:
      */
    
      switch(value)
      {
    
      #define X(Enum,Val,Text)     case Val:
       X_ERROR
      #undef X
             printf("Error %d is ok\n",value);
             break;
          default:
             printf("Invalid error: %d\n",value);
             break;
      }
    

提交回复
热议问题