2010-08-08 137 views
19

我记录它使用的元编程严重,例如一些代码:C++元编程Doxygen文档

template<rysq::type A, rysq::type B, rysq::type C, rysq::type D, class Transform> 
struct Kernel<meta::braket<A,B,C,D>, Transform, 
       typename boost::enable_if< 
        quadrature<meta::braket<A,B,C,D>, Transform> >::type> 
: Eri <Transform> { 

什么是使用doxygen的记录这类结构的好办法?

+0

我认为你需要编写适当的文档,使用文字处理器。如果我遇到了这种常见的doxy生成的文档(不管多加多少注释),我想我可能会说“不,谢谢”。但是,我可能会这样说:-) – 2010-08-08 17:11:54

+1

这正是我在C++中远离模板元编程的原因。这很荒谬。 – You 2010-08-08 17:17:09

+9

@你有没有更好的方式去做,而不是任何语言 – Anycorn 2010-08-08 17:48:19

回答

8

使用预处理器宏。下面是the not-yet-official Boost.XInt library一个例子(目前排队等待审核列入升压):

#ifdef BOOST_XINT_DOXYGEN_IGNORE 
    // The documentation should see a simplified version of the template 
    // parameters. 
    #define BOOST_XINT_INITIAL_APARAMS ... 
    #define BOOST_XINT_CLASS_APARAMS ... 
    #define BOOST_XINT_CLASS_BPARAMS other 
    #define BOOST_XINT_APARAMS ... 
    #define BOOST_XINT_BPARAMS other 
#else 
    #define BOOST_XINT_INITIAL_APARAMS \ 
     class A0 = parameter::void_, \ 
     class A1 = parameter::void_, \ 
     class A2 = parameter::void_, \ 
     class A3 = parameter::void_, \ 
     class A4 = parameter::void_, \ 
     class A5 = parameter::void_ 
    #define BOOST_XINT_CLASS_APARAMS class A0, class A1, class A2, class A3, \ 
     class A4, class A5 
    #define BOOST_XINT_APARAMS A0, A1, A2, A3, A4, A5 
    #define BOOST_XINT_CLASS_BPARAMS class B0, class B1, class B2, class B3, \ 
     class B4, class B5 
    #define BOOST_XINT_BPARAMS B0, B1, B2, B3, B4, B5 
#endif 

使用#define d宏名代替模板参数,到处都需要他们,就像这样:

/*! \brief The integer_t class template. 

This class implements the standard aribitrary-length %integer type. 

[...lots more documentation omitted...] 
*/ 
template<BOOST_XINT_INITIAL_APARAMS> 
class integer_t: virtual public detail::integer_t_data<BOOST_XINT_APARAMS>, 
    public detail::nan_functions<detail::integer_t_data<BOOST_XINT_APARAMS>:: 
    NothrowType::value, // ...lots more base classes omitted... 
{ 
    // ...etcetera 

并把这样的诗句中的Doxyfile:

PREDEFINED    = BOOST_XINT_DOXYGEN_IGNORE 

EXPAND_AS_DEFINED  = BOOST_XINT_INITIAL_APARAMS \ 
         BOOST_XINT_CLASS_APARAMS \ 
         BOOST_XINT_CLASS_BPARAMS \ 
         BOOST_XINT_APARAMS \ 
         BOOST_XINT_BPARAMS 

结果是Doxygen的看到无论是“...”或‘其他’为模板参数,编译器会看到真实的。如果您在课程本身的文档中描述了模板参数,那么图书馆的用户只需要在他可能寻找他们的地方看到他们;他们会隐藏在其他地方。

作为此设计的另一个优点,如果您需要更改模板参数列表,则只需在宏定义和实际使用更改参数的功能中对其进行更改。其他一切都会自动适应。

+2

我不喜欢为doxygen添加额外的宏/代码,就好像编写文档注释是不够的。希望他们很快会支持模板。 – 2012-09-10 09:48:21

+0

对于图书馆代码来说,以一种很好的格式化方式在用户的指尖上拥有所有文档的便利性超过了我不得不添加宏和代码的个人不便。因人而异。 :-) – 2012-09-11 10:42:40

0

元编程似乎实现了数学。我会在doxygen文档中写出描述数学公式与胶乳逃逸。

+0

嗨。我可能没有说清楚,我需要记录编程逻辑,而不是数学描述。 – Anycorn 2010-08-08 17:15:15

+1

@aaa我会说你需要记录两者。 – 2010-08-08 17:18:04

+0

@aaa当您剥离C++和元编程技术时,哪些编程逻辑保留在显示的片段中? – 2010-08-08 17:27:54

3

这是我对此采取:

/// 
/// \defgroup Kernel Kernel 
/// 
/// \brief Kernel does this and that 
/// \{ 

/// \brief Kernel template class brief description. 
template<Braket,Transform,Boolean> 
struct Kernel 
{}; 

/// \brief Kernel partial template specialization brief description. 
/// 
/// More detailed description...<br> 
/// Partially specializes Kernel with meta::braket<A,B,C,D\>.<br> 
/// If quadrature<meta::braket<A,B,C,D\>, Transform\> is true then enable 
/// this algorithm, otherwise enable this other algorithm.<br> 
/// Inherits privately from template class Eri<Transform\><br> 
/// \tparam A   template parameter A of type rysq::type, documentation and concepts 
/// \tparam B   template parameter B of type rysq::type, documentation and concepts 
/// \tparam C   template parameter C of type rysq::type, documentation and concepts 
/// \tparam D   template parameter D of type rysq::type, documentation and concepts 
/// \tparam Transform template parameter class Transform documentation and concepts 
/// \see Kernel\<Braket,Transform,Boolean\> 
/// \see Eri 
/// \see meta::braket 
/// \see quadrature 
#ifdef DOXY 
// This is the documentation version 
template<A,B,C,D,Transform> 
struct Kernel<Braket,Transform,Boolean> 
#else 
// This is what gets compiled 
template<rysq::type A, rysq::type B, rysq::type C, rysq::type D, class Transform> 
struct Kernel<meta::braket<A,B,C,D>, Transform,typename boost::enable_if<quadrature<meta::braket<A,B,C,D>, Transform> >::type> 
#endif 
: Eri <Transform> {}; 

/// \} 

不要忘记添加强力霉素中的Doxygen的预处理器的预定区段。

我通常更喜欢隐藏我的代码的用户的实现细节,所以我改变了Doxygen看到的东西。 在这种情况下,您将在一个组,内核组以及类列表下找到您的所有特化项目,所有特化项目将被组合在一起,并且不会有很长且不可理解的名称。

希望它有帮助。

1

我不喜欢使用其他宏/代码的解决方案,如the swine

这是我的解决方案,它基于Doxygen生成的HTML页面的后处理。

它是一个在Linux下工作的python脚本。它在“模板类别和结构参考”页面以及“所有成员页面的列表”中取消所有“< ...>”。

在每个记录的方法仍然存在之前,侵入性较小的“模板< ...>”。

以“html /”目录(生成文档的位置)作为参数运行脚本。

#!/usr/bin/python 

import subprocess 
import sys 
import re 

def processFile(fileName): 

    f = open(fileName, 'r') 

    content = f.read(); 

    f.close(); 

    regex = re.compile("(&lt;.*&gt;).*(Template Reference|Member List)") 

    match = re.search(regex, content) 

    if not match: 
    return 

    toRemove = match.group(1) 

    regex = re.compile(toRemove) 

    content = re.sub(regex, "", content) 

    f = open(fileName, 'w') 

    f.write(content) 

    f.close() 


path = sys.argv[1] 

finder = subprocess.Popen(["find", path, "-name", "class*.html", "-o", "-name", "struct*.html"], stdout = subprocess.PIPE) 

(files, junk) = finder.communicate() 

files = files.splitlines() 

print files 

for fname in files: 
    if fname == "": 
continue 
    processFile(fname)