代码之家  ›  专栏  ›  技术社区  ›  Anycorn

C++元程序设计文档

  •  19
  • Anycorn  · 技术社区  · 15 年前

    我正在记录一些大量使用元编程的代码,例如:

     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记录这种构造的好方法是什么?

    4 回复  |  直到 15 年前
        1
  •  8
  •   Head Geek    15 年前

    使用预处理器宏。下面是一个例子 the not-yet-official Boost.XInt library (目前正在排队等待审查,以纳入Boost):

    #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
    

    然后在doxy文件中放入这样的行:

    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
  •  3
  •   Julien Lebot    15 年前

    这是我的看法:

    ///
    /// \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预处理器的预定义部分添加doxy。

    我通常更喜欢对代码的用户隐藏实现细节,所以我更改了Doxygen看到的内容。 在这种情况下,您将在一个组、内核组和类列表下找到所有的专门化,所有的专门化将被分组在一起,并且不会有一个非常长且不可理解的名称。

    希望它有帮助。

        3
  •  1
  •   Community Mohan Dere    9 年前

    我不喜欢带有其他宏/代码的解决方案,例如 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)
    
        4
  •  0
  •   Peter G.    15 年前

    元编程似乎实现了数学。我将在doxygen文档中编写带有乳胶转义的描述数学公式。