3

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};
};
kamikaze
  • 1,529
  • 8
  • 18
  • 1
    Doxygen has no full C++ parser. So it might get valid C++ code wrong. This might change, when the use Clang's parser which parses valid C++ code fine. – usr1234567 Oct 10 '15 at 13:29
  • Thanks, I wasn't aware this option exists. I tried recompiling doxygen with clang support and activating it in the configuration (the first stage of the doc build takes recognizably longer, now), but the recursive class warning remains. :( – kamikaze Oct 10 '15 at 14:00
  • The same question came already up with Doxygen 1.7.4: http://stackoverflow.com/questions/5163478/doxygen-report-potential-recursive-class-relation I guess you use the latest Doxygen 1.8.10? Probably it is the best to file a bug. At least with the Clang parser it should be possible to figure out about the recursion. – usr1234567 Oct 10 '15 at 18:19
  • @usr1234567 I found that before, but it's not the same case in my opinion. I have a case of self-recursion, that was just a naming conflict. – kamikaze Oct 12 '15 at 09:11

3 Answers3

5

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};
};
doxygen
  • 14,341
  • 2
  • 43
  • 37
  • I don't like having to do that to the code, but I think the documentation output would be beautiful. So I think I'll go with this one. Thank you for taking the time! – kamikaze Oct 10 '15 at 15:38
2

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>
{
};
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

By default doxygen has no full C++ parser. So it might get valid C++ code wrong.

Since doxygen 1.8.4 it is possible to configure doxygen to use the C++ parser from Clang, which should get parsed most of the real world C++ code.

albert
  • 8,285
  • 3
  • 19
  • 32
usr1234567
  • 21,601
  • 16
  • 108
  • 128