C ++的一个(如此之多)令人遗憾的设计缺陷是,在使用模板元编程时,基本上不可能将实现与接口分开。
我的图书馆遍布:
template <typename Ma, typename Mb>
typename boost::enable_if_c<
detail::IsMatrix<Ma>::val and detail::IsMatrix<Mb>::val and
detail::MatrixDimensionCheck<Ma,Mb>::isStaticMatch,
bool>::type
operator==(const Ma &a, const Mb &b) {
return detail::matrixEqual(a,b);
}
如果这是不可读的,我不会责怪你。如果参数是矩阵并匹配维度,那么大多数混乱只是将返回类型定义为bool
,如果它们是其他东西则是未定义的(因此依赖SFINAE来防止此运算符隐藏其他重要事物)。
由于本质上是静态类型检查函数的内容现已嵌入到我的普通C ++函数的签名中,因此这些实现内容将出现在生成的文档中。
我不希望用户必须阅读此内容。他们需要知道的是,这个函数返回bool
(通过阅读上面的内容几乎不可能知道)。在文档中,我可以用简单的英语简洁地解释该运算符只接受矩阵。
有没有办法说服Doxygen将这种类型的混乱呈现为bool
? (我假设在代码中或多或少没有办法在代码中直接清除它,但如果你能想到某些东西,欢迎这些想法)。
答案 0 :(得分:2)
嗯,我实现这一目标的唯一方法是复制函数定义而不是使用doxygen的自动功能,而是使用@fn
命令。对于你的例子,像
/*!@fn template <typename Ma, typename Mb> bool operator==(const Ma &a, const Mb &b)
* @brief My equality operator
* @note The operator is available if the types @c Ma and @c Mb match.
* It will be discarded otherwise
*/
template <typename Ma, typename Mb>
typename boost::enable_if_c<
detail::IsMatrix<Ma>::val and detail::IsMatrix<Mb>::val and
detail::MatrixDimensionCheck<Ma,Mb>::isStaticMatch,
bool>::type
operator==(const Ma &a, const Mb &b) {
return detail::matrixEqual(a,b);
}
应该这样做。
答案 1 :(得分:2)
怎么样:
#ifdef DOXYGEN
#define RETURN_TYPE(Test, Type1) Type1
#else
#define RETURN_TYPE(Test, Type1) typename boost::enable_if_c< Test, Type1 >::type
#endif
template <typename Ma, typename Mb>
RETURN_TYPE((detail::IsMatrix<Ma>::val
and detail::IsMatrix<Mb>::val
and detail::MatrixDimensionCheck<Ma,Mb>::isStaticMatch), bool)
operator==(const Ma &a, const Mb &b) { return detail::matrixEqual(a,b); }
恕我直言,它更容易阅读&amp;理解比最初的C ++代码。 请注意第一个宏参数中的双括号,以避免编译器在“Test”中的逗号上中断。如果首先重新排序返回类型(Type1),并使用变量arg宏进行测试,则可以删除它。
答案 2 :(得分:1)
重新说服Doxygen将bool
显示为返回类型:我所知道的唯一方法是Raffi的回答,并补充说你可能想要隐藏Doxygen的实际功能(有几种方法可以做到这一点)。
重新清理:这看起来像
template <typename Ma, typename Mb>
typename bool_isEqual<Ma, Mb>::type
operator==(const Ma &a, const Mb &b)
...
bool_isEqual
在适当时将所有模板类型逻辑和typedef
s type
封装到bool
。 (选择名称bool_isEqual
是因为假设其他模板函数具有返回bool
但具有其他条件的类似结构。)
如果这是一致的,那么它可能足够可读。
答案 3 :(得分:1)
我发现以下方法非常明确:
///@cond .... ///@endcond
在#ifdef DOXYGEN
内的源代码中放入一个简单的模板化函数声明,因此它对于正常编译是不可见的。观察:
///@cond
template <typename Ma, typename Mb>
typename boost::enable_if_c<
detail::IsMatrix<Ma>::val and detail::IsMatrix<Mb>::val and
detail::MatrixDimensionCheck<Ma,Mb>::isStaticMatch,
bool>::type
operator==(const Ma &a, const Mb &b) {
return detail::matrixEqual(a,b);
}
///@endcond
#ifdef DOXYGEN
///Documentation for your function...
template<typename Ma, typename> operator==(const Ma &a, const Mb &b);
#endif
答案 4 :(得分:-1)
我认为这可能适合你。显而易见它是一个比你更简单的例子,但是使用没有enable_if
的文档化模板函数来调用另一个“隐藏”函数的基本思想是没有记录但提供了SFINAE。
// Ignore this function in doxygen
template <typename T>
typename boost::enable_if<boost::is_unsigned<T>, bool>::type
test_hidden(T t) {
return true;
}
template <typename T>
typename boost::disable_if<boost::is_unsigned<T>, bool>::type
test_hidden(T t) {
return false;
}
// Document this function
template <typename T>
bool test(T t)
{
return test_hidden(t);
}
int main()
{
unsigned int a = 1;
int b = 0;
std::cout << test(a) << std::endl; // true
std::cout << test(b) << std::endl; // false
return 0;
}