【问题标题】:Doxygen complains about recursive C++ classDoxygen 抱怨递归 C++ 类
【发布时间】:2016-01-08 08:38:37
【问题描述】:

我有一个实现欧几里得算法(优化版本)的简单递归模板。 Doxygen 抱怨它:

/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 >!

我很惊讶为什么这是一个投诉/警告。我认为递归类型是常见且合法的。它也是许多递归模板之一,但只有一个 doxygen 抱怨。 令我惊讶的是,我只发现了 doxygen 错误检测递归的类似问题。

如果你有兴趣,这里是代码:

/**
 * 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};
};

【问题讨论】:

  • Doxygen 没有完整的 C++ 解析器。所以它可能会使有效的 C++ 代码出错。当使用解析有效 C++ 代码的 Clang 解析器时,这可能会改变。
  • 谢谢,我不知道这个选项存在。我尝试使用 clang 支持重新编译 doxygen 并在配置中激活它(现在,文档构建的第一阶段需要更长的时间),但递归类警告仍然存在。 :(
  • Doxygen 1.7.4 已经提出了同样的问题:stackoverflow.com/questions/5163478/… 我猜你使用的是最新的 Doxygen 1.8.10?可能最好提交一个错误。至少使用 Clang 解析器应该可以弄清楚递归。
  • @usr1234567 我之前发现过,但我认为情况不一样。我有一个自递归的例子,那只是命名冲突。

标签: c++ templates doxygen


【解决方案1】:

这个结构确实超出了 doxygen 的解析能力。

由于该类的用户不知道它是否以递归方式实现,因此您可以使用以下解决方法:

/**
 * 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};
};

【讨论】:

  • 我不喜欢对代码这样做,但我认为文档输出会很漂亮。所以我想我会选择这个。感谢您抽出宝贵时间!
【解决方案2】:

如果你事先声明模板有什么不同吗?在定义点上,唯一可能的基类确实是递归的。我会像这样组织代码,不仅仅是为了让 Doxygen 开心,还因为我还先用基本案例建立了数学归纳和递归关系:

// 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>
{
};

【讨论】:

  • 不,没有区别。如果确实如此,我会感到惊讶。
【解决方案3】:

默认情况下,doxygen 没有完整的 C++ 解析器。所以它可能会使有效的 C++ 代码出错。

由于doxygen 1.8.4configure doxygen 可以使用 Clang 中的 C++ 解析器,它应该可以解析大部分真实世界的 C++ 代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-02
    • 2023-02-10
    • 2011-01-08
    • 1970-01-01
    • 2020-04-20
    • 2015-07-02
    相关资源
    最近更新 更多