Documenting ``C++''

Next: Documenting bison files  Prev: Setup and configuration

Many ``C++'' elements may be documented: classes, methods, functions, template classes and functions, typedefs, enums, global variables, nested types, friend and using declarations, anonymous unions and preprocessor defines. A ``C++'' auto comment summary lines start with 3 slashes, and elaboration lines with 2,

/// summary line1
/// summary line 2
/// ...
//  elaborate line1
//  ...
For example,

/// this is class X
//  more on class X

class X {
public:
  /// first member
  void f(int k);

  ...
};

///
typedef unsigned int uint;
A non comment or an empty line terminate an auto comment. However you may place a ``C++'' comment between an auto comment and element. For example,

/// this is f
//  more on f

//  low level f issues.

void f(int x);

Referencing special cases

Referencing overloaded functions

To reference an overloaded function, you need to specify it's full signature.

 @ref{ReferencesTable::addTop(ostream&,const char*,FileInfo const&)}
addTop
 @ref{ReferencesTable::addTop(const char*,FileInfo const&,uint)}
addTop
Note that types have to be typed exactly as they appeared in function declaration in the ``C++'' source, with one space only wherever necessary. In addition `@ref{ReferencesTable::addTop}' will reference the first overloaded function.

Referencing templates

To reference a template class, use Svec<> or Svec. For a member, use Svec<>::insert.

To reference a template function, use del<> or del<>(vector<T*>*). Use del<>(vector<char*>*) to reference a template specification.

Linking virtual functions

d4c&b handling of virtual functions is not as easy as one would like. To understand the current compromise, it is necessary to understand the problem first.

In many cases documentation of an overriding virtual function is the same (or contains) the documentation of that function it replaces in the base class. Keeping 2 (or more) identical copies of the same documentation is bad for the usual reason. d4c&b can't do the copying because there is no guarantee that documentation for the two classes is generated at the same time.

d4c&b instead provides a one click access to the base documentation from the derived class, by hyper-linking the virtual keyword. (for example, see FileEntries::FreeComment::ref).

To do the above, one must

  1. Explicitly specify the virtual keyword in the derived class.
  2. Insure that type signature of the two functions is identical (excluding arguments names).
  3. Specify the base class with a `@virtual' declaration.

    A `@virtual' declaration specifies the base class for virtual functions following it. For example

    ///
    class X {
      /// f documentation
      virtual void f(int i);
    };
    
    ///
    class Y : X {
      ...
    };
    
    ///
    class Z : public Y {
      //@virtual X
    
      ///
      virtual void f(int i);
    };
    
    The @virtual specification may be omitted when the class is derived directly from exactly one base class. For example

    ///
    class X {
      /// f documentation
      virtual void f(int i);
    };
    
    ///
    class Y : public X {
      ///
      virtual void f(int i);
    };
    

``C++'' limitation

Parsing ``C++'' is hard enough even for a compiler, and d4c&b definitely does not wish to become one. d4c&b parses only auto documented elements (and so may be unaware of some types), and uses source code as-is and not the preprocessor output. As a result, there are restriction on what d4c&b can parse. I find those reasonable, but your mileage may vary.

In some cases it is possible to work around problems by wrapping ``C++'' code with a pair of `/*@*/'. Any such code is discarded by d4c&b. See below for examples.

No ``C++'' preprocessor macros in elements

Since d4c&b does not invoke the preprocessor, using macros in an element baffles d4c&b syntax parser. When you need such a feature, you can either hide the macro call or use @special as a last resort.

For example,

friend bool operator==  /*@*/ __STL_NULL_TMPL_ARGS /*@*/ (const map&, const map&);

Functions prototypes.

A function prototype should contain arguments names, which should be the last token. For example

///
void f(const char* x);
Whenever you have a complex type, introduce a typedef (which I find helpful in any case). An argument name may be omitted when it is trivial to deduce it's absence,

  1. when type ends with a `*' or `&'
  2. when type is a single word
  3. when there is no name, (`void' or `...')

Typedef parsing.

d4c&b can parse only several forms of typedef declarations,

Finding where an element ends

d4c&b expects a ``C++'' element to end with one of the following characters: `;' `:' or `{'. When this is not the case, you need to help d4c&b by placing the special ``C'' style comment `/*@end*/' where element ends, or hide the code.

For example, when you use g++ naming results extension.

///
String
X::f(void) /*@end*/
  return s;
{
 ...
}

or

///
String
X::f(void)
/*@*/ return s; /*@*/
{
 ...
}

const in prototype definitions

In a function prototype, put a const on the argument before the name. For example, `f(int const x);' [1].

This is the only way that d4c&b, which doesn't parse types, can tell that the const applies to the argument and remove it when constructing the signature. (`f(int)' in the example).

Ranking of references in a ``C++'' class

When an ambiguous reference is inside a class, class context guides the resolution as well. Class members rank higher than non members, a member of an enclosing class is next and so on.

///
float x;

///
class X {
  ///
  int x;

  /// @ref{x}
  void f(void);
};
The reference will pick X::x, just like ``C++'' does.

In addition, d4c&b prefers a class name over a constructor, so that @ref{X} resolve to class X even when X has a constructor. To reference a constructor, use @ref{X::X}.

Special elements

When d4c&b can't parse an element declaration, you can use a the @special directive, a last resort hack. For example,

/// Set debug topic from command in topic.
    
//@special setDebug $;

extern bool LIBFNAME(setDebug) (const char* topic);
The @special directive is placed immediately before the element, and specifies element name and where element ends. The end specification can simply specify the element suffix (above, this may be `@special setDebug topic)'), or specify characters beyond the element end. In the latter case, a `$' marks the end of the element so that those extra characters are removed from the element description.


1. It is true that it matters only if d4c&b needs to generate the function signature, which happens when f is overloaded