Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doxygen complains about recursive C++ class

I have a simple recursive template that implements (the optimised version of) Euclid's algorithm. Doxygen complains about it:

/usr/home/kamikaze/stark/Yggdrasil/src/units/Units.hpp:335: warning: Detected potential recursive class relation between class units::euclid and base class units::euclid< Rhs, Lhs%Rhs >!

/usr/home/kamikaze/stark/Yggdrasil/src/units/Units.hpp:335: warning: Detected potential recursive class relation between class units::euclid and base class euclid< Rhs, Lhs%Rhs >!

/usr/home/kamikaze/stark/Yggdrasil/src/units/Units.hpp:335: warning: Detected potential recursive class relation between class units::euclid and base class units::euclid< Rhs, Lhs%Rhs >!

/usr/home/kamikaze/stark/Yggdrasil/src/units/Units.hpp:335: warning: Detected potential recursive class relation between class units::euclid and base class euclid< Rhs, Lhs%Rhs >!

I'm dumbfounded why that is a complaint/warning. I think recursive types are common and legal. It's also one of many recursive templates, but the only one doxygen complains about. To my surprise I've only found similar questions where doxygen was misdetecting recursion.

If you're interested, here is the code:

/**
 * Implements Euclid's algorithm to find the GCD between two integers.
 *
 * @tparam Lhs,Rhs
 *  The values to get the GCD for
 */
template <int Lhs, int Rhs>
struct euclid : euclid<Rhs, Lhs % Rhs> {
};

/**
 * Terminates Euclid's algorithm.
 *
 * @tparam Gcd
 *  The GCD to return
 * @see euclid
 */
template <int Gcd>
struct euclid<Gcd, 0> {
    /**
     * The GCD of the two original values.
     */
    static constexpr int const value{Gcd};
};
like image 205
kamikaze Avatar asked Oct 21 '25 14:10

kamikaze


2 Answers

This construct is indeed beyond doxygen's parsing capabilities.

Since it is not interesting for the user of this class to know that is it implemented in a recursive way, you could use the following workaround:

/**
 * Implements Euclid's algorithm to find the GCD between two integers.
 *
 * @tparam Lhs,Rhs
 *  The values to get the GCD for
 */
template <int Lhs, int Rhs>
struct euclid /** @cond */ : euclid<Rhs, Lhs % Rhs> /** @endcond */ {
  /** @cond */
};

template <int Gcd>
struct euclid<Gcd, 0> {
  /** @endcond
   * The GCD of the two original values.
   */
  static constexpr int const value {Gcd};
};
like image 82
doxygen Avatar answered Oct 24 '25 05:10

doxygen


Does it make a difference if you declare the template beforehand? At the point of definition, the only possible base class is indeed recursive. I would organize the code like this, not just to make Doxygen happy, but because I also set up mathematical induction and recurrence relations with the base case first:

// forward declaration
template <int Lhs, int Rhs>
struct euclid;

// base case
template <int Gcd>
struct euclid<Gcd, 0>
{
    static constexpr int const value{Gcd};
};

// recurrence relation
template <int Lhs, int Rhs>
struct euclid : euclid<Rhs, Lhs % Rhs>
{
};
like image 20
Ben Voigt Avatar answered Oct 24 '25 07:10

Ben Voigt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!