在 Doxygen 输出中隐藏模板专业化参数

Hide Template Specialization Parameters in Doxygen Output

我正在编写一个库,它广泛使用元编程,并且具有 类 的特征,例如

/// Doxygen comments...
template<class T>
struct unit_traits<T, typename void_t<
    typename T::base_unit_type,
    typename T::conversion_ratio,
    typename T::pi_exponent_ratio,
    typename T::translation_ratio>::type>
{
    typedef typename T::base_unit_type base_unit_type;          ///< typedef documentation
    typedef typename T::conversion_ratio conversion_ratio;      ///< typedef documentation
    typedef typename T::pi_exponent_ratio pi_exponent_ratio;    ///< typedef documentation
    typedef typename T::translation_ratio translation_ratio;    ///< typedef documentation
};

然而,特化只是一个实现细节(还有其他地方使用特化来结束递归等),它使 doxygen 输出混乱,因为库用户只需要知道 unit_traits<someType>::... 可用。有没有什么方法可以隐藏文档中的专业化参数,最好不要创建虚拟文档目标?

更新

为了清楚起见,我尝试了以下方法,它们并没有隐藏专业化:

    template<class T>
    struct unit_traits
/** @cond */
        <T, typename void_t<
        typename T::base_unit_type,
        typename T::conversion_ratio,
        typename T::pi_exponent_ratio,
        typename T::translation_ratio>::type>
/** @endcond */
    {
        typedef typename T::base_unit_type base_unit_type;
        typedef typename T::conversion_ratio conversion_ratio;
        typedef typename T::pi_exponent_ratio pi_exponent_ratio;
        typedef typename T::translation_ratio translation_ratio;
    };

template<class T>
        struct unit_traits
    #ifndef DOXYGEN_SHOULD_SKIP_THIS
            <T, typename void_t<
            typename T::base_unit_type,
            typename T::conversion_ratio,
            typename T::pi_exponent_ratio,
            typename T::translation_ratio>::type>
    #endif
        {
            typedef typename T::base_unit_type base_unit_type;              
            typedef typename T::conversion_ratio conversion_ratio;                                      
            typedef typename T::pi_exponent_ratio pi_exponent_ratio;                                
            typedef typename T::translation_ratio translation_ratio;                                    
        };

根据 doxygen FAQ,您可以使用预处理器基本上让 doxygen 查看您的代码的不同版本(这是否是一个好主意是一个单独的问题)。

所以,大概你可以这样做:

/** Doxygen doc for general-form unit_traits. */
template<typename General>
class unit_traits;

现在,您可以像这样愚弄 doxygen(再次提醒,最后警告):

#ifndef DOXYGEN_SHOULD_SKIP_THIS
// Code actually being built.
template<>
class unit_traits<int>
#else // DOXYGEN_SHOULD_SKIP_THIS
/** Doxygen comment for the int case. */
class unit_traits
#endif // DOXYGEN_SHOULD_SKIP_THIS
{
....
};

您的编译器可以处理这个问题。关于 doxygen,它要么工作要么不工作——因为它不是真正有效的 C++ 代码 unit_traits 既有模板又没有,doxygen 要么买要么不买,即使买,下一个版本也可能不会。

显然,您可以这样做,但是:

#ifndef DOXYGEN_SHOULD_SKIP_THIS
// Code actually being built.
template<>
class unit_traits<int>
#else // DOXYGEN_SHOULD_SKIP_THIS
/** Doxygen comment for the int case. */
class int_unit_traits
#endif // DOXYGEN_SHOULD_SKIP_THIS
{
...
};

因为两个预处理器路径都是有效的 C++(嗯,有点),你的编译器 doxygen 应该很高兴。


警告

就我个人而言,我认为您尝试 "fool" doxygen 这一事实表明存在概念问题。大量模板化的 C++ 几乎无法记录,doxygen 在这方面做得比我在一百万年里做得更好,但它仍然存在问题。

在类似的情况下,我通常只是将一般情况和专业化的所有文档放在一般情况的 doxygen 注释中。我让 doxygen 忽略了专业化(使用预处理器),并且只是在每个说文档是一般情况下的说法上加上一个非 doxygen 评论。不可否认,这也很糟糕:-)