为何Doxygen会生成仅私有使用的实例化模板类型文档?
Doxygen生成私有模板实例化文档的冗余问题
我发现Doxygen生成的文档里,大量出现仅在私有成员变量中使用的模板实例化描述,这些实例从未出现在库的公开API里,导致文档冗余。想弄清楚:
- 这是Doxygen的bug吗?
- 这类文档存在合理性吗?
- 如果合理,有没有配置可以移除这些类的文档?
复现用极简头文件
#ifndef TEST_H #define TEST_H /** An example templated class */ template<typename T> class MyTemplatedClass { public: /** Constructor */ MyTemplatedClass() {/* empty */} private: T _t; }; /** A templated subclass of the example templated class */ template<typename T> class MyTemplatedSubclass : public MyTemplatedClass<T> { public: /** Constructor */ MyTemplatedSubclass() {/* empty */} private: T _t; }; /** Some other class */ class SomeOtherClass { public: SomeOtherClass() {/* empty */} private: MyTemplatedSubclass<int> _mtci; // 注意这些对调用代码不可见! MyTemplatedSubclass<float> _mtcf; }; #endif
Doxygen配置差异(相对于默认1.9.6配置)
Jeremys-Mac-mini-2:crap jaf$ doxygen -x ./test.dox # Difference with default Doxyfile 1.9.6 (4586b5cfaa3d46d51f6a51882951d15644c49edf) PROJECT_NAME = TEST OUTPUT_DIRECTORY = . ABBREVIATE_BRIEF = NO INLINE_INHERITED_MEMB = YES FULL_PATH_NAMES = NO JAVADOC_AUTOBRIEF = YES TAB_SIZE = 8 TYPEDEF_HIDES_STRUCT = YES EXTRACT_ALL = YES CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = YES WARN_NO_PARAMDOC = YES WARN_AS_ERROR = YES INPUT = . FILE_PATTERNS = *.h RECURSIVE = YES EXAMPLE_PATTERNS = SOURCE_BROWSER = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES HTML_TIMESTAMP = YES MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest LATEX_CMD_NAME = latex PDF_HYPERLINKS = NO USE_PDFLATEX = NO GENERATE_RTF = YES GENERATE_MAN = YES GENERATE_XML = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES INCLUDE_PATH = . GENERATE_TAGFILE = test.tag HAVE_DOT = YES COLLABORATION_GRAPH = NO
意外输出截图

问题解答
1. 这不是Doxygen的bug
这种行为是设计使然,不是bug。你当前设置了EXTRACT_ALL = YES,这个配置会让Doxygen提取所有能识别的代码实体,包括那些仅在私有成员里引用的模板特化。
2. 这类文档的合理性
从代码完整性角度,Doxygen认为这些模板实例是代码内部依赖的一部分,记录它们能帮助理解类的实现细节。但对于库的公开API文档来说,这些内容完全是冗余的——用户根本不需要关心库内部用了什么私有类型。
3. 移除冗余文档的几种方案
方案一:调整提取核心配置(推荐)
把EXTRACT_ALL = YES改成EXTRACT_ALL = NO,然后只给你想要对外公开的API添加Doxygen注释(用/** ... */格式)。这是最规范的做法,只生成你明确标记的公开内容,从根源上避免冗余。
如果不想完全关闭EXTRACT_ALL,可以搭配设置:
EXTRACT_PRIVATE = NO EXTRACT_PRIV_VIRTUAL = NO
这会过滤掉私有成员相关的实体,包括它们引用的模板实例,但注意这也会隐藏其他私有内容。
方案二:排除特定符号
直接在Doxyfile里指定要排除的模板特化:
EXCLUDE_SYMBOLS = MyTemplatedSubclass<int>,MyTemplatedSubclass<float>
这种方式精准,但如果私有模板实例很多,手动维护这个列表会很麻烦。
方案三:用注释标记隐藏内部内容
在私有成员的注释里添加@internal,告诉Doxygen这是内部内容,不要生成文档:
private: /** @internal */ MyTemplatedSubclass<int> _mtci; /** @internal */ MyTemplatedSubclass<float> _mtcf;
或者用条件块包裹整个私有区域:
private: @cond INTERNAL MyTemplatedSubclass<int> _mtci; MyTemplatedSubclass<float> _mtcf; @endcond
然后在Doxyfile里添加:
ENABLED_SECTIONS = !INTERNAL
方案四:隐藏无文档实体
设置:
HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES
但这个方案对你的场景效果有限,因为你的模板基类本身有注释,Doxygen还是会生成它们的实例化文档。
内容的提问来源于stack exchange,提问作者Jeremy Friesner
相关产品推荐
相关产品推荐

