templates - 将特征 C++ 块表达式推回 std::vector
问题描述
我想创建一个实用函数,它接受一个特征矩阵和一个与矩阵行数相同大小的 std::vector。
结果应该是对输入矩阵行的行引用的 std::vector。
有关如何实现该函数的简单案例,请参见下面的代码片段:
template<typename RowReferenceType, typename MatrixType>
std::vector<RowReferenceType> getReferencedRows(MatrixType& matrix, const std::vector<bool>& addRow)
{
assert(matrix.rows() == addRow.size());
std::vector<RowReferenceType> rows;
for(size_t i = 0; i < addRow.size(); ++i)
{
if(addRow[i])
rows.push_back(matrix.row(i));
}
return rows;
}
由于类型推导失败等多种原因,上面的代码将无法编译。我们可以指定类型,但我希望函数的调用者只在函数的参数中指定矩阵和 std::vector。
以下是该函数的预期输出示例:
Eigen::MatrixXd V(4, 3);
V <<
0.5, 0.3, 0.2,
0.46, 0.88, 0.99,
0.46, 0.88, 0.99,
0.46, 0.88, 0.99;
std::vector<bool> referenceRow{ false, true, false, true};
auto rows = getReferencedRows<Eigen::Block<Eigen::MatrixXd>, Eigen::MatrixXd>(V, referenceRow);
for(auto& r : rows)
{
r = Eigen::RowVector3d{ 0,0,0 };
}
在上面的代码片段中,第 1 行和第 3 行将被更改为零向量V
,因此直接由赋值表达式修改r = Eigen::RowVector3d{ 0,0,0 };
这是我第一次尝试让模板类型推导做更多工作:
template<typename Scalar, int Rows, int Cols>
std::vector<Eigen::Block<Eigen::Matrix<Scalar, Rows, Cols>, Rows, Cols>> getReferenceRows(Eigen::Matrix<Scalar, Rows, Cols>& matrix, const std::vector<bool>& addRow)
{
assert(matrix.rows() == addRow.size());
std::vector<Eigen::Block<Eigen::Matrix<Scalar, Rows, Cols>, Rows, Cols>> rows;
for(size_t i = 0; i < addRow.size(); ++i)
{
if(addRow[i])
{
auto block = matrix.row(i);
rows.push_back(block);
}
}
return rows;
}
上面代码的问题是我仍然无法推断出Eigen::Block<...>
表达式的模板参数以推回std::vector
.
我也在考虑使用Eigen::ref<...>
,但我遇到了同样的问题。
解决方案
Solved indirectly by using Eigen::Ref
template<typename Scalar, int Rows, int Cols>
using EigenReferenceRowVector = Eigen::Ref<Eigen::Matrix<Scalar, Rows, Cols>, 0, Eigen::InnerStride<>>;
template<typename Scalar, int Rows, int Cols>
std::vector<EigenReferenceRowVector<Scalar, 1, Cols>> getReferencedRows(Eigen::Matrix<Scalar, Rows, Cols>& matrix, const std::vector<bool>& addRow)
{
std::vector<EigenReferenceRowVector<Scalar, 1, Cols>> rows;
assert(addRow.size() == matrix.rows());
for(int i = 0; i < addRow.size(); ++i)
{
if (addRow[i])
rows.push_back(matrix.row(i));
}
return rows;
}
And output:
Eigen::MatrixXd V(4, 3);
V <<
0.5, 0.3, 0.2,
0.46, 0.88, 0.99,
0.46, 0.88, 0.99,
0.46, 0.88, 0.99;
std::vector<bool> referenceRow{ false, true, false, true };
auto rows = getReferencedRows(V, referenceRow);
for(auto& r : rows)
{
r = Eigen::RowVector3d{ 0,0,0 };
}
std::cout << V;
This answer is suboptimal as each matrix type needs to have its own Eigen::Ref<...>
vector reference type defined and each function overloaded to return the appropriate type.
推荐阅读
- go - 分析全局变量
- nginx - 为什么 nginx 抱怨这里不允许使用“proxy_read_timeout”指令?
- flutter - setState() 是否被 try & catch 忽略?
- amazon-web-services - 当我尝试连接到 ec2 时,没有可用的受支持的身份验证方法。如何连接到 AWS 实例?
- python - 第二个打印语句没有在给定的代码中运行?
- javascript - 如何停止向 django formset 中的第一个表单添加删除按钮?
- c# - 动态(以编程方式)创建的图块通过计时器更改其 isEnabled 属性
- python - 为什么我的代码似乎不适用于奇数
- c++ - QFileSystemModel 未在 Win 10 上更新
- flutter - Flutter:微信资产选择器。将语言更改为英语