如何使用Doxygen记录由宏生成的类?

7
我将用宏来生成下面这种方式的类:
generator.h:
class CLASS_NAME : public parent
{
    //generate variables with names given by CLASS_VARIABLES using complicated
    //Boost.Preprocessor stuff.
};

#undef CLASS_NAME
#undef CLASS_VARIABLES

myclass.h:

#define CLASS_NAME MyClass
#define CLASS_VARIABLES (a, b, c, x, y, z)
#include "generator.h"

实际的类更加复杂,使用了各种Boost.Preprocessor宏。是否有一种方法可以通过在generator.h中添加注释来自动记录生成的类的Doxygen文档,或者生成带有文档的示例类?我尝试启用ENABLE_PREPROCESSING和MACRO_EXPANSION,但这似乎不足够。

4个回答

5

在我写作时,只要满足一些条件,doxygen就会执行完整的文件包含。来自doxygen内部文档

...预处理器在遇到#include(除了在{...}块内找到的#include之外)时解析但不实际包含代码

我通过实验发现的另一个未记录但直观的前提是,#include所在的{...}块必须本身有文档记录。例如,在以下测试文件上运行使用Boost.Preprocessor的doxygen,只要在配置文件中启用了MACRO_EXPANSION,所需的提取模式设置为“所有实体”,并且正确设置了boost文件夹的INCLUDE_PATH,则将为结构FOO::AFOO::BFOO::C生成条目:

#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/tuple/elem.hpp>

#define STRUCTS (A, B, C)

namespace FOO {
    #define BOOST_PP_LOCAL_MACRO(n) struct BOOST_PP_TUPLE_ELEM(3,n, STRUCTS) {};
    #define BOOST_PP_LOCAL_LIMITS (0,2)
    #include BOOST_PP_LOCAL_ITERATE()
}

然而,如果将结构体放在匿名命名空间中,删除FOO将导致没有文档。因此,如果您可以忍受在显式命名空间内#include "generator.h",它将起作用。

我不确定你关于记录 #include 指令所在块的第二个前提条件。我认为这是不必要的。 - Heyji

2
http://www.doxygen.nl/manual/docblocks.html中,"其他地方的文档"段落是什么意思?
/*! \class CLASS_NAME
    \brief An auto generated class

    A more detailed class description.
*/

/*! \fn CLASS_NAME::CLASS_NAME()
    \brief Default constuctor
*/

嗯,这似乎不起作用。我无法像你提出的那样精确地执行它,因为我的实际类名是CLASS_NAME和字符串的连接。我尝试使用\class MyClass,但是似乎没有生成任何文档。难道是因为Doxygen搜索MyClass但找不到它吗?我还尝试过\class CLASS_NAMEConcatenatedString,但同样没有结果。 - AbuBakr
那么,也许需要为该类添加前向声明。 - Fantastory

1

这样行不通。Doxygen预处理器并没有真正执行完整的文件包含(它只在包含的文件中查找宏定义;否则,ENABLE_PREPROCESSING指令将完全无用!)。因此,#include "generator.h"没有任何效果。

如果您物理上用所包含文件的内容替换#include指令,则可以解决问题。(我知道这并不是很有用)。

另一种方法是修改您的文件如下:

generator.h:

#define DEFCLASS class CLASS_NAME : public parent \
{ \
   ... whatever ... \
};

myclass.h:

#define CLASS_NAME MyClass
#define CLASS_VARIABLES (a, b, c, x, y, z)
#include "generator.h"
DEFCLASS

但是如果您在源文件中使用DEFCLASS超过一次,这将无法正常工作(可能是Doxygen的错误/缺陷)。


我认为我不能使用你的修改,因为我在我的类定义中再次使用了 #include#define。我可以将 #define 放在类的前面,但我不认为我能够摆脱 #include... - AbuBakr
如下所述,如果#include位于{ }块内部,则包含将起作用。 - Heyji

1
我建议将生成的类放在单独的头文件中,并只记录头文件。在最好的情况下,生成的类更多地是实现细节。
另一个选择是编写脚本。可以使用您喜欢的脚本语言,或者像cheetah这样的工具也不错。
我猜测您的生成器看起来很简单,可以生成样板或特性等内容。
GENERATE_CLASS(Foo);
GENERATE_CLASS(Bar);

类似这样的东西对于 grep 来说是很合理的内容。


我不确定我是否正确理解了你的第一段。你是建议创建一个包含预处理器输出的示例头文件吗?如果可以自动创建此头文件,那么这将是一个好的解决方案。由于我使用cmake,这可能是可行的。然后,我可以使用sweetrommie的建议在generator.h中创建注释。 - AbuBakr
在第一段中,我并不是指生成的输出。我是指将代码分离到自己的头文件中。然后提供一般用途的执行摘要,而不是类的具体细节。另一个选项是创建一个纯虚拟接口,所有生成的类都“继承”(无论是字面上还是模仿)并记录下来。如果您想要生成某些内容,我建议使用Cheetah。 - Tom Kerr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接