3

I'm using the C preprocessor to generate elements in an enum. Is there a way to write doxygen comments for the generated elements? I can't just run it through the preprocessor before doxygen since that will strip the doxygen comments.

Example:

#define ATTRIBUTES \
X(TITLE,    "title") \
X(FILENAME, "filename") \
X(GENRE_ID, "genre_id")

enum ATTRIBUTES_ENUM {
  #define X(a, b) a##_ATTRIBUTE,
  ATTRIBUTES
  #undef X
  ATTRIBUTES_COUNT
};

And adding something like:

/**
 * \def TITLE_ATTRIBUTE
 * The media's title.
 */

doesn't work.

EDIT Thanks to Thomas Matthews, here's the solution I used:

#define ATTRIBUTES \
X(TITLE,    "title")    /*!< title attribute */ \
X(FILENAME, "filename") /*!< filename attribute */ \
X(GENRE_ID, "genre_id") /*!< genre id attribute */

#define X(a, b) a##_ATTRIBUTE,

enum ATTRIBUTES_ENUM {
  ATTRIBUTES
  ATTRIBUTES_COUNT
};

#undef X

And tell Doxygen to expand macros. The only downside is that the comment for the last element is also used as the comment for the ATTRIBUTES define. But that's a minor issue in my case.

1
  • It's possible you could abuse the ## operator to generate a // token - but you'd be in the realm of undefined behaviour. The problem is that comments are deleted in translation phase 3, before macros are expanded. Commented Oct 24, 2011 at 20:09

1 Answer 1

4

Try the following

  1. In the Doxygen configuration file, tell it to process the macros.
  2. In the macro definition, add the Doxygen comments after each member:

    #define ATTRIBUTES \  
    X(TITLE, "title") /**!< title element */ \  
    X(FILENAME, "filename") /**!< file name element */ \  
    X(GENRE_ID, "genre_id") /**!< title element */  
    

Due to code formmatting issues, the comments on each line should be C sytle comments.

My understanding is that Doxygen should process the macro (making the substitutions), then feed the modified text into it's comment engine.

Just a guess though.

I highly suggest a different schema for converting enums to text. Use either an array, vector or map. Such as:

enum Attributes_Enum
{
  TITLE, FILENAME, GENRE
};

struct Enum_Text_Entry
{
    enum Attributes_Enum value;
    const char * text;
};

Enum_Text_Entry  Enum_To_Text[] =
{
    {TITLE, "title"},
    {FILENAME, "filename"},
    {GENRE, "genre"},
};

const unsigned int NUMBER_OF_ENTRIES =
sizeof(Enum_To_Text) / sizeof(Enum_To_Text[0]);

Now just search the table for an enum and read the text out. The nice thing about putting the enum value and the text together in a structure is that this allows the enum values to change, but the rest of the code doesn't have to change.

Sign up to request clarification or add additional context in comments.

1 Comment

Nice, that worked! I had to play around with that a bit and move the #define out of the enum definition. In our case, I believe the thinking was that a linear search through the list of attributes would be undesirable because it ends up in a tight loop. It's a good point though - using the preprocessor like this is sort of messy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.