预处理器 #include 指令和宏扩展

Preprocessor #include directive and macro expansion

我有下面的代码。使用#define LIST 指令时,doxygen 会为 Child_* 类 生成文档。使用#include 指令时,Child_* 类 的文档将被忽略。

下面也公开了配置文件。

问题:我应该如何配置 doxygen 才能使 #include 指令正常工作?

//        test.cpp
#include <iostream>

#define LIST \
    TEST(CLASS_A, A) \
    TEST(CLASS_B, B) \
    TEST(CLASS_C, C) \
    TEST(CLASS_D, D) \
    TEST(CLASS_E, E)

class Mother
{

public:
    void print(void) { std::cout << "Hello\n";}
};

#define TEST(X,Y) class Child_##Y : public Mother {};
#include "List.txt" // using #include directive instead of #define LIST
//LIST
#undef TEST

int main(int argc, char * argv[])  
{
    #define TEST(X,Y) Child_##Y My_##X; My_##X.print();
    #include "List.txt" // using #include directive instead of #define LIST
    //LIST
    #undef TEST
} 

并且 "List.txt" 包含:

// List.txt
TEST(CLASS_A, A)
TEST(CLASS_B, B)
TEST(CLASS_C, C)
TEST(CLASS_D, D)
TEST(CLASS_E, E)

我的配置文件:

# Doxyfile 1.8.11

#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING      = UTF-8
PROJECT_NAME           = "Test Doxygen"
PROJECT_NUMBER         = 
PROJECT_BRIEF          = "testing x macro with doxygen"
PROJECT_LOGO           = 
OUTPUT_DIRECTORY       = doc
CREATE_SUBDIRS         = NO
ALLOW_UNICODE_NAMES    = NO
OUTPUT_LANGUAGE        = English
BRIEF_MEMBER_DESC      = YES
REPEAT_BRIEF           = YES
ABBREVIATE_BRIEF       = "The $name class" \
                         "The $name widget" \
                         "The $name file" \
                         is \
                         provides \
                         specifies \
                         contains \
                         represents \
                         a \
                         an \
                         the
ALWAYS_DETAILED_SEC    = NO
INLINE_INHERITED_MEMB  = NO
FULL_PATH_NAMES        = YES
STRIP_FROM_PATH        = 
STRIP_FROM_INC_PATH    = 
SHORT_NAMES            = NO
JAVADOC_AUTOBRIEF      = NO
QT_AUTOBRIEF           = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS           = YES
SEPARATE_MEMBER_PAGES  = NO
TAB_SIZE               = 4
ALIASES                = 
TCL_SUBST              = 
OPTIMIZE_OUTPUT_FOR_C  = NO
OPTIMIZE_OUTPUT_JAVA   = NO
OPTIMIZE_FOR_FORTRAN   = NO
OPTIMIZE_OUTPUT_VHDL   = NO
EXTENSION_MAPPING      = 
MARKDOWN_SUPPORT       = YES
AUTOLINK_SUPPORT       = YES
BUILTIN_STL_SUPPORT    = NO
CPP_CLI_SUPPORT        = NO
SIP_SUPPORT            = NO
IDL_PROPERTY_SUPPORT   = YES
DISTRIBUTE_GROUP_DOC   = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING            = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS  = NO
TYPEDEF_HIDES_STRUCT   = NO
LOOKUP_CACHE_SIZE      = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL            = YES
EXTRACT_PRIVATE        = NO
EXTRACT_PACKAGE        = NO
EXTRACT_STATIC         = NO
EXTRACT_LOCAL_CLASSES  = YES
EXTRACT_LOCAL_METHODS  = NO
EXTRACT_ANON_NSPACES   = NO
HIDE_UNDOC_MEMBERS     = NO
HIDE_UNDOC_CLASSES     = NO
HIDE_FRIEND_COMPOUNDS  = NO
HIDE_IN_BODY_DOCS      = NO
INTERNAL_DOCS          = NO
CASE_SENSE_NAMES       = NO
HIDE_SCOPE_NAMES       = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES     = YES
SHOW_GROUPED_MEMB_INC  = NO
FORCE_LOCAL_INCLUDES   = NO
INLINE_INFO            = YES
SORT_MEMBER_DOCS       = YES
SORT_BRIEF_DOCS        = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES       = NO
SORT_BY_SCOPE_NAME     = NO
STRICT_PROTO_MATCHING  = NO
GENERATE_TODOLIST      = YES
GENERATE_TESTLIST      = YES
GENERATE_BUGLIST       = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS       = 
MAX_INITIALIZER_LINES  = 30
SHOW_USED_FILES        = YES
SHOW_FILES             = YES
SHOW_NAMESPACES        = YES
FILE_VERSION_FILTER    = 
LAYOUT_FILE            = 
CITE_BIB_FILES         = 
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT                  = List.txt \
                         test.cpp
INPUT_ENCODING         = UTF-8
FILE_PATTERNS          = 
RECURSIVE              = NO
EXCLUDE                = 
EXCLUDE_SYMLINKS       = NO
EXCLUDE_PATTERNS       = 
EXCLUDE_SYMBOLS        = 
EXAMPLE_PATH           = 
EXAMPLE_PATTERNS       = *
EXAMPLE_RECURSIVE      = NO
IMAGE_PATH             = 
INPUT_FILTER           = 
FILTER_PATTERNS        = 
FILTER_SOURCE_FILES    = NO
FILTER_SOURCE_PATTERNS = 
USE_MDFILE_AS_MAINPAGE = 
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER         = NO
INLINE_SOURCES         = NO
STRIP_CODE_COMMENTS    = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION    = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS        = YES
USE_HTAGS              = NO
VERBATIM_HEADERS       = YES
CLANG_ASSISTED_PARSING = NO
CLANG_OPTIONS          = 
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING   = YES
MACRO_EXPANSION        = YES
EXPAND_ONLY_PREDEF     = NO
SEARCH_INCLUDES        = YES
INCLUDE_PATH           = .
INCLUDE_FILE_PATTERNS  = 
PREDEFINED             = 
EXPAND_AS_DEFINED      = 
SKIP_FUNCTION_MACROS   = NO
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES               = 
GENERATE_TAGFILE       = 
ALLEXTERNALS           = NO
EXTERNAL_GROUPS        = YES
EXTERNAL_PAGES         = YES
PERL_PATH              = /usr/bin/perl

好像有人问过这个问题here and that the answer, provided by spyderfreek from Doxygen manual是:

...the preprocessor parses, but not actually includes code when it encounters a #include (with the exception of #include found inside { ... } blocks).

因此,代码示例应为:

#include <iostream>

#define LIST \
    TEST(CLASS_A, A) \
    TEST(CLASS_B, B) \
    TEST(CLASS_C, C) \
    TEST(CLASS_D, D) \
    TEST(CLASS_E, E)

namespace God {
    class Mother
    {

        public:
            void print(void) { std::cout << "Hello\n";}
    };
}

#define TEST(X,Y) class Child_##Y : public Mother {};
namespace God {
    #include "List.txt" // using #include directive instead of #define LIST
    //LIST
}
#undef TEST

int main(int argc, char * argv[])  
{
    #define TEST(X,Y) Child_##Y My_##X; My_##X.print();
    #include "List.txt" // using #include directive instead of #define LIST
//LIST
    #undef TEST
}

生成所需的文档。