我正在建立一个静态类型的矩阵,其中所有与矩阵的操作都经过类型检查。但是,当我想做一些基于给定数字修改矩阵的问题时,我遇到了问题。
例如,添加一列很简单:
template<int A, int B>
Matrix<A,B+1> addOneCol(Matrix<A,B> m1) {
return Matrix<A,B+1>();
}
但是,添加N列要困难得多。由于不可能使用具有分支的函数进行类型检查,而分支的返回类型不是预期的(即使分支条件可以保证),所以我只能考虑一种递归方法:
template<int A, int B, int Z>
Matrix<A,B+1> addZCols(Matrix<A,B> m1) {
return addOneCol(m1);
}
template<int A, int B, int Z>
Matrix<A,B+Z> addZCols(Matrix<A,B> m1) {
return addOneCol(addZCols<A,B,Z-1>(m1));
}
template<int A, int B>
Matrix<A,B+1> addOneCol(Matrix<A,B> m1) {
return Matrix<A,B+1>();
}
但是,这会使返回类型中的
addZCols
重载,这是不允许的,并导致错误,导致调用addZCalls
模棱两可,并且无法选择2个候选者之一。我想要的是B+1
的版本仅作为基本案例,可以说是Z=1
。关于如何进行这项工作或采用其他方法的想法吗?
最佳答案
可能有一种更有效的方法,但是使用您提出的递归解决方案,SFINAE可用于消除模板功能的两个版本的歧义。
#include <type_traits>
template <int A, int B>
struct Matrix {
constexpr int rows() const { return A; }
constexpr int cols() const { return B; }
int data;
};
template<int Z, int A, int B, std::enable_if_t<Z == 0, int> = 0>
Matrix<A, B> addZCols(Matrix<A,B> m1) {
return m1;
}
template<int Z, int A, int B, std::enable_if_t<Z != 0, int> = 0>
Matrix<A,B+Z> addZCols(Matrix<A,B> m1) {
return addOneCol(addZCols<Z-1, A, B>(m1));
}
template<int A, int B>
Matrix<A,B+1> addOneCol(Matrix<A,B> m1) {
return Matrix<A,B+1>();
}
int main() {
Matrix<2, 2> m1;
auto m2 = addZCols<3>(m1);
static_assert(m2.rows() == 2, "check rows");
static_assert(m2.cols() == 5, "check cols");
return 0;
}
为了清楚起见,我也将递归限制偏移了一个,并对
addZCols
的模板参数进行了重新排序以使其调用起来更好,但是它与原始签名的作用相同。
关于c++ - 模板函数的歧义递归定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61392024/