将特征 C++ 块表达式推回 std::vector

Posted

技术标签:

【中文标题】将特征 C++ 块表达式推回 std::vector【英文标题】:push back eigen C++ block expression into std::vector 【发布时间】:2019-08-27 06:44:42 【问题描述】:

我想创建一个实用函数,它接收一个特征矩阵和一个与矩阵行数相同大小的 std::vector。

结果应该是对输入矩阵行的行引用的 std::vector。

请参阅下面的代码 sn-p 了解如何实现该功能的简单案例:

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 ;

在上面的代码sn-p中,第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&lt;...&gt; 表达式的模板参数以推回std::vector

我也在考虑使用Eigen::ref&lt;...&gt;,但遇到了同样的问题。

【问题讨论】:

【参考方案1】:

使用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;

然后输出:

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;

这个答案不是最理想的,因为每个矩阵类型都需要定义自己的 Eigen::Ref&lt;...&gt; 向量引用类型,并且每个函数都需要重载以返回适当的类型。

【讨论】:

以上是关于将特征 C++ 块表达式推回 std::vector的主要内容,如果未能解决你的问题,请参考以下文章

SVO 特征对齐代码分析

为啥将局部变量推回 Vectorworks

如何在 C++ 中调用基类的参数化构造函数?

将指针向量元素推回非指针向量c ++时出错

C++,2D std::vector,我是不是需要明确保留和推回空向量?

找到一种方法将匹配的键和值从映射推回向量